One of the common tasks of Exchange Administrator is to add Exchange Address Book Policy to a user. Depending on needs of organization there may be a need to add address book policies based on their group membership which often are inside other groups. Below solution helps to solve this task. In our case this little script runs every 24 hours making sure the group membership is updated in Global Address Book properly. There's also an updated version of this article, with newer, updated code that can be found here.
Solution
Administrator needs 2 methods to be able to set address book properly:
function Get-GroupMembershipRecursive ($group) { $SubGroup = @{} $AllMembers = @() if(!$group) { $group = Read-Host "Please enter the groups display name" } if ($group.Contains("'")) { $group = $group.Replace("'",'"') } if ($group -eq "/?") { Write-Host "Usage:" Write-Host "" Write-Host "Get-GroupMembershipRecursive -group <group name>" Write-Host "" Write-Host "or Get-GroupMembershipRecursive <group name>" Write-Host "Returns an object containing multiple values." break } $validate = Get-Group $group if ($validate.RecipientTypeDetails.ToString() -match "mail") { $searchGroup = Get-DistributionGroupMember $group #write-host 1.1 $searchGroup if ($searchGroup) { foreach ($member in $searchGroup) { $membertype = $member.RecipientTypeDetails #if($membertype -match "Group") if ($membertype -match "MailUniversalSecurityGroup" -or $membertype -match "MailUniversalDistributionGroup") { $samname = $member.SamAccountName.ToString() if ($SubGroup.ContainsKey($samname) -eq $true) { Write-Output "^ already seen group member (stopping to avoid loop)" } else { #write-host 1.6 $samname " or " $member.DisplayName $SubGroup.Add($samname,$member.DisplayName.ToString()) } } else { if($member.PrimarySmtpAddress -and $member.RecipientTypeDetails -notcontains "group") { $obj = new-object psObject $obj | Add-Member -membertype noteproperty -Name GroupMember -Value $member.name $obj | Add-Member -MemberType noteproperty -Name Group -Value $group $obj | Add-Member -MemberType noteproperty -Name SubGroup -Value $group $obj | Add-Member -MemberType NoteProperty -Name RecipientType -Value $member.RecipientType $obj | Add-Member -MemberType NoteProperty -Name PrimarySmtpAddress -Value $member.PrimarySmtpAddress $AllMembers += $obj } } } } else { $UnknownGroup.add($group,1) } if($SubGroup.Values.Count -gt 0) { #write-host 1.5 $SubGroup.Values.Count foreach ($subGroup in $SubGroup.values) { #DisplayMembers $subGroup #write-host 1.4 $subgroup "or " $SubGroup.Values $searchGroup = Get-DistributionGroupMember $subGroup #write-host 1.2 foreach ($member in $searchGroup) { $obj = new-object psObject $obj | Add-Member -membertype noteproperty -Name GroupMember -Value $member.name $obj | Add-Member -MemberType noteproperty -Name Group -Value $group $obj | Add-Member -MemberType noteproperty -Name SubGroup -Value $subGroup $obj | Add-Member -MemberType NoteProperty -Name RecipientType -Value $member.RecipientType $obj | Add-Member -MemberType NoteProperty -Name PrimarySmtpAddress -Value $member.PrimarySmtpAddress $AllMembers += $obj } } } if ($UnknownGroup.Keys.Count -gt 0) { foreach ($LostGroup in $UnknownGroup.keys) { $obj = new-object psObject $obj | Add-Member -membertype noteproperty -name GroupMember -Value "Cannot enumerate group" $obj | Add-Member -MemberType noteproperty -Name Group -Value $group $obj | Add-Member -MemberType noteproperty -Name SubGroup -Value $LostGroup $obj | Add-Member -MemberType NoteProperty -Name RecipientType -Value "" $obj | Add-Member -MemberType NoteProperty -Name PrimarySmtpAddress -Value "" $AllMembers += $obj } $UnknownGroup.Clear() } } else { Write-Output "$group does not appear to be mail enabled." } Write-Output $AllMembers } function SetAddressBookPolicy ([string] $AddressBookPolicy, [string] $SetOnGroup) { $members = Get-GroupMembershipRecursive $SetOnGroup #$members | ft GroupMember, Group, SubGroup, RecipientType, PrimarySmtpAddress -AutoSize foreach ($member in $members) { if ($member.RecipientType -eq "UserMailbox") { Set-Mailbox $member.PrimarySmtpAddress -AddressBookPolicy $AddressBookPolicy } } }
Usage of those methods:
SetAddressBookPolicy -AddressBookPolicy "<addres_book_policy>" -SetOnGroup "<distribution_group"
Get-GroupMembershipRecursive method is supportive method to make sure that each member of group within group will also get the Address Book Policy applied. Remember to use following commands to make sure the Global Address List, Address Lists and Offline Address Book are all up to date.
Get-GlobalAddressList | Update-GlobalAddressList Get-AddressList | Update-AddressList Get-OfflineAddressBook | Update-OfflineAddressBook
Notes
Please be aware that the script doesn't actually display anything during setting of address book policy. Only warning are displayed if the address book is already assigned to the mailbox.