The CDOEXM Object Model


Figure 18-2 depicts the object model for CDOEXM. CDOEXM does not have many methods and properties, so the object model is easy to learn. The methods and properties make the most common administrative tasks easy to automate. To add a reference to CDOEXM in Microsoft Visual Basic, you just need to include the Microsoft CDO for Exchange Management Library (CDOEXM.DLL). You get this library wherever you install Exchange Server or the Exchange System Manager. The code can run either client-side or server-side as long as you have this object library on your machine.

click to expand
Figure 18-2: The CDOEXM object model

What About ADSI?

CDOEXM and Active Directory Services Interfaces (ADSI) are tightly interwoven. You do not use CDOEXM to create Windows accounts in Active Directory ”you use ADSI. However, to mailbox-enable those Windows accounts, you can use CDOEXM. To access advanced properties in Active Directory, you also use ADSI. If you are going to use CDOEXM, you should be proficient with ADSI as well. Also, you should know the ADSI tools, such as ADSI Edit and LDP (which we discussed in Chapter 13), because they will help you investigate and configure Active Directory settings. One word of caution, though: do not try to set Exchange settings in Active Directory yourself for complex operations such as creating storage groups. Use CDOEXM to do the work because certain properties and processes must be implemented to ensure that the system does not become unstable or is not forced into an inconsistent state.

Accessing Exchange Server Information

When you write code, you'll generally want to understand what kind of information about an Exchange server you can access programmatically. CDOEXM provides the ExchangeServer object, which has properties that return the version number, storage groups, and directory server that the Exchange server uses. Table 18-1 lists the properties of the ExchangeServer object. This object has no methods.

Table 18-1: Properties of the ExchangeServer Object

Property

Description

DataSource

Retrieves the IDataSource2 interface. From this interface, you can open a connection to an Exchange server by passing the name of the server to the Open method of the DataSource object.

DaysBeforeLogFileRemoval

Specifies the number of days before Exchange Server log files will be removed from the server. Please refer to the Exchange Server documentation for the types of log files that Exchange Server uses.

DirectoryServer

Returns the fully qualified domain name (FQDN) of the Active Directory domain controller that the Exchange server communicates with. This is a read-only property.

ExchangeVersion

Returns the version of Exchange Server that is running. An example of output from this property is Version 6.5 (Build 6944) for the Release to Manufacturer (RTM) version of Exchange 2003.

Fields

Returns the Fields collection. The fields you get back are mostly fields from Active Directory such as heuristics , whenCreated , whenChanged , and objectClass .

MessageTrackingEnabled

A Boolean that specifies whether message tracking is enabled on the Exchange server. For more information on message tracking, refer to the Exchange Server documentation.

Name

Returns the name of the Exchange server. This is a read-only property.

ServerType

Returns a CDOEXMServerType enumeration. There are only two types: CDOEXMBackEnd and CDOEXMFrontEnd . Front-End (FE) and Back-End (BE) Exchange servers are discussed in detail in the Exchange documentation.

StorageGroups

Returns an array that lists the Active Directory path to all storage groups on the server. You can then use these Active Directory paths with the StorageGroup object to open a specific storage group .

SubjectLogging

A Boolean that specifies whether subject logging is enabled.

The sample file named EMOSample.vbp, which you can find in the book's companion content, makes this clearer. Figure 18-3 shows the user interface for the sample.

click to expand
Figure 18-3: The CDOEXM sample application

Here is some of the code from the sample that uses the ExchangeServer object to determine server-specific information:

 Dim oExchangeServer As New CDOEXM.ExchangeServer Dim arrSGs() As CDOEXM.StorageGroup      Private Sub cmdConnect_Click()     On Error GoTo errHandler:     If txtExServerName.Text = "" Then         MsgBox "You must enter a name in the Exchange Server name box!", _                vbCritical + vbOKOnly         Exit Sub     End If          If Right(txtExServerName.Text, 7) = "LDAP://" Then         'Remove the LDAP         txtExServerName.Text = Mid(txtExServerName.Text, 8)     End If          'Try to connect     oExchangeServer.DataSource.Open txtExServerName.Text          'Try to fill in Exchange Server info     FillInExchangeServerInfo          'Retrieve the storage groups     FillInStorageGroups          Exit Sub errHandler:     MsgBox "There was an error in cmdConnect_Click(). Error#" _          & Err.Number & " Description:" & Err.Description, _            vbCritical + vbOKOnly     End End Sub      Sub FillInExchangeServerInfo()     On Error GoTo errHandler     lblLogRemoval.Caption = oExchangeServer.DaysBeforeLogFileRemoval     lblDirServer.Caption = oExchangeServer.DirectoryServer     lblVersion.Caption = oExchangeServer.ExchangeVersion     lblMsgTracking.Caption = oExchangeServer.MessageTrackingEnabled     lblSubjectLogging.Caption = oExchangeServer.SubjectLoggingEnabled     lblSGCount.Caption = UBound(oExchangeServer.StorageGroups) + 1     If oExchangeServer.ServerType = cdoexmBackEnd Then         lblServerType.Caption = "Backend"     Else         lblServerType.Caption = "Frontend"     End If          Exit Sub errHandler:     MsgBox "There was an error in FillInExchangeServerInfo. Error#" _          & Err.Number & " Description:" & Err.Description, _          vbCritical + vbOKOnly End Sub 

