Tuesday, November 17, 2015

PowerShell reconstructing legacyExchangeDN from the NDR to X.500

While SMTP addressing is the de facto e-mail addressing standard, Exchange internally  uses an X.500 addressing scheme and not SMTP. Using X.500 implies that an X.500 is required, which is why mail objects in an Exchange organization such as mailboxes, require a properly populated legacyExchangeDN AD attribute.

The most encountered symptom of not having properly populated or unpopulated legacyExchangeDN attributes is failure of e-mail delivery or transport. legacyExchangeDN is still required, unlike some Exchange admins I overheard a while ago when they were looking for the cause of several NDRs discussing SMTP was used so it should be ‘no problem’.
After any Exchange migration or "Distribution List to Shared mailbox" conversion (or vice versa) you may have internal messages (and even external messages send to Mail Contacts stored in AD) fail because the old legacyExchangeDN address of original mail object is still in the local NK2 Outlook Autocomplete file on users desktops. Users will receive a 5.1.1 NDR like this:
Delivery has failed to these recipients or distribution lists: Help Desk 
The recipient’s e-mail address was not found in the recipient’s e-mail system. Microsoft Exchange will not try to redeliver this message for you. Please check the e-mail address and try resending this message, or provide the following diagnostic text to your system administrator.If you click on the name, the NDR will get resolved to: 
Generating server: EXCHANGE.corp.contoso.com


#550 5.1.1 RESOLVER.ADR.ExRecipNotFound; not found ##
This behavior is caused because every internal message send/received in the organization will have the recipient info resolvable normally to the legacyExchangeDN AD attribute. 

In this case, the user mailbox would have been recreated or the old legacyExchangeDN value would have been changed to a different one. It can also happen if you tried to convert any mail recipient type to another without re-adding original legacyExchangeDN as X.500 address alias to list of proxy addresses of new mail object (I'd also recommend to save existing additional X.500 address list of original mail object if exists and move it to new mail object).

There is also quick workaround for single affected client. You can simply delete Outlook Autocomplete invalid record from Outlook cache or multiply invalid records using great Nk2edit utility.
Keep in mind that any Exchange object stored in AD may have this issue: Mailbox, Distribution List, Mail Contact, Mail User, Mail Enabled Public Folder,... any mail object. Here is example how to remove Outlook Autocomplete record for Mail Contact (KB2784785):

Just type few first letters and click Delete X in Outlook. Then try to type full address manually, send e-mail and you should be OK with no 5.1.1 NDR at this point. Again this is a workaround for single user desktop and if you still need to implement more elegant solution for every user you need to fix it on server side.

Find and fix it on server side

You can analyze your whole Exchange environment for already existing X.500 addressing issues but not reported by users. Following PowerShell script will report such NDRs occurred during last 7 days:

Get-TransportServer | Get-MessageTrackinglog `
-EventID FAIL -Start (Get-Date).AddDays(-7) -ResultSize Unlimited | `
Where {$_.Recipients -match "^IMCEAEX*"}

To reconstruct the X.500 address using the information from the NDR message use support article KB2807779 contains a short instruction or utilize the small interactive Powershell script below to convert the reported IMCEAEX address to an X.500 entry.

Let's take full IMCEAEX address from NDR above "IMCEAEX-_O=CHIPPEWA_OU=EXCHANGE+20ADMINISTRATIVE+20GROUP+20+28FYDIBOHF23SPDLT+29_CN=RECIPIENTS_CN=Help+20Desk3cd@contoso.com" and convert IMCEAEX to original X.500:

$Address = Read-Host "Enter full IMCEAEX address from NDR"

$Repl= @(@("_","/"), `
@("\+20"," "), `
@("\+28","("), `
@("\+29",")"), `
@("\+2C",","), `
@("\+3F","?"), `
@("\+5F", "_" ), `
@("\+40", "@" ), `
@("\+2E", "." ))

$Repl | ForEach { $Address = $Address -replace $_[0], $_[1] }
$Address = "X500:$Address" -replace "IMCEAEX-","" -replace "@.*$", ""

Write-Host $Address  


Just add it to proxy addresses list of affected mail object using ADSI/ADUC or Exchange ECP/EMS:

Exchange ECP/EMS: