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

Neil RussellSolution Development Specialist
Published:
Updated:
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
14,172 Views
Neil RussellSolution Development Specialist

Comments (3)

Neilsr,

This works fantastic, except for one thing.  Is there a way to prevent the target forest from creating an SMTP address for the users in the target domain?

Example:

Bob@SourceForest.com email address gets created
Bob@TargetForest.com also gets created but set to secondary address

Or does it even matter?  It doesn't appear that it has affected anything but I didn't know if that would cause any issues or not.

Also, in the future if I wish to use federation can I simply delete the contacts before federating?
Neil RussellSolution Development Specialist

Author

Commented:
I am not 100% what you are getting at with the Bob@ question sorry. Could you explain in more detail?


Deleting contacts in exchange is a nightmare!! Dont forget that outlook remembers the contact reference stored in exchange once you have used it once. If you delete a contact from exchange and then click reply on an email to that contact in outlook thet you had BEOFRE you deleted the contact and recreated it, it will fail with a contact not found.
Thanks for responding.  I figured it out.  The question was in relation to the recipient policy creating them an email address in the target domain.

So if I understand you right, once I go to delete all of these contacts and setup federation (or in our case I think we'll be using GALSYNC from netsec, then at that point I will need to send out a global email telling people to stop replying to the old contact?  The new contacts in the future wouldn't have the append info you have in your script, just their normal information.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.