I have just posted this article in the Greatest Hits series on the ILM Technet forum.
The article covers various management tasks you can acheive with the standard AD MA, including provisioning and updating of users, mailboxes, contacts and distribution groups. There are quite a few code samples as well.
Managing Exchange 2000/2003/2007 with ILM 2007
This article covers the management of Exchange-enabled objects using the native Active Directory Management Agent that is included with ILM 2007 FP1.
The managed object types discussed are Users, Contacts, Groups and Dynamic Distribution Lists. The article also covers the special cases of adding mailboxes to existing accounts, and supporting a Resource Forest. Where extra steps are required for Exchange 2007 this has been highlighted.
It is assumed that the reader is comfortable with the concepts of Provisioning code and Advanced attribute flow rules.
Permissions
The service account used in the connection properties of the Management Agent must have sufficient rights to execute the required changes in AD.
Typically a Domain Admin account will be used, but if this is not permitted in your environment you will need to do some testing. The minimum permissions required are:
- Replicate Directory Changes
- Rights to create/delete/modify objects in the specific OUs
- Exchange Administrator (2003) or Exchange Recipient Administrator (2007)
Ă‚Â
Users
Provisioning Mail Users
Exchange 2000/2003
Provisioning a mail user is most simply done using the CreateMailbox method of the ExchangeUtils class. This method will create a new user account, and populate the necessary mail attributes for you.
See the code sample Create a User with a Mailbox at the end of this document for an example of the provisioning code.
Mixed Exchange 2003 and 2007
In a mixed environment the RUS still runs so Exchange 2003 methods may be used. Make sure that you do not tick the “Enable Exchange 2007 provisioning” box in the Management Agent configuration.
Exchange 2007
The same code will work when provisioning to Exchange 2007, however there are some extra requirements for the ILM server:
- ILM 2007 FP1 or later
- Powershell
- Exchange 2007 Management Tools
- Latest rollup packs on Exchange and ILM servers
In addition you must tick Enable Exchange 2007 provisioning on the Extensions tab of the Management Agent.
Adding a Mailbox to an existing User
Sometimes you may need to create a mailbox for an existing account. As the account already exists this is not actually a provisioning task, and is therefore handled with export flow rules.
All you need to do is to populate the following attributes, in addition to the basic user attributes:
- displayName – if not already set
- mailNickname – with the local part of the email address (the bit before the “@”)
- homeMDB – with the DN of the mail store
- mDBUseDefaults – set to “True” to use the default quota settings
Ă‚Â
Special Mailbox Types
Exchange 2007 includes some extra mailbox types:
- Room Mailbox,
- Equipment Mailbox,
- Linked Mailbox.
The Linked Mailbox is covered in the Resource Forest section below.
The Room and Equipment mailboxes are currently not supported by ILM 2007 provisioning. The only reliable method is to create a User Mailbox using ILM 2007, and then use the set-mailbox cmdlet to change the mailbox type.
Troubleshooting
Export Errors
The most common problems with provisioning Exchange users will relate to permissions. Make sure that the account used by the MA to connect to AD has permission to create Exchange users. Also make sure you have the latest service packs and rollups on the Exchange and ILM servers – at least SP1 RU9.
Where’s the Mailbox?
Exchange does not create the actual mailbox until it is opened or something is sent to it, therefore it is completely normal for no new mailboxes to be listed directly after the ILM export.
To confirm if the user is really mail-enabled:
- In Exchange 2003, check that the user’s Exchange tabs have appeared in the Exchange-enhanced version of AD Users & Computers.
- In Exchange 2007, use the get-user cmdlet to confirm the user’s object type is “UserMailbox”, or check that they appear as a Recipient in the Management Console.
Ă‚Â
Exchange 2007 and Global Catalog targeting
There is a known problem with Exchange 2007 provisioning and AD replication delays. On the MA’s Configure Directory Partitions tab you can hard-code the name of a preferred domain controller. Enter the name of the nearest Global Catalog to ensure that both the user creation and the mailbox creation are performed in the same place.
Note |
---|
Use the Resource Kit utility nltest to find Global Catalog servers: nltest /DSGETDC:mydomain.com /GC |
Ă‚Â
Modifying Mail Users
You can change a user’s Exchange related attributes using export flow rules.
The following table is not exhaustive. If you wish to automate an Exchange modification the best thing to do is make the change manually and then inspect the attribute changes using ADSIEdit.
In this way you can discover which attributes you need to create flow rules for, and the types of value you should flow.
Attribute | Function | Comments |
---|---|---|
altRecipient | Used in forwarding – the DN or the mail-enabled object to forward all mail to. | When forwarding mail to an external account you must create a Contact object in this Exchange organization. |
deliverAndRedirect | If forwarding is enabled, set to TRUE to deliver to both the mailbox and the forwarding address. | Use in combination with altRecipient. |
extensionAttributen | Free-use string attributes where you can store any data you like. | Be consistent. If extensionAttribute4 is being used for star sign, then make sure it is only ever used for that. |
homeMDB | Location of the mailbox. | Do NOT change once it has been set. If you need to move the mailbox use Exchange admin utilities. |
The user’s primary email address. | If changing the address you should also change mailNickname and the “SMTP:” value of proxyAddresses. | |
Ă‚Â | Ă‚Â | Ă‚Â |
mailNickname | This should match the local part of the primary email address. | Ă‚Â |
mDBUseDefaults | Use the default quota for the mail store. | Set to False if setting an individual limit. |
mDBStorageQuota | The “Warning” limit Expressed in Kbytes. |  |
mDBOverQuotaLimit | The “Block Send” limit Expressed in Kbytes. |  |
mDBOverHardQuotaLimit | The “Block Send & Receive” limit | Expressed in Kbytes. |
msExchHideFromAddressLists | Set to “True” to hide from the GAL. |  |
msExchMailboxGuid | The unique identifier of the mailbox | DON’T CHANGE THIS! It can be useful to flow this back into the Metaverse if you need to test that the mailbox was created. |
proxyAddresses | Multivalue attribute holding all possible email addresses for this account | The capital “SMTP:” address is the primary. The other “smtp:” addresses act as aliases. |
Ă‚Â
Resource Forest
In a Resource Forest scenario the following accounts are needed:
- An enabled user account in the Account Forest.
- A disabled account in the Resource Forest with an attached mailbox.
The account creation in the two forests and the mailbox linking are simple enough to achieve with ILM. A provisioning code sample has been included at the end of this document under Create Account Forest and Resource Forest Accounts.
The difficulty comes with the permissions assignment piece of the puzzle – it is necessary for the user’s account to have the Full Access and Send As rights to the mailbox. This is not something that is possible with the native Active Directory MA.
While there are several ways to solve the permissions-assignment problem, the typical way is to run a script after the export step. The script might simply trawl AD looking for accounts to update or it could read details from the ILM export log and target the new accounts.
While outside the scope of this document, the following resources have been included for reference:
- A Microsoft technote showing how to Script Exchange 2000/2003 mailbox permissions,
- A PowerShell script for Exchange 2007 has been included in the Code section at the end of this article.
Ă‚Â
Contacts
Contacts are used for two primary functions in Exchange, both of which can be automated with ILM:
- Adding organization-wide contacts to the Global Address List.
ILM could be used to import information from a CRM system and automatically create the contact object. - As a way to forward mail from a mailbox within the organization.
Some organizations (such as universities) allow users to forward their mail to another address. As long as ILM has the information about the forwarding request (perhaps entered by the user in a self-service portal) it can be configured to create the contact and set up the forwarding.
Provisioning
Contacts may be provisioned very simply using the CreateMailEnabledContact method from the ExchangeUtils class.
See the code sample Create a Contact at the end of this document for an example of the provisioning code.
Modifying
Attribute | Function | Comments |
---|---|---|
The contact’s email address. | If changing the address you should also change targetAddress and the “SMTP:” value of proxyAddresses. | |
msExchHideFromAddressLists | Set to “True” to hide from the GAL. |  |
proxyAddresses | Multivalue attribute holding all possible email addresses that will forward via the contact. | To work the contact needs an alias using “smtp:” in the local domain. The “SMTP:” address should match mail and targetAddress. |
targetAddress | The email address that mail sent to this contact will be forwarded to. | One address only. |
Ă‚Â
Distribution List
There are three types of Distribution list in Exchange:
- Groups of type Distribution
- Groups of type Security that have an email address
- Dynamic distribution lists.
All three types can be created and managed with ILM, but the processes will differ.
Distribution Groups
To provision a standard Distribution Group use the CreateDistributionList method of the ExchangeUtils class. See Create a Distribution List at the end of this document for a code sample.
The main modification you will do with groups is to update the membership list. Group population is outside the scope of this document, though it is worth looking into Group Populator and Multi-Value tables.
Security Groups with Email Address
It is possible to mail-enable a Security group, allowing it to then also act as a distribution list.
Provisioning such a group is a simple matter of creating a security group and adding the mail address. See Create a Mail-Enabled Security Group under Code Samples at the end of this document.
Dynamic Distribution Lists
You may also use ILM to provision Dynamic Distribution Lists. All you need to do is to create an object of type msExchDynamicDistributionList and add values to the following attributes:
- displayName
- mailNickname
- msExchDynamicDLFilter
- msExchDynamicDLBaseDN
See Create a Dynamic Distribution List under Code Samples at the end of this document.
Code Samples
Create a User with a Mailbox
Ă‚Â
This MVExtension code is in addition to export flow rules to the user object type on the following attributes:
- displayName
- givenName
- sAMAccountName
- sn
- userPrincipalName
Ă‚Â
Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision Const ADS_UF_NORMAL_ACCOUNT As Integer = &H200 Dim csentry As CSEntry Dim MA As ConnectedMA Dim dn As ReferenceValue Dim rdn As String Dim homeMDB As String Dim mailNickname As String Dim mail As String Select Case mventry.ObjectType Case "person" MA = mventry.ConnectedMAs("MYDOMAIN") If <test that account should exist> AndAlso MA.Connectors.Count = 0 Then rdn = "CN=" & mventry("sn").Value & ", " & mventry("givenName").Value dn = MA.EscapeDNComponent(rdn).Concat("OU=Users,OU=MyOrg, " _ & "dc=mydomain,dc=local") mailNickname = mventry("mailNickname").Value ' The following line assumes MDB, SG and MailServer have been ' populated for the user in the Metaverse. homeMDB = "CN=& mventry("MDB").StringValue _ & ",CN=" & mventry("SG").StringValue _ & ",CN=InformationStore,CN=" & mventry("MailServer").StringValue _ & ",CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT)" _ & ",CN=Administrative Groups,CN=First Organization" _ & ",CN=Microsoft Exchange,CN=Services,CN=Configuration" _ & ",DC=mydomain,DC=local" csentry = ExchangeUtils.CreateMailbox(MA, dn, mailNickname, homeMDB) csentry.DN = dn csentry("unicodePwd").Values.Add("FirstP@ssw0rd") csentry("userAccountControl").IntegerValue = ADS_UF_NORMAL_ACCOUNT csentry.CommitNewConnector() End If End Select End Sub
Ă‚Â
Create Account Forest Accounts and Resource Forest Accounts
Ă‚Â
Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision Const ADS_UF_NORMAL_ACCOUNT As Integer = &H200 Dim csentry As CSEntry Dim MA As ConnectedMA Dim dn As ReferenceValue Dim rdn As String Dim homeMDB As String Dim mailNickname As String Dim mail As String Select Case mventry.ObjectType Case "person" 'Create Account Forest account - no mailbox MA = mventry.ConnectedMAs("AccountForest") If MA.Connectors.Count = 0 Then rdn = "CN=" & mventry("sn").StringValue _ & ", " & mventry("givenName").StringValue dn = MA.EscapeDNComponent(rdn).Concat("OU=Users,OU=MyOrg, " _ & "dc=accountdomain,dc=local") csentry = MA.Connectors.StartNewConnector("user") csentry.DN = dn csentry("unicodePwd").Values.Add("FirstP@ssw0rd") csentry("userAccountControl").IntegerValue = ADS_UF_NORMAL_ACCOUNT csentry.CommitNewConnector() End If 'Create disabled account and mailbox in Resource forest. ' This can only be done once the objectSID from the account domain ' is available. Create a metaverse Binary attribute called SID ' and flow objectSid -> SID. ' The account is disabled because no password is set. Alternatively set ' a random password and disable using userAccountControl. MA = mventry.ConnectedMAs("ResourceForest") If MA.Connectors.Count = 0 AndAlso mventry("SID").IsPresent Then rdn = "CN=" & mventry("displayName").StringValue dn = MA.EscapeDNComponent(rdn).Concat("OU=LinkedMailboxes,OU=MyOrg, " _ & "dc=resourcedomain,dc=local") mailNickname = mventry("mailNickname").StringValue homeMDB = "CN=" & mventry("MDB").StringValue _ & ",CN=" & mventry("SG").StringValue _ & ",CN=InformationStore,CN=" & mventry("MailServer").StringValue _ & ",CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT)" _ & ",CN=Administrative Groups,CN=First Organization" _ & ",CN=Microsoft Exchange,CN=Services,CN=Configuration" _ & ",DC=mydomain,DC=local" csentry = ExchangeUtils.CreateMailbox(MA, dn, mailNickname, homeMDB) csentry.DN = dn csentry("msExchMasterAccountSid").BinaryValue = mventry("SID").BinaryValue 'The following setting is optional but can help with tracking the mailbox user. csentry("extensionAttribute1").Value = "accountdomain\" _ & mventry("uid").StringValue csentry.CommitNewConnector() End If End Select End Sub
Ă‚Â
Assign Resource Mailbox Permissions – Exchange 2007, powershell
Ă‚Â
The following script assigns the FullAccess and SendAs permissions to a resource forest mailbox.
The resource forest account needs to have the domain\username of the user’s actual account written to extensionAttribute1, as per the provisioning code above.
$Filter = "(&(ObjectCategory=user)(extensionAttribute1=*))" $Searcher = New-Object System.DirectoryServices.DirectorySearcher($Filter) $Searcher.Findall() | Foreach-Object -Process { $alias = [string]$_.properties.item("mailNickname") $user = [string]$_.properties.item("extensionAttribute1") Add-MailboxPermission -Identity $alias -AccessRights FullAccess, SendAs -User $user }
Ă‚Â
Create a Contact
Ă‚Â
Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision Dim csentry As CSEntry Dim MA As ConnectedMA Dim dn As ReferenceValue Dim rdn As String Dim mailNickname As String Dim mail As String Select Case mventry.ObjectType Case "person" MA = mventry.ConnectedMAs("MYDOMAIN") If MA.Connectors.Count = 0 Then rdn = "CN=" & mventry("displayName").StringValue dn = MA.EscapeDNComponent(rdn).Concat("OU=Contacts,OU=MyOrg, " _ & "dc=mydomain,dc=local") mail = mventry("mail").StringValue 'The mailNickname is only for internal Exchange purposes. 'You could just as easily use an id number from the source data. mailNickname = mventry("mail").Value.Split("@")(0) csentry = ExchangeUtils.CreateMailEnabledContact(MA, dn, mailNickname, mail) csentry.DN = dn csentry.CommitNewConnector() End If End Select End Sub
Ă‚Â
Create a Distribution List
Ă‚Â
Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision Dim csentry As CSEntry Dim MA As ConnectedMA Dim dn As ReferenceValue Dim rdn As String Dim mailNickname As String Dim mail As String Select Case mventry.ObjectType Case "group" MA = mventry.ConnectedMAs("MYDOMAIN") If MA.Connectors.Count = 0 Then rdn = "CN=" & mventry("cn").StringValue dn = MA.EscapeDNComponent(rdn).Concat("OU=Groups,OU=MyOrg, " _ &"dc=mydomain,dc=local") mailNickname = mventry("mailNickname").StringValue csentry = ExchangeUtils.CreateDistributionlist(MA, dn, mailNickname) csentry.DN = dn csentry.CommitNewConnector() End If End Select End Sub
Ă‚Â
Create a Mail-Enabled Security Group
Ă‚Â
Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision Dim csentry As CSEntry Dim MA As ConnectedMA Dim dn As ReferenceValue Dim rdn As String Dim mailNickname As String Dim mail As String Select Case mventry.ObjectType Case "group" MA = mventry.ConnectedMAs("MYDOMAIN") If MA.Connectors.Count = 0 Then rdn = "CN=" & mventry("cn").StringValue dn = MA.EscapeDNComponent(rdn).Concat("OU=Groups,OU=MyOrg, " _ & "dc=mydomain,dc=local") mailNickname = mventry("mailNickname").StringValue csentry = MA.Connectors.StartNewConnector("group") csentry("groupType").Value = -2147483640 'Universal Security csentry("displayName").Value = mventry("cn").StringValue csentry("mailNickname").Value = mailNickname csentry.DN = dn csentry.CommitNewConnector() End If End Select End Sub
Ă‚Â
Create a Dynamic Distribution List
Ă‚Â
This MVExtension code snippet creates Department DDLs.
The department names have been imported into department objects in the Metaverse.
The users’ department attribute matches exactly the department names.
Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision Dim csentry As CSEntry Dim MA As ConnectedMA Dim dn As ReferenceValue Dim rdn As String Dim mailNickname As String Dim mail As String Select Case mventry.ObjectType Case "department" MA = mventry.ConnectedMAs("MYDOMAIN") If MA.Connectors.Count = 0 Then rdn = "CN=" & mventry("cn").StringValue dn = MA.EscapeDNComponent(rdn).Concat("OU=DDLs,OU=MyOrg, " _ & "dc=mydomain,dc=local") mailNickname = mventry("mailNickname").StringValue csentry = MA.Connectors.StartNewConnector("msExchDynamicDistributionList") csentry.DN = dn csentry("displayName").Value = mventry("cn").StringValue csentry("mailNickname").Value = mailNickname 'The following filter selects users whose department equals the DDL cn csentry("msExchDynamicDLFilter").Value = "(&(!cn=SystemMailbox{*})" _ & "(&(&(&(& (mailnickname=*)" _ & "(| (&(objectCategory=person)(objectClass=user)" _ & "(|(homeMDB=*)(msExchHomeServerName=*))) )))" _ & "(objectCategory=user)(department=" _ & mventry("cn").StringValue & "))))" csentry("msExchDynamicDLBaseDN").Value = "OU=Groups,OU=MyOrg, " _ & "dc=mydomain,dc=local" csentry.CommitNewConnector() End If End Select End Sub
Ă‚Â
ILM Forum Threads
- Provisioning Exchange 2007 with ILM 2007
- ILM With FP1 and Exchange 2007
- Exchange 2007 ‘Shared’ Mailbox Provisioning with ExchangeUtils
- Attribute List for Exchnage 2003
Ă‚Â
About the Author
Carol Wapshere has been working in IT since 1990, and has since worked in many different organizations, across four different countries. She started out in Netware then moved into Microsoft server products, picking up an assortment of skills in other non-Microsoft systems along the way. She first started working with MIIS in 2005 and loved how it could be used to tie together disparate systems, bringing in much-needed order, and making lots of tedious jobs just disappear.
Thanks to Markus Vilcinskas and Peter Geelan for their help with this document.
https://www.wapshere.com/missmiis