Saturday, March 23, 2013

Creating mail contacts and distribution lists using only DirectoryServices in .NET


Summary

I had a hard time discovering this solution and wanted to post in hopes to help someone else. At my first attempt at finding a solution, all I could find was people saying  it was impossible with just writing to Active Directory. So for awhile I was heading down the path of creating the contact using DirectoryServices then using remote powershell commands against the exchange server to mail enable the contacts and distribution lists. I eventually abandoned that approach and went back to finding a way with only using DirectoryServices.
If you don’t care about the code and just want attributes, here are the email attributes that were set when everything started working.
  • targetAddress
  • proxyAddresses
  • legacyExchangeDN
  • mailNickName
  • reportToOriginator = TRUE (for distribution lists) Add this, it is not in the code blocks.

Environment

Exchange 2010
Server 2008 R2 (Active Directory)
Visual Studio 2012
.NET 4.0

Code

Imports System.DirectoryServices / using System.DirectoryServices;
Create Contact in VB
Private Sub CreateContact()

        ' Create a conntaction to Active Directory

        Dim ad As DirectoryEntry

        Dim contacts As DirectoryEntry

        Dim entry As DirectoryEntry

 

        ad = New DirectoryEntry("LDAP://MACHINENAME/DC=DOMAIN,DC=COM", "username", "password")

        ' Find the OU to create the contact in

        contacts = ad.Children.Find("OU=Contacts")

 

        ' Create AD object

        entry = contacts.Children.Add("CN=LastName\, FirstName", "contact")

 

        ' Fill out basic attributes

        entry.Properties("displayName").value = "FirstName LastName"

        entry.Properties("givenName").value = "FirstName"

        entry.Properties("sn").Value = "LastName"

        entry.Properties("mail").value = "EmailAddress@Something.com"

 

        ' The follow attributes I believe to be the ones required for mail enabling

        ' (though I have not testing thoroughly to pinpoint exactly what is required)

 

        ' SMPT MUST be capitalized

        entry.Properties("targetAddress").value = "SMTP:EmailAddress@Something.com"

        entry.Properties("proxyAddresses").Value = New Object() {"SMTP:EmailAddress@Something.com"}

 

        ' To find the legacyExchangeDN, copy value from an existing contact

        entry.Properties("legacyExchangeDN").Value = ""

        ' mailNickName can not have spaces

        entry.Properties("mailNickName").Value = New String("FirstNameLastName").Replace(" ", "")

 

        ' Commit Changes to Active Directory

        entry.CommitChanges()

 

        ' Close connections to Active Directory

        entry.Close()

        ad.Close()

    End Sub


Create Contact in C# (I can not verify this code, I just used a converter)


private void CreateDistributionList()

{

    DirectoryEntry ad = default(DirectoryEntry);

    DirectoryEntry contacts = default(DirectoryEntry);

    DirectoryEntry entry = default(DirectoryEntry);

 

    // Create a conntaction to Active Directory

    ad = new DirectoryEntry("LDAP://MACHINENAME/DC=DOMAIN,DC=COM", "username", "password");

    // Find the OU to create the contact in

    contacts = ad.Children.Find("OU=Distrubtion Lists");

 

    // Create AD object

    entry = contacts.Children.Add("CN=LastName\\, FirstName", "group");

 

    // Fill out basic attributes

    entry.Properties("groupType").Value = 8;

    // 8 = Universal Group

    entry.Properties("displayName").Value = "Name";

    entry.Properties("sAMAccountName").Value = "Name";

    // I don't know if this is required

    entry.Properties("mail").Value = "EmailAddress@Something.com";

    entry.Properties("telephoneNumber").Value = "555-555-5555";

    entry.Properties("description").Value = "description";

 

    // The follow attributes I believe to be the ones required for mail enabling

    // (though I have not testing thoroughly to pinpoint exactly what is required)

 

    // SMPT MUST be capitalized

    entry.Properties("targetAddress").Value = "SMTP:EmailAddress@Something.com";

    entry.Properties("proxyAddresses").Value = new object[] { "SMTP:EmailAddress@Something.com" };

    // To find the legacyExchangeDN, copy value from an existing contact

    entry.Properties("legacyExchangeDN").Value = "";

    // mailNickName can not have spaces

    entry.Properties("mailNickName").Value = new string("FirstNameLastName").Replace(" ", "");

 

    // Commit Changes to Active Directory

    entry.CommitChanges();

 

    // Close connections to Active Directory

    entry.Close();

    ad.Close();

}


