Anjani Singh

How To Access Nested Outlook Distribution List Entry Through VSTO?

On the Microsoft exchange server, there can be multiple distribution list and each list can either directly contain users or it can contain another distribution list nested within it. When we create Outlook add-in, we may need to access these lists or outlook users programmatically. Here, I am describing couple of ways to access distribution list entry which is a part of another distribution list entry using Visual Studio Tools for office (VSTO).

The approach described here can be used while fetching first level DL or while fetching user members within any level DL. Both User and Distribution list are derived from AddressEntry class because of the obvious reason that members of Distribution list can be both user or another list. Derived Class for users is ExchangeUser and derived class for Distribution List is ExchangeDistributionList.

AddressEntryin turn is obtained from collection AddressEntries properties of AddressList object. Address Lists which contain all the Distribution lists for your exchange server can be obtained as shown below:


outlook = new


); Outlook.AddressLists addrLists = outlook.Application.Session.AddressLists;


Now Consider an example of exchange server where we have Distribution List Hierarchy as:

Nested Outlook Distribution List

For Instance, we have to fetch the Distribution list-‘Dev Team Delhi’, ‘Dev Team Mumbai’ and ‘Dev Team Chennai’– present inside the parent Distribution List ‘Dev Team’ list .

AddressLists (denoted by variableaddrLists in above code) does not contain any function to find the AddressList object. AddressLists can be obtained through iterating over complete collection. Sometimes Distribution lists can be thousands in number.

In our example of finding Members (Distribution list) for ‘Dev Team’ Distribution List, one of the approach can be:



> GetDevTeamByCity() { List<string

> devTeamRegions = new


>(); try

{ var

outlook = new


); Outlook.AddressLists addrLists = outlook.Application.Session.AddressLists; // All Address List collections


(Outlook.AddressList addrList in

addrLists) { if

(addrList.Name.Equals("All Distribution Lists"

, StringComparison.OrdinalIgnoreCase)) { foreach

(Outlook.AddressEntry addrEntry in

addrList.AddressEntries) { if

((addrEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeDistributionListAddressEntry) && addrEntry.Name.Equals("Dev Team"

, StringComparison.OrdinalIgnoreCase)) // Parent DL of Dev Team across regions

{ foreach

(Outlook.AddressEntry regionEntry in

addrEntry.Members) { if

(regionEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeDistributionListAddressEntry) { // Checked for type of DL

devTeamRegions.Add(regionEntry.Name); } } return

devTeamRegions; } } } } } catch

(System.Exception ex) { throw

; } return

devTeamRegions; }


The above code returns required list of Distribution list members in the form of list of strings. Here, we first find main Distribution List or AddressList named ‘All Distribution Lists’ from AddressLists collection of outlook. Then we iterate over it and find parent list ‘Dev Team’ for required Distribution lists. Internally, data is fetched from Outlook COM object. This COM object is responsible for interacting with Exchange server.

Also note, in the innermost loop, AddressEntryUserType is checked for type of olExchangeDistributionListAddressEntry to confirm it is of type ExchangeDistributionList before returning the list of string containing ‘Dev Team Delhi’,’Dev Team Mumbai’,’Dev Team Chennai’.

Once the required list is found we may have to delve deeper for finding user member in list. For instance, finding users in ‘Dev Team Delhi’. For this, the required check should be done for

olExchangeUserAddressEntry type and then AddressEntry can be typecasted to ExchangeUser Type as shown below:


(userEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry) { Outlook.ExchangeUser userInfo = userEntry.GetExchangeUser(); var

Email = userInfo.PrimarySmtpAddress, var

FirstName = userInfo.FirstName, var

LastName = userInfo.LastName }


In the above example with multiple hierarchy of Distribution list, there were only three Distribution lists. But in real scenario, there can be thousands of Distribution lists which need to be traversed through forEach loop because each level can have multiple lists.

Here is a second approach to find the Distribution list contained within another Distribution list.


outlook = new


); Outlook.AddressLists addrLists = outlook.Application.Session.AddressLists; // Same till here

Outlook.AddressList addrEntryMain = addrLists["All Distribution Lists"

]; // finding the main DL directly

Outlook.AddressEntries addEntries = addrEntryMain.AddressEntries; // Getting AddressEntries property which is list of AddressEntry

Outlook.AddressEntry Silo = addEntries["Dev Team"

]; // Finding directly without foreach loop.


(Outlook.AddressEntry addrEntry in

Silo.Members) { if

(addrEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType. olExchangeDistributionListAddressEntry) { devTeamRegions.Add(addrEntry.Name); } }


Same results can be obtained from this approach. Here, I directly access‘Dev Team’by addEntries [‘Dev Team’].

Concluding Points

The second approach does not require iterating over all the Distribution Lists, making code simpler and elegant. Also, in the first approach developer may tend to use nested ForEach loop to reach ‘Dev Team’ assuming that it is nested inside ‘Product Team’, while in our case it was directly accessible under ‘All Distribution Lists’. Hierarchy didn’t make any difference here. The approaches which I presented can be used to fetch first Level DL or nested DL or even while fetching the Users within DL. When you have too many DL’s, the second approach shows significant advantage.


Related Articles


NHibernate, Linq and Lazy Collections

For the past few months we have been busy building a services framework for one of our clients so that they can build all of their enterprise web services without ever having to worry about the cross cutting concerns and... Read more

Page Redirects using Spring.NET

Who is responsible for page redirects in ASPNET MVP – The View or the Presenter None of the above, it is you :) On a serious note, it is the View as one shouldn’t pollute the Presenter with the page navigation... Read more