Working with Storage Groups

The StorageGroup object allows you to work with storage groups. From this interface, you can retrieve the log file paths for the database, figure out how many databases and what types of databases are in the storage group, and create new storage groups. Table 18-2 lists the methods and properties of the StorageGroup object.

Table 18-2: Methods and Properties of the StorageGroup Object

Method or Property

Description

CircularLogging

A Boolean property that specifies whether new log entries will overwrite the oldest log entries in the file.

DataSource

Returns the IDataSource2 interface. From this interface, you can use the Open method to open a storage group by passing the Active Directory path to the storage group, or you can use the SaveTo method to create a new storage group. You can also use the Delete method to delete a storage group.

Fields

Returns the ADO Fields collection for the storage group. Most of the interesting properties are already directly exposed by the StorageGroup object, so the Fields collection is not that interesting.

LogFilePath

A string that specifies where the database transaction log files are stored.

MailboxStoreDBs

An array of strings that contains the Active Directory path to any mailbox databases in the storage group. You can then use the Open method of the DataSource property on the MailboxStoreDB object to open the mailbox database.

Name

Specifies the name of the storage group.

PublicStoreDBs

An array of strings that contains the Active Directory path to any public folder databases in the storage group. You can then use the Open method of the DataSource property on the PublicStoreDB object to open the mailbox database.

SystemFilePath

A string that specifies where database system files are stored.

Zerodatabase

A Boolean that specifies whether deleted database pages will be overwritten with zeroes when you back up the server.

MoveLogFiles

A method that takes a string that specifies the new path to move the transaction log files to.

MoveSystemFiles

A method that takes a string that specifies the new path to move the database system files to.

The StorageGroup object is straightforward. The following code shows how to use this interface. The following code from the EMOSample application opens a StorageGroup object and queries for the properties of the storage group.

 Sub FillInStorageGroups()     On Error GoTo errHandler          'Scroll through the array of storage groups and     'open each one into a SG object     arrEXSG = oExchangeServer.StorageGroups     Dim oTmpSG As CDOEXM.StorageGroup     ReDim arrSGs(UBound(arrEXSG))     For i = LBound(arrEXSG) To UBound(arrEXSG)         Set oTmpSG = CreateObject("CDOEXM.StorageGroup")         oTmpSG.DataSource.Open "LDAP://" & arrEXSG(i)         Set arrSGs(i) = oTmpSG         'Fill in the combo box         comboSG.AddItem oTmpSG.Name         Set oTmpSG = Nothing     Next          comboSG.ListIndex = 0          Exit Sub errHandler:     MsgBox "There was an error in FillInStorageGroups. Error#" & Err.Number _          & " Description:" & Err.Description, vbCritical + vbOKOnly End Sub      Sub FillInSGInfo(iIndex)     lblCL.Caption     = arrSGs(iIndex).CircularLogging     lblLFPath.Caption = arrSGs(iIndex).LogFilePath     lblMBDB.Caption   = UBound(arrSGs(iIndex).MailboxStoreDBs) + 1     lblPFDB.Caption   = UBound(arrSGs(iIndex).PublicStoreDBs) + 1     lblZeroDB.Caption = arrSGs(iIndex).ZeroDatabase     lblSFPath.Caption = arrSGs(iIndex).SystemFilePath End Sub 

Creating New Storage Groups

To create a new storage group in your system, all you do is figure out the right Active Directory path to pass to the SaveTo method of the DataSource object on the StorageGroup object. This is not difficult, but the path will be long because the location where Exchange Server stores its information in Active Directory is buried a couple of layers deep in the hierarchy. Here's an example path to a storage group reference in Active Directory:

 CN=First Storage Group,CN=InformationStore,CN=SERVERNAME,CN=Servers,CN=First Ad ministrative Group,CN=Administrative Groups,CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=DOMAIN,DC=com 

As you can see, storage groups are stored under Services, then Exchange, then your organization, then the administrative group, then the server, and finally the information store. Figure 18-4 shows this storage group object in ADSI Edit.

