Tuesday, December 12, 2006

Exchange Distribution Lists and WebDAV

Download Sample Code

I encountered an interesting side project recently where I wanted to retrieve information about distribution lists on a local Exchange Server from a web-based application.

I didn't want to use CDO/MAPI directly for various reasons, so I looked into the WebDAV api available for querying Exchange via web requests. I found some helpful information here, and was quickly able to produce a class to consume distribution list data for use in my app.

The basic query for retrieving all distribution lists from a particular folder (where folder is the RootURI below) is:

<?xml version=\"1.0\"?>

<D:searchrequest xmlns:D = "DAV:" >

<D:sql>SELECT "urn:schemas:contacts:cn\", "urn:schemas:contacts:members\", "DAV:displayname" FROM RootURI WHERE "DAV:ishidden" = false AND "DAV:isfolder" = false AND "DAV:contentclass" = 'urn:content-classes:group'</D:sql>

</D:searchrequest>

DAV content-classes are found via mappings from PR_MESSAGE_CLASS and PR_CONTAINER_CLASS properties. The schema references to specific properties in Exchange are derived from the Exchange Server schema. In the above example, we want the property cn from the urn:schemas:contacts namespace. The uri we query should contain contact items whose content-class is of type group.

Now, in order to figure out where all these properties live, and what you can expect can be challenging. You can start with the properties reference by namespace on MSDN. These will tell you the content-class. Or, as I did here, you can use a tool like IndependentDav to get a look at what is returned from the server. I don't think the tool is necessary once you have a handle on where things come from, but it can difficult to track some things down because mappings between Exchange Store schema content-classes and DAV content-classes are not 1:1 and the properties reference gives the content-class of the Exchange Store schema. Finally, you can query the store at a uri without limiting the return values, and look through the query results manually.

Getting on with the distribution lists then, I created a helper class to make the requests and manage the two part process of first constructing a DistributionList class, then filling the members of the list with a seperate query. I pass the streamed response from the query directly to the constructor of the DistributionList class. The code is long and cumbersome, so it's better to just look at it in the sample.

The list members are actually not found via webDAV directly, but a query to the OWA server services as described here. I created a ListMemberList class to hold ListMember classes. The constructor on the list parses each member in the response, and set it as a property on the DistributionList class.  

When its all said and done, I can use the management class to get the DL's from the configured server with very little overhead, and - best of all - no interop.

Submit this story to DotNetKicks

2 comments:

Danijel said...

Hi Jeff,
Your sample Downloadlink is down. I would like to use your classes, as I try to enumerate the DL member, but was not successful. Could you please send my the sample to mriced@gmx.de.
regards,
Danijel

gabe19 said...

Thanks for the heads-up danijel, the link has been fixed.