Powershell – Creating valid mail enabled contacts without using Exchange specific cmdlets

active-directoryexchangeexchange-2013powershell

I have written a powershell script to routinely process and import a large (over 70k) amount of contacts into an Exchange environment. The script works fine but I would like to speed it up if possible. The most time consuming parts used to be importing and exporting the data.

I was able to cut down a lot of the processing time by removing most of the dependencies on Exchange 2013 cmdlets. For example, using the "native" Get-ADObject cmdlet to extract the data instead of a combination of the Exchange specific Get-MailContact and Get-Contact I was able to reduce the processing time by a factor of 10.

The command looks like this:

$result = Get-ADObject -LDAPFilter "(objectClass=contact)" -searchBase "$OU"  -ResultPageSize 100 -property GivenName, SN, DisplayName, Department, physicalDeliveryOfficeName , telephoneNumber, mailnickname, targetaddress |  select @{ label="Email"; Expression={ ($_.targetaddress -replace "^SMTP:","").tostring().Tolower().Trim() }}, @{ N="Alias"; E={ $_.mailnickname} }, @{ N="FirstName"; E={ $_.GivenName} }, @{ N="LastName"; E={ $_.SN} }, DisplayName,  @{ N="Office"; E={ $_.physicalDeliveryOfficeName} } , Department, @{ N="Phone"; E={ $_.telephoneNumber} }

Now I would like to be able to do the opposite, to create the contacts. That is, create a mail enabled contact without using Exchange specific cmdlets. I managed to create a contact using this command:

$Attributes = @{'displayName' = $displayname; 'GivenName' = $first; 'SN' = $last; 'Department' = $department; 'physicalDeliveryOfficeName' = $office; 'telephoneNumber' = $phone; 'mail' = $email; 'mailnickname' = $alias; 'targetaddress' = $email}

New-AdObject -Type Contact -Name $displayname -Path $OU -OtherAttributes $Attributes -whatif

However, although the object is apparently created correctly, it does not show up among the contacts on Exchange. The only way so far I have been able to achieve this is to run the "Enable-MailContact" cmdlet on the object after creation, which defeats the purpose of not using Exchange cmdlets in the process.

So my question is, does anybody know if there is a way to create a functional mail enabled contact using only the New-ADObject cmdlet and without relying on Exchange specific cmdlets ?

Thank you.

Best Answer

It turned out that the crucial missing item was the "showinaddressbook" property.

This article explains how it works: https://support.microsoft.com/en-us/kb/253828

The showInAddressBook attribute has two purposes. The first is to let people see the entry listed in the address list by means of Messaging Application Programming Interface (MAPI) client, such as Microsoft Outlook. The second purpose is to allow users to "resolve a name" on a MAPI client.

Even though the article refers to the Recipient Update Service (RUS) which does not exist anymore since Exchange 2007, I guess the underlying process for mail enabling an object is still the same.

So basically to create a mail-enabled contact without using the Exchange 2013 cmdlets I did something like this:

$alias = "ADDR-00001"
$email = "jdoe@somewhere.com"
$first = "Joe"
$last = "Doe"
$displayname = "DOE Joe"
$department = "My Dept."
$office = "My Office"
$phone = "55554448934"
$proxyAddresses = "SMTP:jdoe@somewhere.com"
$DestinationOU = "OU=contact,OU=example,DC=corp,DC=example,DC=com"
$AddressBook = "CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,CN=Example-Org,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=corp,DC=example,DC=com","CN=All Contacts,CN=All Address Lists,CN=Address Lists Container,CN=Example-Org,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=corp,DC=example,DC=com"

$Attributes = @{'displayName' = $displayname; 'GivenName' = $first; 'SN' = $last; 'Department' = $department; 'physicalDeliveryOfficeName' = $office; 'telephoneNumber' = $phone; 'mail' = $email; 'mailnickname' = $alias; 'targetaddress' = $email; 'proxyAddresses' = $proxyAddresses; 'showinaddressbook' = $AddressBook;}

New-AdObject -Type Contact -Name $displayname -Path $DestinationOU -OtherAttributes $Attributes

The resulting object still does not have the LegacyExchangeDN value and it has a peculiar ExchangeVersion but the AddressListMembership property is now populated.

Get-Mailcontact "jdoe@somewhere.com" | select displayName, RecipientType, LegacyExchangeDN, ExchangeVersion, AddressListMembership| fl

DisplayName           : DOE Joe
RecipientType         : MailContact
LegacyExchangeDN      :
ExchangeVersion       : 0.0 (6.5.6500.0)
AddressListMembership : {\All Contacts, \Default Global Address List}