click to expand
Figure 18-4: The location of storage group objects in Active Directory

To create a new storage group, you just create a new StorageGroup object, generate the correct Active Directory path, and add a CN=MyStorageGroup name at the beginning. The following code creates a new storage group called MyNewSG using CDOEXM:

 Dim oNewSG As New CDOEXM.StorageGroup     oNewSG.DataSource.SaveTo "LDAP://server/CN=MyNewSG,CN=InformationStore," _         & "CN=SERVERNAME,CN=Servers,CN=First Administrative Group," _         & "CN=Administrative Groups,CN=First Organization,CN=Microsoft " _         & "Exchange, CN=Services,CN=Configuration,DC=DOMAIN, ,DC=com" 

If you do not want to hardcode the path, you can just grab an existing storage group from the ExchangeServer object and parse it to get the path. The following code from the Training application does this:

 'cut out the Storage Group name from the URL strTemp = oCDOEXMServer.StorageGroups(0) strTemp = Mid(strTemp, InStr(2, UCase(strTemp), "CN")) ' Build the URL to the StorageGroup strSGURL = "LDAP://" & oCDOEXMServer.DirectoryServer & "/CN=" _          & strFolderStoreName & "," & strTemp 

A blank storage group is an interesting beginning to your application. You'll see later in the chapter how to create a new mailbox or public folder databases in a storage group. You'll also learn how to create a folder tree. Finally, you'll see how to create a new mailbox.

Deleting Storage Groups

Deleting empty storage groups is no problem. You just open the storage group that you want to delete by using the Open method of the DataSource object on the StorageGroup object. If you find any databases in the storage group, delete them ”you cannot delete a storage group that contains any databases. Then call the Delete method of the DataSource object, as shown in the following code:

 Dim oNewSG As New CDOEXM.StorageGroup oNewSG.DataSource.Open "LDAP://SERVER/CN=MyNewSG,CN=InformationStore," _     & "CN=SERVERNAME,CN=Servers,CN=First Administrative Group," _     & "CN=Administrative Groups,CN=First Organization," _     & "CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=DOMAIN,DC=com" oNewSG.DataSource.Delete 

Working with Folder Trees

Before we talk about working with databases, let's briefly discuss how to work with public folders. If you don't plan to do anything with public folders, you can skip this section.

To create a new public folder database, you first create a new public folder tree that the database will be associated with. By having a separate tree, you can associate different databases with different public folder trees. This gives you the flexibility to build many different hierarchies of public folders for your applications. Mailbox databases do not have this requirement.

To work with folder trees, you use the FolderTree object. This interface has just three unique properties beyond the DataSource , Fields , and Name properties you saw earlier. These properties are listed in Table 18-3.

Table 18-3: Properties of the FolderTree Interface

Property

Description

RootFolderURL

Specifies the URL to the root folder in the tree. Do not expect this to be the URL to use for your applications. For example, the public folders RootFolderURL value is http://SERVER/ExAdmin/ domain.com/Public%20Folders

StoreDBs

A string array of Active Directory paths of other public store databases that contain replicas of this folder tree.

TreeType

An enumeration that specifies the type of folder tree. The three possible values are cdoexmGeneralPurpose (a non-MAPI public folder tree), cdoexmMAPI , and cdoexmNNTPOnly .

Creating a New Folder Tree

To create a new folder, you create a new FolderTree object. You set the name property on that object, and then you figure out the right Active Directory path to save your folder tree to, using the Save method of the FolderTree object's DataSource object. A typical path for a folder tree differs from that for a storage group. Here is an example path for the public folders folder tree. You would also use this path to open a folder tree.

 LDAP://SERVER/ CN=Public Folders,CN=Folder Hierarchies,CN=First Administrative Group,CN=Admini strative Groups,CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Conf iguration,DC=DOMAIN,DC=com 

The following code creates a new folder tree called MyNewFT. Note that you must use the SaveTo method and save to the Folder Hierarchies container as well as add a CN=MyNewFT to the path.

 Dim oNewSG As New CDOEXM.FolderTree oNewSG.Name = "MyNewFT" oNewSG.DataSource.SaveTo "LDAP://SERVER/CN=MyNewFT,CN=Folder Hierarchies," _     & "CN=First Administrative Group,CN=Administrative Groups," _     & "CN=First Organization,CN=Microsoft Exchange," _     & "CN=Services,CN=Configuration,DC=DOMAIN,DC=com" 

Deleting a Folder Tree

To delete a folder tree, you open the folder tree and then call the Delete method on the DataSource object for the FolderTree object. You cannot orphan public folder databases, so you must first delete the database or disassociate the database with the folder tree before attempting to delete the folder tree. The following code deletes the folder tree we created earlier:

 Dim oNewSG As New CDOEXM.FolderTree oNewSG.DataSource.Open "LDAP://SERVER/CN=MyNewFT,CN=Folder Hierarchies," _     & "CN=First Administrative Group,CN=Administrative Groups," _     & "CN=First Organization,CN=Microsoft Exchange," _     & "CN=Services,CN=Configuration,DC=DOMAIN,DC=com" oNewSG.DataSource.Delete 

Working with Public Folder Databases

You can work with two types of databases in Exchange: mailbox databases and public folder databases. We'll look at public folder databases first. When you work with public folder databases, you use the PublicStoreDB object. Table 18-4 lists the properties and methods of this interface.

Table 18-4: Properties and Methods of the PublicStoreDB Object

Element

Description

DataSource

Returns the IDataSource2 interface. From this interface, you can use the Open method to open a public folder database by passing the Active Directory path to the database or use the SaveTo method to create a new public folder database. You can also use the Delete method to delete the public folder database.

DaysBeforeGarbageCollection

Returns or sets the number of days before deleted items in the database will be permanently deleted. See the Exchange Server documentation for more information on garbage collection.

DaysBeforeItemExpiration

Returns or sets the number of days before items and folders will expire in the database.

DBPath

A read-only property that returns the file path to the database file. This file will end with the .edb extension.

Enabled

A Boolean property that specifies whether the database will be mounted at startup. A value of True means that the database will be mounted.

Fields

Returns the ADO Fields collection for the object.

FolderTree

A string property that returns or sets the Active Directory path to the folder tree associated with the public folder database.

GarbageCollectOnlyAfterBackup

A Boolean that specifies whether items that have not been backed up will be permanently deleted from the database. A value of True means that items cannot be deleted until they are backed up.

HardLimit

A property that specifies the size in kilobytes beyond which posting will be disabled.

ItemSizeLimit

A property that specifies the maximum allowable size (in kilobytes) of an item in the database.

Name

Specifies the name of the database.

SLVPath

A read-only string property that returns the path to the streaming file database. The streaming file database contains data stored in its Internet content format. For more information about the database architecture of Exchange Server, see the product documentation.

Status

A read-only property that returns a CDOEXMStoreDBStatus enumeration value that specifies whether the database is mounted. The enumeration contains four values: cdoexmOnline , cdoexmOffline , cdoexmMounting , and cdoexmDismounting .

StoreQuota

A property that specifies or returns the maximum size (in kilobytes) of the database.

Dismount

A method that dismounts the database. It takes an optional property that specifies the amount of time in seconds that the system will attempt to dismount the database.

Mount

A method that mounts the database. It takes an optional property that specifies the amount of time in seconds that the system will attempt to mount the database.

MoveDataFiles

A method that moves the data files for the database. It takes three parameters. The first is the new path for the database file. The second is the new path for the streaming files. The final parameter is optional and is a flags parameter reserved for future use.

Creating a New Public Folder Database

To create a new public folder database, you must have created your folder tree. You then create the Active Directory path to your public folder database. Next you create a PublicFolderDB object. Then you set the FolderTree property to the folder tree you created. Next you call the SaveTo method on the PublicFolderDB object with the Active Directory path. If you want to mount the database, you can then call the Mount method on the PublicFolderDB object. The following code shows how to create a new public folder database called MyNewPFDB. The folder tree MyNewFT must already exist.

 Dim oPFDB As New CDOEXM.PublicStoreDB      oPFDB.FolderTree = "LDAP://SERVER/CN=MyNewFT,CN=Folder Hierarchies," _     & "CN=First Administrative Group,CN=Administrative Groups," _     & "CN=First Organization,CN=Microsoft Exchange," _     & "CN=Services,CN=Configuration,DC=DOMAIN,DC=com"      oPFDB.DataSource.SaveTo "LDAP://SERVER/CN=MyNewPFDB,CN=MyNewSG," _     & "CN=InformationStore,CN=SERVER,CN=Servers,CN=First Administrative " _     & "Group,CN=Administrative Groups,CN=First Organization," _     & "CN=Microsoft Exchange,CN=Services,CN=Configuration," _     & "DC=DOMAIN,DC=microsoft,DC=com" oPFDB.Mount 

Deleting Public Folder Databases

To delete a public folder database, you first open the database by passing the Active Directory path to the database, and then you call the Open method on the DataSource object for the PublicFolderDB object. Next you call the Delete method on the DataSource object. The following code deletes the MyNewPFDB database:

 Dim oPFDB As New CDOEXM.PublicStoreDB oPFDB.DataSource.Open "LDAP://SERVER/CN=MyNewPFDB,CN=MyNewSG," _     & "CN=InformationStore,CN=SERVER,CN=Servers,CN=First Administrative " _     & "Group,CN=Administrative Groups,CN=First Organization," _     & "CN=Microsoft Exchange,CN=Services,CN=Configuration," _     & "DC=DOMAIN,DC=microsoft,DC=com" oPFDB.DataSource.Delete 

Creating Exchange Server Virtual Directories

When you create virtual directory entries in Internet Information Services (IIS) that point to Web files or folders that are stored in an Exchange database, IIS does not automatically add the proper Exchange ISAPI extension called Davex.dll to the virtual directory. This happens because you must create an Exchange virtual directory. If you just create a new virtual directory through Microsoft Internet Information Services (IIS), the virtual directory information will be stored in the IIS metabase, not in Active Directory. Exchange Server replicates information stored in Active Directory to the IIS metabase for creation of Exchange virtual directories. Therefore, the easiest way for you to create Exchange virtual directories programmatically is by creating them in Active Directory to begin with. Then you do not have to worry about creating the pointer to the Exchange Internet Server Application Programming Interface (ISAPI) yourself. If you want a graphical tool for creating Exchange virtual directories, use the Exchange System Manager.

Figure 18-5 shows the Exchange System Manager interface for creating a new Exchange virtual directory.

click to expand
Figure 18-5: Creating an Exchange virtual directory in the Exchange System Manager

To programmatically create the entries in Active Directory using ADSI, you must get the container called 1 under the HTTP protocols section under the Microsoft Exchange section in Active Directory. Then you must create a new entry of class msExchProtocolCfgHTTPVirtualDirectory and set its properties appropriately. The following code from the Training application does this:

 Function SetNewWeb(strComputerName, strFolderName, strDomainName,_                    strVirDirName, bAddTrainingApp)     On Error Resume Next     Dim iServer    As New CDOEXM.ExchangeServer     Dim strFHname  As String     Dim NewWeb     As IADsContainer     Dim ExchFolder As Object          Dim ADCont     As IADsContainer          Result = True          'Create an Exchange Virtual Directory so that OWA     'is the default view for the virtual directory          iServer.DataSource.Open strComputerName     Result = Result And GetFolderTreeURL(strComputerName, strFHname)          WriteLog "Getting Object: LDAP://" & iServer.DirectoryServer _            & "/CN=1,CN=HTTP,CN=Protocols," & _            Mid(iServer.DataSource.SourceURL, _                InStr(1, iServer.DataSource.SourceURL, "CN="))          Set ADCont = GetObject("LDAP://" & iServer.DirectoryServer _                          & "/CN=1,CN=HTTP,CN=Protocols," _                          & Mid(iServer.DataSource.SourceURL, _                                InStr(1, iServer.DataSource.SourceURL, "CN=")))          Set NewWeb = ADCont.Create("msExchProtocolCfgHTTPVirtualDirectory", _                                "CN=" & strVirDirName)          NewWeb.Put "HTTPPubGAL", CBool(0)     'NewWeb.Put "anonymousAccount", "IUSR_MSEX2K"     If bAddTrainingApp Then         strFolderName = strFolderName & "\trainingapplication"     End If     NewWeb.Put "folderPathname", CStr(strFolderName)     'Allow Write access in Access Flags so user can create folders     NewWeb.Put "msExchAccessFlags", CInt(535)     NewWeb.Put "msExchAuthenticationFlags", CInt(6)     NewWeb.Put "msExchBasicAuthenticationDomain", CStr(strDomainName)     NewWeb.Put "msExchDefaultLogonDomain", CStr(strDomainName)     NewWeb.Put "msExchDirBrowseFlags", -1073741794     NewWeb.Put "msExchLogonMethod", CInt(3)     NewWeb.Put "msExchLogType", CInt(0)     NewWeb.Put "msExchServerAutoStart", CBool(True)     NewWeb.Put "msExchServerRole", CInt(0)     NewWeb.Put "name", CStr(strVirDirName)     NewWeb.SetInfo     If Err <> 0 Then         If Err.Number <> &H80071392 Then 'If virtual dir exists                                          'no need to raise an error             MsgBox "Error creating virtual directory for " _                    & strFolderName, vbInformation + vbOKOnly, App.Title             WriteLog "Error creating virtual directory " & strVirDirName _                    & " for folder tree " & strFolderName             SetNewWeb = -1         End If     Else         SetNewWeb = 0     End If          Set iServer = Nothing      End Function 

Table 18-5 lists the properties you must set (except those that are always the same value, such as msExchLogonMethod ).

Table 18-5: Required Properties for Exchange Virtual Directories

Property

Description

anonymousAccount

Specifies the Windows account that IIS will use to authenticate users when they are accessing the Web site anonymously.

folderPathname

