Managing Exchange 2000/2003/2007 with ILM 2007

I have just posted this article in the Greatest Hits series on the ILM Technet forum.

http://social.technet.microsoft.com/Forums/en-US/identitylifecyclemanager/thread/f8ad045d-7252-4cd1-a189-d704a8f99129

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.

noteNote
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.
mail 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:

  1. An enabled user account in the Account Forest.
  2. 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:

  1. A Microsoft technote showing how to Script Exchange 2000/2003 mailbox permissions,
  2. 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:

  1. 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.
  2. 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
mail 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:

  1. Groups of type Distribution
  2. Groups of type Security that have an email address
  3. 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

 

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.


http://www.wapshere.com/missmiis

About: Carol

I've been doing IT for 30 years, and IdM for 15. I live in Australia and build IdM solutions based on Microsoft Identity Manager. I also play the violin, but that doesn't help much with the IdM solutions.