One may think that making changes to the e-mail address of a mailbox is a simple thing, but Exchange does a bit of work to ensure the changes are correct and will not cause problems in the system.
 
Here's an overview of how the UI updates e-mail addresses and how it validates and checks for uniqueness when changes are made.

E-Mail Address Attributes

Exchange stores and uses information about the e-mail addresses of a recipient in the following attributes:

   proxyAddresses 

This is the main attribute where e-mail address information is kept. When you open the properties of a recipient in Outlook and look at the "E-mail Addresses" tab, you are looking at this attribute. This is a multi-valued string containing all the addresses that represent the recipient. Each value must have the following format:

      type:address

For example:

      SMTP:nospam@online.microsoft.com

When the type is in uppercase letters, the address is considered to be the primary address of that type and it is used as the default reply address of that recipient. When the type is in lowercase letters, the address is considered a secondary address and is used to resolve addresses during e-mail delivery, allowing the same recipient to receive e-mails directed to different e-mail addresses.

For example: 
         Primary:      SMTP:currentAlias@domain.com
         Secondary:  smtp:oldAlias@domain.com

On the 'Users and Computers' snap-in, this property is edited on the 'E-mail Addresses' page of a recipient.

   targetAddress

In contacts and mail-enabled users this attribute contains the type and address of the mailbox represented by the recipient. This will point to a mailbox outside the Exchange organization, for example, to a hotmail account or to another's company address.
 
On the 'Users and Computers' snap-in, this property is edited on the 'Exchange General' page of contacts and mail-enabled users.

   mail

The value of this attribute corresponds to the primary SMTP proxy address. Windows often displays this attribute as the e-mail address of the user.
 
On the 'Users and Computers' snap-in, this property is edited on the 'General' page of recipients.

   textEncodedOrAddress

The value of this attribute corresponds to the primary X400 proxy address.
 
On the 'Users and Computers' snap-in, this property is edited by changing the primary X400 address on the 'E-mail Addresses' page of recipients.

It is important to note that the values found in mail, textEncodedOrAddress and targetAddress must also be included in proxyAddresses with their respective types, otherwise they would not be picked up when Exchange makes searches against proxyAddresses.
 
However, this creates a problem: we actually need to keep these attributes synchronized to each other when the administrator makes changes to them, either in the UI or with CDOEXM. The problem is aggravated because in 'Users and Computers' Windows implements the property page that sets the mail attribute, while the Exchange extension implements the property pages with targetAddress and proxyAddresses. Not only do we need to synchronize changes when the property page is saved but we need to synchronize when the administrator flips from one page to the other, to keep the UI consistent. To do that, we run what we call the proxy-sync mechanism.

Proxy-Sync Scenarios

Proxy-Sync runs when an administrator makes a change in one of the e-mail attributes of a recipient and that change needs to be synchronized to another attribute. For example, when mail changes, the primary SMTP entry in proxyAddresses must also be updated so that both addresses are synchronized, but if you try to delete the mail attribute without mail-disabling the recipient, then we copy the primary SMTP address back to mail.

The following list summarizes the changes supported by proxy-sync since Exchange 2000 SP2:

1.    Action: Remove e-mail from General page.
Results: Primary SMTP from proxyAddresses is copied back to mail.

2.    Action: Modify e-mail on General page.
Results: There are four cases to be considered:

o        If the new address already exists in proxyAddresses and:

·         it is the primary SMTP address: proxy is in sync already.

·         it is a secondary SMTP address: demote the current primary SMTP and promote the new address to primary SMTP.

o        If the new address does not already exists in proxyAddresses and:

·         targetAddress is the primary SMTP: demote the current primary SMTP and add the new address as primary SMTP.

·         targetAddress is a secondary SMTP: replace the primary SMTP with the new address.

3.    Action: Modify the primary SMTP on E-mail Addresses page, either by editing or by promoting a secondary address to primary.
Results: new primary SMTP is copied to mail.

4.    Action: Modify the primary X400 on E-mail Addresses page, either by editing or by promoting a secondary address to primary.
Results: new primary X400 is copied to textEncodedOrAddress.

5.    Action: Modify the address corresponding to targetAddress in the E-mail Addresses page.
Results: The new address is copied to targetAddress.  Actions 3 and 4 also apply if the edited address is a primary proxy.

6.    Action: Modify the targetAddress in the Exchange General page of contacts and mail-enabled users.
Results: The following rules are applied:

o        If the old targetAddress is the primary SMTP and the new targetAddress:

·         is also SMTP: remove the old primary SMTP.

·         is not SMTP: keep the primary SMTP intact.

·         In either case, continue following the next rules:

o        If there is already a primary address for the same type, add the targetAddress as a secondary address.

o        If there is not a primary address for the same type, add the targetAddress as a primary address and if it is SMTP or X400, copy to mail or textEncodedOrAddress, respectively.

E-mail Address Validation

Well, now that all our e-mail addresses are synchronized, we can try to save them, right? No, we are not quite there yet. Before saving we must make sure that all addresses are valid, according to their type.

 

When validating the proxyAddresses attribute, we'll check the following:

o        There must be a primary SMTP address

o        There can be only one primary address of each type

o        Every secondary address type must have a corresponding primary address

o        All addresses must pass validation of their type

·         This is actually done by the proxy generation DLL associated with each type. I won't go in details on that here since you can find more information about them in MSDN.

·         Now, these DLLs will not be installed in an admin-only installation, so we need to RPC to an Exchange server and let the server perform that validation. The Exchange System Attendant service responds by calling each proxy DLL and letting them validate the e-mail addresses typed by the user.

Can we save now? Close, but not yet. There is still one step left.

Uniqueness Check

We would not like to let an administrator accidentally create duplicate e-mail address when we can prevent that from happening. I mean, if that happens messages would start returning, people will complain and everybody gets frustrated. So let's do this one last thing before saving changes to the e-mail addresses of a recipient: let's make sure they are all unique in the organization.

 

To do that, we perform an LDAP query against the Global Catalog, looking for any object that has any of the proposed values in its proxyAddresses attribute. The query will look somewhat like this, with as many clauses as e-mail addresses we need to check: (| (proxyAddresses=SMTP:alias@domain.com) (proxyAddresses=smtp:alias2@domain.com) )

 

Of course, we need to properly format and escape the e-mail addresses in the query but most importantly, we need to be aware of the fact that there may be one object with the same addresses that we're trying to save, which would be the object we are editing. That one is ok, but if anyone else shows up in that query, we have a duplicate and we do not allow the changes to be persisted.

 

What about Recipient Policies?

 

You may be wondering why I haven't mentioned Recipient Policies anywhere. The process described above happens in the user interface, completely independent of Recipient Policies. It goes without saying that once the recipient is updated, Recipient Policies will go make sure everything is according to policy, but that's another story.

 

- Fabio Pintos