Create Distribution List in VB


Private Sub CreateDistributionList()

        Dim ad As DirectoryEntry

        Dim contacts As DirectoryEntry

        Dim entry As DirectoryEntry

 

        ' Create a conntaction to Active Directory

        ad = New DirectoryEntry("LDAP://MACHINENAME/DC=DOMAIN,DC=COM", "username", "password")

        ' Find the OU to create the contact in

        contacts = ad.Children.Find("OU=Distrubtion Lists")

 

        ' Create AD object

        entry = contacts.Children.Add("CN=LastName\, FirstName", "group")

 

        ' Fill out basic attributes

        entry.Properties("groupType").Value = 8 ' 8 = Universal Group

        entry.Properties("displayName").Value = "Name"

        entry.Properties("sAMAccountName").Value = "Name" ' I don't know if this is required

        entry.Properties("mail").Value = "EmailAddress@Something.com"

        entry.Properties("telephoneNumber").Value = "555-555-5555"

        entry.Properties("description").Value = "description"

 

        ' The follow attributes I believe to be the ones required for mail enabling

        ' (though I have not testing thoroughly to pinpoint exactly what is required)

 

        ' SMPT MUST be capitalized

        entry.Properties("targetAddress").Value = "SMTP:EmailAddress@Something.com"

        entry.Properties("proxyAddresses").Value = New Object() {"SMTP:EmailAddress@Something.com"}

        ' To find the legacyExchangeDN, copy value from an existing contact

        entry.Properties("legacyExchangeDN").Value = ""

        ' mailNickName can not have spaces

        entry.Properties("mailNickName").Value = New String("FirstNameLastName").Replace(" ", "")

 

        ' Commit Changes to Active Directory

        entry.CommitChanges()

 

        ' Close connections to Active Directory

        entry.Close()

        ad.Close()

    End Sub


Create Distribution List in C# (I can not verify this code, I just used a converter)


private void CreateDistributionList()

{

    DirectoryEntry ad = default(DirectoryEntry);

    DirectoryEntry contacts = default(DirectoryEntry);

    DirectoryEntry entry = default(DirectoryEntry);

 

    // Create a conntaction to Active Directory

    ad = new DirectoryEntry("LDAP://MACHINENAME/DC=DOMAIN,DC=COM", "username", "password");

    // Find the OU to create the contact in

    contacts = ad.Children.Find("OU=Distrubtion Lists");

 

    // Create AD object

    entry = contacts.Children.Add("CN=LastName\\, FirstName", "group");

 

    // Fill out basic attributes

    entry.Properties("groupType").Value = 8;

    // 8 = Universal Group

    entry.Properties("displayName").Value = "Name";

    entry.Properties("sAMAccountName").Value = "Name";

    // I don't know if this is required

    entry.Properties("mail").Value = "EmailAddress@Something.com";

    entry.Properties("telephoneNumber").Value = "555-555-5555";

    entry.Properties("description").Value = "description";

 

    // The follow attributes I believe to be the ones required for mail enabling

    // (though I have not testing thoroughly to pinpoint exactly what is required)

 

    // SMPT MUST be capitalized

    entry.Properties("targetAddress").Value = "SMTP:EmailAddress@Something.com";

    entry.Properties("proxyAddresses").Value = new object[] { "SMTP:EmailAddress@Something.com" };

    // To find the legacyExchangeDN, copy value from an existing contact

    entry.Properties("legacyExchangeDN").Value = "";

    // mailNickName can not have spaces

    entry.Properties("mailNickName").Value = new string("FirstNameLastName").Replace(" ", "");

 

    // Commit Changes to Active Directory

    entry.CommitChanges();

 

    // Close connections to Active Directory

    entry.Close();

    ad.Close();

}


 


One last bit of info



After you create a contact or distribution list it will not show up on the Global Address List until the scheduled update, probably over night. If you want to force an update you must run the following powershell command on the Exchange server.

Get-GlobalAddressList | Update-GlobalAddressList

Update

I just discovered that the reportToOriginator is required for certain spam filters. We recently switched to a new spam filtering service and our outgoing emails sent to distribution lists created this way were failing. Once set to TRUE, everything was wonderful again.