I recently had a case come across my desk where end users reported that after changing certain attributes in the directory these attributes were reverted to original or incorrect values.
In this case what we had was a centralized portal for information where end users could request that updates be made to their accounts. For example, if I was married I could request that my last name be updated in the directory to my new last name. This of course would imply that if I had email addresses based off first and last name that I would also want those addresses updated.
In Exchange 2003 the recipient update service (RUS) would scan the directory for object changes based on the objects USN. If we found an object that was changed after the USN stamped on the RUS, we knew we would need to take action against it. In this case the RUS always utilized a single Exchange server to calculate addresses and a single domain controller to read objects and write objects.
In Exchange 2007 and Exchange 2010 the RUS has become a process initiated by a task rather then scanning the directory for changes. By default when any task is run that alters a user object, such as set-mailbox or set-user, the recipient update service is called by the task. In this case calling the recipient update service means utilizing any Exchange Server’s system attendant and utilizing any domain controller – we are no longer limited to having a single Exchange server or single domain controller responsible for these tasks.
When the task set-user or set-mailbox contacts the RUS it provides a complete set of user attributes as read from the directory. The RUS then calculates valid email addresses, and provides them back to the set task. Once this information is provided the set task then commits the changes to the directory. Proxy addresses are always calculated and sent to the task which will re-write them to the directory. Other attributes, such as name etc, are only written to the directory if they were specified in the set command to be changed.
In the example of set-user and set-mailbox we have provided the –domainController switch so that a static domain controller could be utilized. For a mailbox server the task will always attempt to find a server with the mailbox role installed (hence having a system attendant where the RUS lives) in the same Active Directory site. If one is not present, the task will look to adjacent Active Directory sites.
Let’s take a look at how this changing from a directory scan to a task based system could cause the symptoms I outlined above.
I have a program that allows a user to change their name information and their ability to be seen in the address list. My email address policies are set to stamp information based on First.Last@domain.com (PRIMARY) and email@example.com (SECONDARY).
In this instance a user named BARBARA SMITH wants to change her last name to JONES. Her account currently has the following attributes relevant to our example:
proxyAddresses (2): smtp:Barbara@domain.com; SMTP: Barbara.Smith@domain.com
The application has received the request to process the change. The following command is called:
set-user –identity Barbara –lastName Jones –domainController DC-2
At this point the task contacts the directory and reads the attributes. It then contacts an Exchange server, and passes in the current attributes plus the attributes that changed. At this time the RUS evaluates this information and determines that an email address change should occur. The email address change should include a primary SMTP address of Barbara.Jones@domain.com. This information is provided back to the task.
The task then executes a write operation against DC-2 since the domain controller is statically specified. The attributes written to the directory are as follows:
proxyAddresses (3): smtp:Barbara@domain.com; SMTP:Barbara.Jones@domain.com; smtp:Barbara.Smith@domain.com
The next step of the application is to reset the hide from address book value. This happens regardless of whether or not the value needs to be updated. The following command is called:
set-mailbox –identity BARBARA –hiddenFromAddressList:$FALSE
At this point the task contacts the directory and reads the attributes. In this case domainController was not specified, and the task chooses at random DC1. The task reads the following values from DC1.
You’ll note that the values are the original values – this is because DC1 has not had time to fully replicate the changes from DC2.
Because I used the set-mailbox command, these attributes are passed into the RUS along with the attribute to change – in this case hiddenFromAddressList. The RUS evaluates the attribute set, and determines that the email addresses that should be on this user are firstname.lastname@example.org and email@example.com.
The task receives this feedback, and on DC-1 updates the following attributes:
After the domain controllers have had time to converge if I were to look at the attributes of the user here is what I see:
proxyAddresses (2): smtp:Barbara@domain.com; SMTP: firstname.lastname@example.org
It would essentially appear that the last name change was successful but the recipient update service did not update the user successfully. In actuality, after tracing the issue, it was determined that one command utilized the static domain controller, the other command did not, and this resulted in the RUS evaluating two sets of different information for the same user and thus appearing as if changes did not occur that should have occurred.
In the end this issue was rectified by ensuring that when multiple set operations are included in sequence that all set operations specify the same domain controller.