Powershell – Exchange 2010 Auto-mapping mailboxes feature doesn’t work when groups grant permissions

active-directoryexchange-2010outlook-2010powershell

I have a shared mailbox that I need to deploy to one of our departments in an Exchange 2010 SP2 environment with Outlook 2010 clients. I'm trying to rely on the auto-mapping feature introduced by Exchange 2010 SP1, for obvious reasons, but it's not working.

On closer inspection, this would be because it doesn't work with groups, skillfully preventing it from becoming a useful feature for anyone with more than a handful of mail users to administer.

The above link contains a workaround PowerShell script to read a group's membership and directly add those members to have full access permissions, but this doesn't provide the functionality to update the auto-mapping as people join or leave the department.

Does any one know of a way to get this feature functional when groups are used to grant users full access permissions to a mailbox? (Or have any ides about how to approach the problem, even? Right now, I'm thinking of a Powershell script that updates the relevant AD attributes on a regular basis, but… there's gotta be a better way.)

Best Answer

I created this script when we ran into the same issue. Maybe it's not the prettiest thing in the world, but it gets the job done. I have a separate OU for the access groups and then another for the resources mailboxes. The groups and resource mailboxes use the same name except for an A- in front for the group.

e.g. A-RESMBX1 for the group name and REXMBX1 for the resource mailbox.

The script enumerates the groups in the groups OU and then the resource mailboxes in that OU. It then cycles through each group and finds the matching resource mailbox. When a match is found it enumerates the groups' users and then adds them to the msExchDelegateListLink attribute of the Resource Mailbox.

It will also remove users from the msExchDelegateListLink attribute that are no longer members of the associated access group. I have this running in a Scheduled Task on a DC.

Our need was due to high turnover of interns that needed to have access to a large number of resource mailboxes.

You'd need to update the LDAP paths to the OUs for $Groups & $ResMBXs as well as your DC name for $DomainController

Import-Module ActiveDirectory
$DomainController = "MYDOMAINCONTROLLER"
$Groups = Get-ADGroup -Filter * -SearchBase 'OU=Groups,OU=Resource Mailboxes,DC=mydomain,DC=com' -Server $DomainController | Sort-Object Name
$ResMBXs = Get-ADUser -Filter * -SearchBase 'OU=Resource Mailboxes,DC=mydomain,DC=com' -Server $DomainController -properties msExchDelegateListLink  | Sort-Object Name

Write-Host "Enumerating Groups and Resource Mailboxes..."
Write-Host ""

# IsMember function is borrowed from : http://gallery.technet.microsoft.com/scriptcenter/5adf9ad0-1abf-4557-85cd-657da1cc7df4
# Hash table of security principals and their security group memberships. 
$GroupList = @{}    

Function IsMember ($ADObject, $GroupName) 
{ 
    # Function to check if $ADObject is a member of security group $GroupName. 

    # Check if security group memberships for this principal have been determined. 
    If ($GroupList.ContainsKey($ADObject.sAMAccountName.ToString() + "\") -eq $False) 
    { 
        # Memberships need to be determined for this principal. Add "pre-Windows 2000" 
        # name to the hash table. 
        $GroupList.Add($ADObject.sAMAccountName.ToString() + "\", $True) 
        # Retrieve tokenGroups attribute of principal, which is operational. 
        $ADObject.psbase.RefreshCache("tokenGroups") 
        $SIDs = $ADObject.psbase.Properties.Item("tokenGroups") 
        # Populate hash table with security group memberships. 
        ForEach ($Value In $SIDs) 
        { 
            $SID = New-Object System.Security.Principal.SecurityIdentifier $Value, 0 
            # Translate into "pre-Windows 2000" name. 
            $Group = $SID.Translate([System.Security.Principal.NTAccount]) 
            $GroupList.Add($ADObject.sAMAccountName.ToString() + "\" + $Group.Value.Split("\")[1], $True) 
        } 
    } 
    # Check if $ADObject is a member of $GroupName. 
    If ($GroupList.ContainsKey($ADObject.sAMAccountName.ToString() + "\" + $GroupName)) 
    { 
        Return $True 
    } 
    Else 
    { 
        Return $False 
    } 
} 

Foreach ($gr in $Groups) {

         Foreach ($mbx in $ResMBXs) {
             $MBXName = "A-" + $mbx.Name
             $LDAPUser=[ADSI]"LDAP://$($DomainController)/$($mbx.distinguishedName)"

             if ($gr.Name -eq $MBXName) 
             {
              #Build an Array of DNs from each Group
              $Members = Get-ADGroupMember $gr -Server $DomainController
              if ($Members -ne $Null)
              {
                  Foreach ($mbr in $Members){


                     if($mbr.distinguishedName -ne $Null)
                     {
                        $LDAPUser.msExchDelegateListLink.Add($mbr.distinguishedName)
                        $LDAPUser.SetInfo()
                     }
                    $AddedUsers += $mbr.Name
                  }
              }
              Else {Write-Host -foregroundcolor darkyellow "Group contains no members..."; Write-Host ""}

              if($mbx.msExchDelegateListLink -ne $Null) {
                  $ACLUsers = $mbx.msExchDelegateListLink
                  Foreach ($ACLUser in $ACLUsers)
                  {
                    #Check if user is a member of the current group
                    #If not, remove from attribute
                    $user = [ADSI]"LDAP://$($DomainController)/$($ACLUser)"
                    $userDN = Get-ADUser $ACLUser -Server $DomainController
                    $mem = IsMember $user $gr.Name
                    If ($mem -eq $False)
                        {
                            $LDAPUser.msExchDelegateListLink.Remove($userDN.distinguishedName)
                            $LDAPUser.SetInfo()
                            Write-Host "The Following User was removed from: " -nonewline; Write-Host -foregroundcolor yellow $mbx.Name
                            Write-Host -nonewline -foregroundcolor darkyellow " " $UserDN.Name
                            Write-Host ""
                        }
                  }
                 }
              $Members = ""
              Write-Host "The Following Users were added to: " -nonewline; Write-Host -foregroundcolor yellow $mbx.Name
              Write-Host ""
              Write-Host -foregroundcolor darkyellow $AddedUsers
              Write-Host ""
              $AddedUsers = ""
             }
         }

      }