<

How do we share our Global Address List (GAL) across different forests WITHOUT using federated services

Published on
19,065 Points
12,065 Views
5 Endorsements
Last Modified:
Approved
A commonly asked question on the site recently has been regarding how do I share the GAL between different forests? I want a list of Contacts representing all the users in a remote domain, How do i get them?

It's a problem I was posed with a little while back. Two domains in separate forests, with a full two way trust in place but how do we get a constantly up to date contact list of users in the "Other" forest?
So I set about writing a PowerShell script that would allow me to extract all the users in the "Other" domain and create a mail enabled contact in my domain.

It was decided that each contact would display as "Contact Name (Other Domain)"  for clarity when looking through the GAL.

The script creates the Contacts in the OU you specify and updates their key data such as phone numbers, office,  job Title, company name, department.

I present below the script I ended up with.  It works for me and for a few others who have adopted it. Feel free to use it yourself if you find it useful.  

To use the script you will need to edit the section of the script headed  "# Changes need to be made to all of the following #"
You will need to set the following:
$TargetForest - YOUR Domain Name
$TargetOU - Where to create your new contacts
$TargetDC - The FQDN of YOUR DC
$TargetContactSuffix - A Suffix string to apply to all contacts
And for the Remote Domain....
$SourceForest - REMOTE Domain name
$SourceDC - FQDN of a DC in $SourceForest
$SourceOU - Base OU to read users from the remote Domain

Finally the last thing you will need to do is to install the Quest QAD CommandLets (Available Here)

 
Add-PSSnapin Quest.ActiveRoles.ADManagement  
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010  
clear  
$Error.Clear()  
  
#############################################################  
#  Changes need to be made to all of the following          #  
#############################################################  
#MY Domain details.  
$TargetForest="yourdomainname.com"  
$TargetOU = "OU=External Contacts,DC=yourdomainname,DC=com" # Where contacts will go  
$TargetDC = "MyDc.yourdomainname.com"                       # Pref is for GC PDC  
$TargetContactSuffix = " (The other domain)"                # Appended to name i.e. "AUser Name (The other Domain name)"  
  
# SOURCE - Where to read remote domains users from  
$SourceForest="theotherdomain.com"                          # Domain name of Source of Contacts  
$SourceDC = "DC1.theotherdomain.com"                        # Name of any DC in source Domain  
$SourceOU = "OU=Myusers,DC=theotherdomain,DC=com"           # Base OU/container to read users from  
#############################################################  
#            end of config section                          #  
#############################################################  
  
#Connect to Source forest AD  
Connect-QADService -Service $SourceForest  
  
$SourceForestUsersToMigrate = Get-QADUser -SearchRoot $SourceOU  -SearchScope Subtree -LdapFilter "(homeMDB=*)" -SizeLimit 0  
  
#Connect to Destination Forest AD  
Connect-QADService -Service $TargetForest  
  
$UserCount =0  
$NewUsers = @()  
$MailErrors = @()  
  
$SourceForestUsersToMigrate | ForEach-Object  {  
  
        New-MailContact -DomainController $TargetDC  -Name ($_.DisplayName + $TargetContactSuffix) -DisplayName ($_.DisplayName + $TargetContactSuffix) -FirstName $_.FirstName -LastName $_.LastName -Alias ($_.FirstName +  ($_.LastName).ToUpper())  -OrganizationalUnit $TargetOU -ExternalEmailAddress $_.Email -ErrorAction SilentlyContinue  
                if ( $? -ne $true ) {   #new-mailcontact failed if $False  
#       Why did the creation fail?  
                        if ( $Error[0].exception.Gettype().fullname -eq "Microsoft.Exchange.Configuration.ObjectModel.ProxyAddressExistsException" ) {  
                                "Email address already Exists: " + $_.email  
                                $Contact = Get-Contact $_.UserPrincipalName    
                                If ($? -ne $true ) {  
                                        $MailErrors += ("Could not do " + $_.userprincipalname + ":" + $_.email + "`n")  
                                } else {  
                                        Set-Contact $Contact -Phone $_.PhoneNumber -Office $_.office -Title $_.title -Company $_.company -Department $_.department  
                                }  
                        }  
                }  
                else {  
                        "Email Conatact added: " + ($_.DisplayName + $TargetContactSuffix) + " : " + $_.email  
                        set-mailcontact -DomainController $TargetDC -Identity ($_.DisplayName + $TargetContactSuffix) -EmailAddressPolicyEnabled $false  
                        Set-Mailcontact -DomainController $TargetDC -Identity ($_.DisplayName + $TargetContactSuffix) -EmailAddresses $_.Email  
                        $NewUsers += ( $_.Email + " `n")  
                        $UserCount = $UserCount + 1  
                }  
        }  
$NewUsers  
$MailErrors

Open in new window


If you manage to enhance/improve it then please, let us all know.

The first enhancement I shall be working on myself is to add the facility for the script to delete contacts that you have for the remote domain where the user can no longer be found on the remote domain.
5
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free