Virtual Developer Workshop: Containerized Development with Docker
A distribution list can be created like a normal mailbox with only a small difference: It can contain other mailboxes and distribution lists as members for itself. A mailbox or a distribution list is created below the Site Container of an Exchange domain. Once this entity is created, depending on the replication timing, it becomes available on the Global Address List. This article tries to explain how to access the Exchange domain and create a distribution list and create a distribution list programmatically using C# and Active Directory.
This article assumes some basic knowledge on CDO and Exchange server.
Typical issues that arise when someone programmatically tries to create the distribution list is that they cannot create a distribution list if they are not connected to the server on the site; for example, if the user of Site1 tries to modify the details of a distribution list on a different site, say Site2, through the program, this won't be permitted. In this case, the user with administrator rights must log on again, using the ID that hosts the corresponding site.
Some other issues could be something such as finding all the connected sites and servers in an Exchange environment. Also, parsing the address book for some data using ADSI will likely be slow. This article and the sample program use an approach combining both CDO and ADSI to create a distribution list with C#. This can easily be extended to creating mailboxes also.
Microsoft Exchange Architecture
A Microsoft Exchange Environment can be configured to contain many sites under a domain. Although all of us might know this, this might be useful if we do a small preview of the basic details.
If a Microsoft.com domain is available as a root, there could be many sites configured under the root domain of Microsoft.com, such as London, New York, and Moscow. This has many advantages; for example:
- Easier localized management of users
- Logical classification of employees/users
- Faster access because of localized placement of servers
- All the mail addresses can be accessed together through a Global Address List
- And many more...
And, apart from this, each of the domains can contain many servers that can handle the mail delivery mechanisms to share the load of the site under the domain. The architecture looks something like this:
Typically, if a user wants to modify any distribution list members or any other distribution list data, the user has to have the relevant admin rights. The Microsoft Exchange Administrator program usually is used to make the modifications on these data on the distribution list. Occasionally, Outlook also can be used to modify the membership of the distribution list, provided the logged-on user is either an administrator or he is the owner of the distribution list. But whatever the case may be, cross-site modifications are not allowed. So, the program has to be careful to use the correct server to do the same.
Creating the Distribution List
A distribution list can be created by accessing the active directory. The object distinguished name of a distribution list will typically look like the following:
At the minimum, a distribution list needs two very basic attributes to be specified. One is the display name and the second is the alias. A distribution list or a mailbox can be created only under the Recipients container.
To create a distribution list under the Recipients container,
- Get the ADSI DirectoryEntry for the Recipients container.
- Create a distribution list by specifying "groupOfNames".
- Specify the other properties such as displaynames, smtp, x400, owner, and so forth.
- Ensure that the Security Descriptor is properly set for the owner attribute.
- Commit the changes to the AD.
The DirectoryEntry.Children.Add("aliasname","groupOfNames") class can be used to create a distribution list under the Recipients container. A call to this function returns an object for the DirectoryEntry for the newly created distribution list. This does not actually get updated until you call the DirectoryEntry.commitchanges method.
Note: If the Display Name contains/starts with special characters like #, the above DirectoryEntry.Children.Add function is called by specifying the Display Name instead of the Alias name of the distribution list and the Exchange Server is not able to recognize the object. Although it will be visible in the Recipients container when you try to access the object, it will say "The object is not found. The replication may not be complete." So, be aware of this point when creating the list.
After getting a pointer to the distribution list as an object of DirectoryEntry, the following properties are to be updated before calling CommitChanges.
This is denoted by the cn property name in Exchange. This can be updated by calling the DirectoryEntry.Properties["cn"]. Do call this once before committing the Changes. This ensures that the display name is updated properly.
This is denoted by the uid property in Exchange Server. This is the alias name for the distribution list and typically will be used to create the Object Distinguished name under the container.
E-Mail addresses property
There could be many types of e-mail addresses in an Exchange environment. They may be smtp, x400, ccmail, and so on. Set the relevant e-mail address. If it is smtp, the mail attribute should be set, and for X400 it is textencodedaddress.
When discussing the e-mail addresses, one point is worth mentioning. The Exchange server keeps all the e-mail addressing data under a node at SiteAddressing. This data can be pulled from an attribute called GateWay-Proxy, which is not available via ADSI, but it can be pulled using ADO.
Members of the distribution list
This is managed under the member property of Exchange. This is an array of the list of mailboxes or distribution lists.
This property is stored under the owner attribute of the distribution List. There will be a problem when you create the DL and assign an owner. Because the DL is freshly created, it won't have any SecurityDescriptor associated with it. To solve this problem, you can pull the SecurityDescriptor of the owner and assign it to the DL.
The Properties of Exchange 5.5 do not understand the LDAP naming with slashes. It returns an error saying Protocol Error. In such cases, use the comma-formatted LDAP Object Distinguished Names. I am not sure about the later versions of Exchange. Be sure to check this out.
Also, when setting some of the properties, an error may return saying that the property is not found. In those cases, use the DirectoryEntry.Properties.Add function to add the property. This is because the Exchange directory may not keep the property fields if it is not a required field. In such cases, adding the property will help.
The attached sample includes two parts. One is the set of classes that can be reused as such for any C# DL creation programs or may be extended. The second is the DL creation functional part. This extensively uses CDO libraries to find the necessary server names, site names, and the much-needed object distinguished names for many entities.
The attached sample project can be downloaded from the Project zip file.
There are two classes available in the DLManagement namespace that can be used in other C# programs. One class, called DistributionListManager, holds the utility functions that could be used for common operations required to create or modify the distribution list. The other class, DistributionList, holds the data regarding the distribution list.
These reusable classes can be downloaded from the Reusable Classes zip file.
Some of the functions in this DistributionListManager are described as below. All the functions in this class are static public members. Therefore, they can be used without instantiating this class.
- GetSites—This function can return a list of sites under an Exchange organization.
- GetOrganization—This function returns the Organization name for a CDO Address entry object
- IsLDAPEntryWithSlashes—Some properties of Exchange 5.5 need the entries with comma-separated names in object distinguished names. This function can be used to check whether the entry contains slashes.
- GetHomeServer—This can be used to find the Home server for a particular distribution list.
- UpdateDL—This function can be used to either create or modify a DL. This takes care of setting all the above-said properties, including adding the owner of the DL with its Security Descriptor.
- FindDL—This function can find and populate the details of a DL and return an object of the DistributionList class.
- FindSMTPAddressing—This function gets the SMTP addressing format for a site using ADO.
This class contains only data members to hold the properties of DLs. This can be used either to retrieve or update the distribution lists using the DLManager class.
This application was written with Visual Studio .NET 2003. The libraries used are as follows:
- Microsoft CDO 1.21 Libraries. These are available by default in your system if Outlook 2000 or above is installed.
- ADODB. This can be included from References --> Com --> Microsoft ActiveX Data Objects 2.6 & above.
About the Author
The author Muthukumar works as a consultant in a multi-national investment bank. He writes tools and applications related to Exchange Server and Outlook 2000. He runs a site http://www.codersource.net.