Exchange 2010, Exchange 2013, Office 365, PowerShell

Migration Preparation script

This script idea came up after being involved in a migration project.

Published: 2013-05-22
Updated: 2013-05-24
Version: 1.1

It’s purpose with this script is for getting Quest Migration Manager (QMM) being able to match objects between domains. In a scenario with one-way trust and not being able to use Quest Migration Manager AD or any other tool for providing the SIDHistory into the AD objects. Users, mailboxes and mail contacts are already created, where the contacts are used for having a global address list (GAL) object they can send emails to.

Using QMM you can match by Username, Mailaddress or SIDHistory. In my case the username differs and the SIDHistory is not available (not allowed being copied into the target AD).

I created four different functions within this script, one called “Export-SourceInformation”, which should be used in the source environment. It will export the information from the source regarding Name, DisplayName, PrimarySmtpAddress, RecipientTypeDetails and save it into a CSV file called “users.csv”.

Then bring the CSV file into the target environment. This CSV file should be used as a control file if you don’t want to run all users at the same time (run some tests before running all of them in one batch).
I would recommend a couple of smaller batches for testing the functions before deploying it in full scale.

There is a function called “Verify-TargetInformation”, which uses the CSV file called “users.csv” and retrieves the Name and PrimarySmtpAddress for each object in the CSV file.

Another function is called “Set-SourceAddress”, this part takes care of the target account.
It uses the file called “users.csv” and checks whether there are any contacts for these mailboxes, if there are the mail contact will be deleted and the mailbox forward settings will be removed together with making sure that the mailbox is showed in the GAL. But before any changes are done, the current configuration for both the mail contact and the mailbox object are being saved into a CSV file called “targetinformation.csv”.

Last but not least, the function called “Rollback-TargetInformation” is used for putting back the PrimarySmtpAddress to the value that it was prior to the change, this by using the CSV file “targetinformation.csv”. When the Directory Synchronization have successfully matched the mailboxes this function should be runned for having back the correct information.

You can use this for free, without any guarantee or warranty and at your own risk.
Feel free to post about it, just make sure to link my blog and blogpost.

Download the script

##################################################################################### 
# Filename: Migration-Preparation-testlabs.ps1  
# Description: 
# This PowerShell script exports information, configures objects and prepares for 
# Quest Migration Manager EX Directory Synchronization 
# 
# Usage: Import-Module Migration-Preparation-testlabs.ps1 
# Start with importing the module, then Starting function: Export-SourceInformation; 
# Set-SourceAddress; Rollback-TargetInformation; Verify-TargetInformation 
# 
# Version: 1.1
#
# Changelog:
# v1.1 - Introduced LegacyExchangeDN - X500 preparation
#
# Jonas Andersson, MCC 2011 & 2012 
# http://www.testlabs.se/blog 
# Twitter @jonand82 
#####################################################################################

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin -ErrorAction SilentlyContinue

## Exporting the SMTP information from Source mailboxes 
Function Export-SourceInformation(){ 

    $filename = "users.csv" 

    $users = Get-Mailbox -resultsize unlimited | Select Name,DisplayName,PrimarySmtpAddress,RecipientTypeDetails,LegacyExchangeDN
    $users | Export-CSV $filename -notype -Encoding Unicode 

}