Specifies the relative folder path. For example, a folder path to a folder called Helpdesk under Public Folders would be specified as Public Folders\Helpdesk .

msExchAccessFlags

An integer that specifies the access flag for the virtual directory. You can combine the following values to get different levels of access:

  • Read access ( 1 )

  • Write access ( 2 )

  • Script source access ( 16 )

  • Execute permissions for scripts ( 512 )

  • Execute permissions for scripts and executables ( 516 )

For example, if you want read access to your virtual directory and you want to execute scripts, you can specify the value 513 for this property.

msExchAuthenticationFlags

Specifies whether Anonymous, Basic, and/or Integrated Windows Authentication is allowed for the virtual directory. These are the values:

  • Anonymous ( 1 )

  • Basic ( 2 )

  • Integrated Windows Authentication ( 4 )

  • Digest Authentication ( 16 )

For example, if you want all authentication methods, you can pass 7 as the value for this property. Remember, though, that IIS restricts machine hops when you use NTLM authentication, and this can affect what security mode you use in an FE/BE configuration. You should use Basic Authentication over SSL in that scenario.

msExchBasicAuthenticationDomain

If you're using Basic Authentication, you can specify the default Windows domain to try to validate the username and password against. If you do not specify this property, IIS will use the default domain on the server on which IIS is running.

msExchDefaultLogonDomain

Specifies the default domain to try Exchange Server authentication against. This property is used when a client does not specify a domain to log onto in the browser logon box.

msExchDirBrowseFlags

If you want to enable directory browsing, which allows users to look at the items in your folders pointed to by the IIS virtual directory, you must specify “1073741794 for this property. If you want to disallow directory browsing, you must specify 1073741854 .

Any future changes you make to the virtual directory should be made through the Exchange System Manager and not through the IIS tools because those changes will not be replicated back into Active Directory. If you do make changes in the IIS tools and Exchange replicates the changes from Active Directory, the changes you make with the IIS tools might be overwritten and lost.

Working with Mailbox Databases

To work with a mailbox database, you use the MailboxStoreDB object. This object is similar in its properties to the PublicStoreDB object, and the methods are exactly the same. Table 18-6 lists the properties of this object that are different from those of the PublicStoreDB object.

Table 18-6: Properties of the MailboxStoreDB Object

Property

Description

OfflineAddressList

A string that specifies an Active Directory path to the offline address list for mailboxes stored in this database.

OverQuotaLimit

Specifies the size limit (in kilobytes) for mailboxes in this database. If this limit is exceeded, the user cannot send mail.

PublicStoreDB

A string that specifies the Active Directory path to the default public folder database for this mailbox.

Creating Mailbox Databases

To create a mailbox database, you just create a MailboxStoreDB object, create an Active Directory path to the new database, and call the SaveTo method on the DataSource object for the MailboxStoreDB object. If you want, you can then call the Mount method to mount the new database. The following code creates a new mailbox database called MyNewMailboxDB :

 Dim oMB As New CDOEXM.MailboxStoreDB oMB.DataSource.SaveTo "LDAP://SERVER/CN=MyNewMailboxDB," _     & "CN=First Storage Group,CN=InformationStore,CN=SERVER," _     & "CN=Servers,CN=First Administrative Group," _     & "CN=Administrative Groups,CN=First Organization," _     & "CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=DOMAIN,DC=com" oMB.Mount 

Deleting a Mailbox Database

Before you can delete a mailbox database, you must first be sure that there are no active mailboxes on that database. You can do this by moving all the mailboxes to a new mailbox database or by mail-disabling any of the users in the database. To delete the mailbox database, you just open the database using the Open method on the DataSource object for the MailboxStoreDB object, and then you call the Delete method.

Creating New Mailboxes

Before you create a new mailbox, you should probably create a new user in Active Directory. The easiest way to create a new user programmatically is to use ADSI. Then you can create a new mailbox for that new user.

To create a new user using ADSI, you retrieve the container where you want to add the user. In the simplest case, this is the Users container. Then you create a new object in that container of the user class. You must set some properties, such as first name, last name, and account name. Then you call the SetInfo method to save the information into Active Directory.

