The Usual Tech Ramblings

Exchange 2007/2010 and Hiding Mailboxes

Like any large organization, we have automated processes that go and happily disable user accounts on termination. This process looks in our HR database for certain flags, and reacts accordingly. As part of the termination/disabling process, it’ll also flag their email account to be hidden from the Exchange Global Address List (GAL).

In Exchange 2003 hiding accounts from the GAL used to handled by an Active Directory (AD) user attribute called msExchHideFromAddressLists. When this was set to TRUE, the user would be hidden from the GAL. Our HR applications toggle this flag for users that are disabled to hide them away from other users.

This process all worked fine for a long time, until Exchange 2007 rolled around. I guess there was plenty of push to allow you to hide a user from all the GALs, but still allow specific GALs to have those users in. So Microsoft introduced a new AD user attribute called showInAddressBook. The problem now appears that if you toggle the msExchHideFromAddressList, but have a value set for showInAddressBook, the user accounts are no longer hidden in the GAL mentioned in the latter attribute.

Can anybody see where this is going? Yup, it appears that all the user accounts were getting the default GALs assigned to the showInAddressBook attribute, so even when they were having the option to hide the user, they were still showing up1. This was causing problems as people that were disabled/terminated were still showing up, and causing some confusions and concerns.

I started to poke around, and bashed together a quick PowerShell script that will walk through all disabled users that have a showInAddressBook attribute, it’ll then wipe out that attribute.

$ldapFilter = '(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2)(showInAddressBook=*))'
$ldap=[ADSI]"LDAP://OU=Disabled Accounts,DC=DOMAIN,DC=TLD,DC=PVT"

$srch = New-Object DirectoryServices.DirectorySearcher($ldap)
$srch.Filter = $ldapFilter
$foundUsers = $srch.findAll()

$foundUsers | % {
       $adUser = $_
       $props = $adUser.Properties
       $objUser = [ADSI]$("LDAP://{0}" -f $props.get_Item('distinguishedName').Item(0))
       $objUser.PutEX(1,'ShowInAddressBook', $null)

If you’ve not seen LDAP queries before, they work by starting with the operator (and, or, etc), and then the objects that they apply to. So in the example above, it reads as such:

(objectClass=user) AND (userAccountControl:1.2.840.113556.1.4.803:=2) AND (showInAddressBook=*)

It can get a little more complicated when you start stringing together multiple options such as AND and OR operators, and various combinations of them. In this example, we’re going for pretty simple.

I then used the .NET libraries System.DirectoryServices.DirectorySearcher. This uses the LDAP query specified, and returns all matching results. Next was a case of walking through the results, and fetching a DirectoryEntry object to edit the properties. In this case we’re setting it to $null which removes it.

After letting this script run over about 25k users disabled users, it cleared up the fluff in the GAL, and made HR happy.

  1. As a weird side-note to this, if you check the box to hide the user in the Exchange management suite, it removes the showInAddressBook flag on its own, same for the PowerShell options too.