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.

5 comments:

  1. This was great, thanks a lot!

    ReplyDelete
    Replies
    1. You're welcome! As long as I've helped at least one person then I'm glad I spent the time to write this up.

      Delete
  2. Many thanks Paul !
    I was searching long to find out this and get it working.
    My challenge was to synchronize an email address Sql table with the mail enabled contacts in Exchange.
    Distribution list is updated automatically with criterias

    You saved my time, so thank you for having shared this.

    Jm

    ReplyDelete
  3. Wow thanks for this. You saved the day!

    Daniel

    ReplyDelete
  4. Just updated. I discovered the reportToOriginator attribute is needed for certain spam filters when sending to distribution lists. Add this line when creating a distribution list with code.
    entry.Properties("reportToOriginator").Value = "TRUE"

    ReplyDelete