The next step is to set the MailboxStore object you created to the IADsUser object you just created for the new user. This aggregates the MailboxStore object onto the IADsUser object. Then you can call the CreateMailbox method over the MailboxStore object. You pass the Active Directory path to the mailbox database where the new mailbox will be created. You then call the SetInfo method again to make sure the changes CDOEXM has made to the IADsUser object are saved back to Active Directory. The following code does all of this:

 Dim objUser As IADsUser Dim objContainer As IADsContainer Dim objMailbox As CDOEXM.IMailboxStore Dim recipname As String, recip As String      recip = "CN=New User"      ' get the container Set objContainer = GetObject("LDAP://CN=users,DC=thomriznt5dom2," _                             & "DC=extest,DC=microsoft,DC=com")      ' create a recipient Set objUser = objContainer.Create("User", recip) objUser.Put "samAccountName", "newuser" objUser.Put "sn", "User" objUser.Put "givenName", "New" objUser.Put "userPrincipalName", "newuser"      objUser.SetInfo objUser.SetPassword "password" objUser.AccountDisabled = False      Set objMailbox = objUser      'Create a mailbox for the recipient 'You cannot create a mailbox using ADSI, so use CDOEXM      objMailbox.CreateMailbox "LDAP://thomriznt52.thomriznt5dom2.extest." _     & "microsoft.com/CN=Mailbox Store (THOMRIZNT52)," _     & "CN=First Storage Group,CN=InformationStore,CN=THOMRIZNT52," _     & "CN=Servers,CN=First Administrative Group," _     & "CN=Administrative Groups,CN=First Organization," _     & "CN=Microsoft Exchange,CN=Services,CN=Configuration," _     & "DC=thomriznt5dom2,DC=extest,DC=microsoft,DC=com" objUser.SetInfo 

Using the MailboxStore object, you can also delete and move mailboxes as well as set properties on the mailbox. Table 18-7 lists the properties and methods of the MailboxStore object.

Table 18-7: Properties and Methods of the MailboxStore Object

Property

Description

DaysBeforeGarbageCollection

Specifies the number of days that deleted mail will be retained before it is permanently deleted.

Delegates

Contains an array of string values that are the URLs of the other users who have access to this mailbox.

EnableStoreDefaults

A Boolean that specifies whether to use the database defaults for storage limits. A value of True means that the default limits will be used.

GarbageCollectOnlyAfterBackup

Specifies whether items can be permanently deleted only after the mailbox has been backed up.

HardLimit

Specifies the size (in kilobytes) beyond which the user can no longer send and receive mail.

HomeMDB

Specifies the Active Directory path to the mailbox store for the recipient.

OverQuotaLimit

Specifies a size limit (in kilobytes) of a mailbox. If this limit is exceeded, sending mail is disabled.

OverrideStoreGarbageCollection

Specifies whether this mailbox should use the garbage collection properties set on this mailbox or the properties set on the database.

RecipientLimit

An integer that specifies the maximum number of recipients this user can send a single e-mail to.

StoreQuota

Specifies the maximum size (in kilobytes) of the mailbox.

CreateMailbox

Takes the path to the mailbox database where you will create a new mailbox.

DeleteMailbox

Deletes the mailbox.

MoveMailbox

Moves the mailbox to a new mailbox database. You must specify as a parameter the Active Directory path of the new mailbox database where you want to move the mailbox.

To access a mailbox, you use both ADSI and the MailboxStore object. The following code opens a user in Active Directory and retrieves the MailboxStore - related object for that user:

 Dim oMB As CDOEXM.IMailboxStore     Dim objUser As ActiveDs.IADsUser          Set objUser = GetObject("LDAP://CN=new user,CN=users," _                           & "DC=thomriznt5dom2,DC=extest,DC=microsoft,DC=com")     Set oMB = objUser 

The Recipient Update Service

Before any object can become truly mailbox- or mail-enabled in the system, you must run a component of Exchange called the Recipient Update Service (RUS). The RUS populates a number of properties, such as the proxy address of the new user. The RUS can take seconds or hours to run, but you configure how often it runs through the Exchange System Manager. It runs asynchronously, so it will not fire on new mailbox creation. The following code sets the RUS to start processing immediately by setting the msExchReplicateNow attribute to true . Because the RUS is asynchronous, it will not run that very second, but this code can significantly reduce the time you have to wait for the RUS to run.

 strDomainName = "domain" strDomain = "DC=domain,DC=com" strServer = "MyServer" 'Kick off the Recipient Update Service ' >>>> ToDo:  Make sure the following string is correct by finding the RUS for '             your domain via ADSIEdit. strRUS = "CN=Recipient Update Service (" & strDomainName _        & "),CN=Recipient Update Services," _        & "CN=Address Lists Container,CN=Microsoft," _        & "CN=Microsoft Exchange,CN=Services," _        & "CN=Configuration," & strDomain set objRUS = GetObject("LDAP://" & strServer & "/" & strRUS) objRUS.Put "msExchReplicateNow", True objRUS.SetInfo 

Combining CDOEXM and CDO for Exchange

