InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

How to get the Global Address List programatically

More Information

The Exchange Address Lists are not stored somewhere on the Exchange Store, neither are they directly stored within Active Directory. The only thing that is stored in the Active Directory database is a LDAP search filter that matches the participants of the address list.
To get a glimpse on these filters you can use ADSI Edit, a very handy tool to examine the Active Directory database.
BUT: As with regedit, the improper use of this tool may affect the stability of your Active Directory. You have been warned! The tool can be found on the Windows CDROM under the Support Tools.

(click to enlarge)
Anyway, take a look on the image to left. Under the node
CN=All Global Address Lists,CN=Address Lists Container,CN=Contoso Ltd,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=contoso,DC=local you will find all global address lists. In most cases, however, there will only be one.
The entry CN=Default Global Address Lists has a property called purportedSearch which contains the LDAP filter for this address list.
The default value is:

    1 (& (mailnickname=*)​(|(&(objectCategory=person)​(objectClass=user)​(!(homeMDB=*))​(!(msExchHomeServerName=*)))​(&(objectCategory=person)​(objectClass=user)​(|(homeMDB=*)​(msExchHomeServerName=*)))​(&(objectCategory=person)​(objectClass=contact))​(objectCategory=group)​(objectCategory=publicFolder)​(objectCategory=msExchDynamicDistributionList)))

This is the default LDAP filter for the Global Address List used by the Recipient Update Service (RUS).

Under the node CN=All Address Lists you will find the other address lists. As with the Global Address List, every list has its own node with the property purportedSearch set to the corresponding LDAP filter.

However, it would be very slow to actually use this LDAP filter. Instead, one would do the search the other way around: Every element which is listed in the global address book has the attribute showInAddressbook. It is much faster to use the following search filter:

    1 (&(mailNickname=*)​(showInAddressBook=<dn of addressbook>))

Simply replace the <dn of addressbook> with the the distinguished name of the address book you want to get. For the global address book, this would be CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,CN=<your organization>,CN=Microsoft

Depending on your programming language you can use different tools to do a LDAP search. If you are using Visual Basic or VBScript you’ll use the IADS Interfaces via the GetObject() command. In any .NET language you can use the System.DirectoryServices.DirectorySearcher class.

VBScript example

Here is an example using VBScript. Note that this example only searches the default domain of an Active Directory.

    1 optionexplicit


    3 dim oRoot

    4 dim oConnect, oCommand, rs

    5 dim strConfigurationContext

    6 dim oGAL

    7 dim strGalContainer

    8 dim strSearchRoot

    9 dim entry

   10 dim oSearchRoot


   12 'to get LDAP namespace

   13 set oRoot = GetObject("LDAP://RootDSE")

   14 strConfigurationContext = oRoot.Get("configurationNamingContext")


   16 'Open the global address list container

   17 strGalContainer = "LDAP://CN=All Global Address Lists,CN=Address Lists Container,CN=Contoso,CN=Microsoft Exchange,CN=Services, " & strConfigurationContext


   19 ' Iterate through global address lists. In this example, only the last one is used.

   20 foreach entry in GetObject(strGalContainer)

   21     set oGAL = entry

   22 next


   24 'Get the searchroot

   25 strSearchRoot = "LDAP://" & oRoot.Get("defaultNamingContext")


   27 'Using ADO to query the Active Directory for a particule user

   28 set oConnect = CreateObject("ADODB.Connection")

   29 set oCommand = CreateObject("ADODB.Command")


   31 'Open the connection

   32 oConnect.Provider = "ADsDSOObject"   

   33 oConnect.Open "Active Directory Provider"


   35 'Create a command object for this connection

   36 Set  oCommand.ActiveConnection = oConnect

   37 oCommand.CommandText = "SELECT samAccountName, givenName, sn FROM '" & strSearchRoot & "' WHERE msExchHideFromAddressLists <> true AND showInAddressBook = '" & oGal.Get("distinguishedName") & "' ORDER BY sAMAccountName ASC"


   39 'Create a recordset based on the ADO command

   40 set rs = oCommand.Execute


   42 while (not rs.EOF)

   43     wscript.echo rs.Fields("samAccountName") & " (" & rs.Fields("givenName") & " " & rs.Fields("sn") & ")"

   44     rs.MoveNext

   45 wend


Many thanks to Joe Richards for the hint on the showInAddressBook property.


Posted by Henning Krause on Sunday, February 27, 2005 12:00 AM, last modified on Monday, November 29, 2010 8:01 PM
Permalink | Post RSSRSS comment feed

Comments (2) -

On 8/18/2008 9:14:40 AM aaron United States wrote:


Hi, I was messing with permissions and i guess i accidently deleted my global address list.

I just recreated it using your default value, however my users still get an error in outlook saying &amp;amp;amp;amp;amp;amp;quot;invalid bookmark&amp;amp;amp;amp;amp;amp;quot; when trying to add a the new exchange server in the mail setup wizard.

Not sure how to fix this... are there more values I need to set besides the purportedSearch ?

On 1/17/2012 5:59:00 AM steve wrote:


thanks for this

 +Pingbacks and trackbacks (2)