<

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

Published on
17,559 Points
10,559 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
Comment
  • 2
3 Comments
 
LVL 23

Expert Comment

by:TheCleaner
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?
0
 
LVL 37

Author Comment

by:Neil Russell
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.
0
 
LVL 23

Expert Comment

by:TheCleaner
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.
0

Featured Post

Protect Your Employees from Wi-Fi Threats

As Wi-Fi growth and popularity continues to climb, not everyone understands the risks that come with connecting to public Wi-Fi or even offering Wi-Fi to employees, visitors and guests. Download the resource kit to make sure your safe wherever business takes you!

Join & Write a Comment

Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
Did you know PowerShell can save you time with SaaS platforms? Simply leverage RESTfulAPIs to build your own PowerShell modules. These will kill repetitive tickets and tabs, using the command Invoke-RestMethod. Tune into this webinar to learn how…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month