One of the most common programming tasks you will perform is to combine CDOEXM with CDO for Exchange (CDOEX). Some of the objects in CDOEX expose interfaces that you can use to retrieve certain CDOEXM interfaces. For example, the Person object in CDOEX also implements the IMailboxStore interface, so if the CDOEX Person object you are working with has a mailbox, you can retrieve the IMailboxStore interface for that person by using the GetInterface method on the Person object or by forcing CDOEX to do this for you by setting a MailboxStore object equal to a CDOEX Person object. An example is shown here:

 Dim oPerson As CDO.Person Dim oMailbox As CDOEXM.IMailboxStore      Set oPerson = CreateObject("CDO.Person") oPerson.DataSource.Open "mailto:thomriz@thomriznt5dom2.extest.microsoft.com"      'Set oMailbox = oPerson.GetInterface("IMailboxStore") 'Or you could coerce CDOEX to do it for you Set oMailbox = oPerson      MsgBox oMailbox.RecipientLimit 

Working with Mailbox Rights

To programmatically modify the permissions on your Exchange mailboxes, you can use the new MailboxRights property on the IExchangeMailbox interface in Exchange 2000 Service Pack 2 and later. This is a read/write property that can take an ADSI security descriptor. The following code uses this new property to set full control permissions for another user on a mailbox. You need the ADSI security DLL from the ADSI Resource Kit to run this code.

 Dim SecurityDescriptor As IADsSecurityDescriptor Dim Dacl As IADsAccessControlList Dim newace As New AccessControlEntry Dim objUser As CDOEXM.IExchangeMailbox Dim objMailboxSD As IADsSecurityDescriptor      Set objUser = GetObject("LDAP://domain.com/CN=users," _                       & "CN=users,DC=domain,DC=com")      Set objMailboxSD = objUser.MailboxRights      Set Dacl = objMailboxSD.DiscretionaryAcl      For Each obj In Dacl     Debug.Print "Trustee:", obj.Trustee     Debug.Print "AccessMask:", obj.AccessMask     Debug.Print "AceFlags:", obj.AceFlags     Debug.Print "AceType:", obj.AceType Next      'AceTypes: 'ADS_ACETYPE_ACCESS_DENIED = 1 'ADS_ACETYPE_ACCESS_ALLOWED = 0 newace.AceType = ADS_ACETYPE_ACCESS_ALLOWED      'Inheritance Flags 'CONTAINER_INHERIT_ACE = 2 newace.AceFlags = 2      'Set the AccessMask from ADSI 'ADS_RIGHT_DELETE = 0x10000, 'ADS_RIGHT_READ_CONTROL = 0x20000, 'ADS_RIGHT_WRITE_DAC = 0x40000, 'ADS_RIGHT_WRITE_OWNER = 0x80000, 'ADS_RIGHT_SYNCHRONIZE = 0x100000, 'ADS_RIGHT_ACCESS_SYSTEM_SECURITY = 0x1000000, 'ADS_RIGHT_GENERIC_READ = 0x80000000, 'ADS_RIGHT_GENERIC_WRITE = 0x40000000, 'ADS_RIGHT_GENERIC_EXECUTE = 0x20000000, 'ADS_RIGHT_GENERIC_ALL = 0x10000000, 'ADS_RIGHT_DS_CREATE_CHILD = 0x1, 'ADS_RIGHT_DS_DELETE_CHILD = 0x2, 'ADS_RIGHT_ACTRL_DS_LIST = 0x4, 'ADS_RIGHT_DS_SELF = 0x8, 'ADS_RIGHT_DS_READ_PROP = 0x10, 'ADS_RIGHT_DS_WRITE_PROP = 0x20, 'ADS_RIGHT_DS_DELETE_TREE = 0x40, 'ADS_RIGHT_DS_LIST_OBJECT = 0x80, 'ADS_RIGHT_DS_CONTROL_ACCESS = 0x100      'Exchange permissions correspond to Const ACE_MB_FULL_ACCESS = &h1 Const ACE_MB_DELETE_STORAGE = &h10000 Const ACE_MB_READ_PERMISSIONS = &h20000 Const ACE_MB_CHANGE_PERMISSIONS = &h40000 Const ACE_MB_TAKE_OWNERSHIP = &h80000 newace.AccessMask = 983041      'Set a valid user account newace.Trustee = "domain\user"      'Add the ACE to the DACL Dacl.AddAce newace      'Set changed DACL to Object objMailboxSD.DiscretionaryAcl = Dacl         'Set the MailboxRights property objUser.MailboxRights = Array(objMailboxSD)      objUser.SetInfo 



Programming Microsoft Outlook and Microsoft Exchange 2003
Programming MicrosoftВ® OutlookВ® and Microsoft Exchange 2003, Third Edition (Pro-Developer)
ISBN: 0735614644
EAN: 2147483647
Year: 2003
Pages: 227
Authors: Thomas Rizzo

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net