## Changing Target mailboxes to Source PrimarySmtpAddress for QMM to match on it 
Function Set-SourceAddress(){ 

    $data = Import-CSV .\users.csv 
    $filename = "targetinformation.csv" 

    ## Saving Target Information into CSV file before changing 
    $MasterList = @() 
    Foreach($t in $data) 
    { 
        $str = $t.displayname 
        $MyObject = New-Object PSObject -Property @{ 

        Name = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").Name 
        DisplayName = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").DisplayName 
        PrimarySmtpAddress = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").PrimarySmtpAddress 
        RecipientTypeDetails = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").RecipientTypeDetails 
        Email = ((Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").EmailAddresses -Join ";") 
        DeliverToMailboxAndForward = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").DeliverToMailboxAndForward 
        ForwardingAddress = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").ForwardingAddress 
        ForwardingSmtpAddress = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").ForwardingSmtpAddress 
        HiddenFromAddressListsEnabled = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").HiddenFromAddressListsEnabled 
        LegacyExchangeDN = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").LegacyExchangeDN
        ContactName = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").Name 
        ContactDisplayName = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").DisplayName 
        ContactPrimarySmtpAddress = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").PrimarySmtpAddress 
        ContactEmail = ((Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").EmailAddresses -Join ";") 
        ContactExternalEmailAddress = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").ExternalEmailAddress 
        ContactHiddenFromAddressListsEnabled = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").HiddenFromAddressListsEnabled

        } 

        $MasterList += $MyObject 
    } 

    $MasterList | Export-Csv $filename -NoTypeInformation -Encoding Unicode 
    Write-Host "Information is saved into the CSV file: $filename" -ForegroundColor White 

    Foreach($i in $data) 
    { 
        $str = $i.displayname 

        ## Removing mail contacts for Source users 
        $c = Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'" 
        Write-Host $c -ForegroundColor Yellow 

        ## Multiple matching, no changes will be done 
        if ($c.count -ge 1) 
        { 
            Write-Host "ERROR: Multiple matching" 
            Write-Host "Matches: $c.count" 
            return 
        } 

        ## Unique contact found, removing it 
        if ($c.count -eq $null) 
        { 
            Write-Host "Unique matching: $c" 
            Write-Host "Removing the mail contact object for: $c" 

            Remove-MailContact -Identity $c -Confirm:$false 

        } 

        ## Starting the configuration for Target Mailboxes 
        $u = Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'" 

        Write-Host $u -ForegroundColor Yellow 

        ## Multiple matching, no changes made 
        if ($u.count -ge 1) 
        { 
            Write-Host "ERROR: Multiple matching" 
            Write-Host "Matches: $u.count" 
            return 
        } 

        ## Setting the Source PrimarySmtpAddress on the Target Mailboxes 
        if ($u.count -eq $null) 
        { 
            Write-Host "Unique matching: $u" 
            Write-Host "Setting Source SMTP as PrimaryAddress for matching using QMM" 
            Write-Host "Configuring the mailbox for showing up in GAL and remove the forwarding configuration"
            Write-Host "Adding the LegacyExchangeDN as X500 for Outlook auto-complete cache"
 

            $email = $i.PrimarySmtpAddress
            $x500 = $i.LegacyExchangeDN

            Set-Mailbox -Identity $u -ForwardingAddress $null -DeliverToMailboxAndForward:$false -HiddenFromAddressListsEnabled:$false -PrimarySmtpAddress $email -EmailAddressPolicyEnabled:$false 

            $ProxyAddresses = (Get-Mailbox -Identity $u).EmailAddresses
            $ProxyAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]("X500:$x500")
            Set-Mailbox -Identity $u -EmailAddresses $ProxyAddresses
        } 

        else 
        { 
            Write-Host "No match" 
            return 
        } 

    } 

    Write-Host "" 
    Write-Host "#################################################################" -ForegroundColor White 
    Write-Host "# First run the Verify-TargetInformation..                        #" -ForegroundColor White 
    Write-Host "# Start the QMM Synchronization for matching Source <-> Target  #" -ForegroundColor White 
    Write-Host "# Finally run the Rollback-TargetInformation when sync is done  #" -ForegroundColor White 
    Write-Host "#################################################################" -ForegroundColor White 
    Write-Host "" 
}

## Rollback of Target PrimarySmtpAddress 
Function Rollback-TargetInformation(){ 

    $data = Import-CSV .\targetinformation.csv 

    $MasterList = @() 
    Foreach($i in $data) 
    { 

        $str = $i.displayname 
        $user = Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'" 

        ## Predicts there is only one @testlabs.se address 
        $pri = Get-Mailbox -Identity $user | Select-Object -ExpandProperty EmailAddresses | Where-Object {$_.SmtpAddress -like '*@testlabs.se'} | Select-Object SmtpAddress 
        $adr = $pri.SmtpAddress 

        Write-Host "Configuring mailbox: $user with adress: $adr" -ForegroundColor White 
        Set-Mailbox -Identity $user -PrimarySmtpAddress $adr -EmailAddressPolicyEnabled:$False 

    } 

}

## Verifying the Target PrimarySmtpAddress 
Function Verify-TargetInformation(){

    $data = Import-CSV .\users.csv 

    $filetime = (get-date -format yyyyMMddhhmm) 
    $filename = "verify-$filetime.csv" 
    $MasterList = @() 

    ## Verifying the PrimarySmtpAddress 
    Foreach($i in $data) 
    { 

        $MyObject = New-Object PSObject -Property @{ 

            Name = (Get-Mailbox -Identity $i.PrimarySmtpAddress).Name 
            PrimarySmtpAddress = (Get-Mailbox -Identity $i.PrimarySmtpAddress).PrimarySmtpAddress 
            Database = (Get-Mailbox -Identity $i.PrimarySmtpAddress).Database
            EmailAddresses = ((Get-Mailbox -Identity $i.PrimarySmtpAddress).EmailAddresses -Join ";") 
        } 

        $MasterList += $MyObject 

    } 

    $MasterList | Export-Csv $filename -NoTypeInformation -Encoding Unicode 
    Import-CSV $filename 

    Write-Host "" 
    Write-Host "SMTP Verification is saved into the CSV file: $filename" -ForegroundColor White 
    Write-Host "" 
}
Tagged , , , , , ,