Monday, April 12, 2010

Exchange: Migrate from Exchange 2007 to Exchange 2010 Forest

Lets say you have an Exchange 2007 organization and an Exchange 2010 organization. Users have mailboxes in both organizations. The mailbox in organization B forwards to the mailbox in organization A through the use of a contact.

mailbox B --> contact in org B --> mailbox A

So the question is how to merge the mailboxes into a single mailbox in org B?

Option 1:
The first option will require Exchange 2007 to be running at least SP2. This option would be to backup then remove the mailbox and contact in org B, these can be replaced by a mail enabled user in org A which forwards to org B.

Define the users to be migrated

First create the variables that will be used to define the migration. For each user to be migrated, you will need to know: -
a) the email address that is the target address on the contact ($useremailorgA)
b) an email address that is common between the source and destination mailboxes ($useremailorgB)
c) the user account name of the destination mailbox user ($usernameorgB)

Perform a test migration

So lets define these values for a test user: -
$useremailorgA = "user@orgA.com"
$useremailorgB = "user@orgB.com"
$usernameorgB = "user"

Now lets create a test mailbox and contact on the target organization (make sure to edit this according to your situation): -

$fname = Read-Host "Enter the first name"
$lname = Read-Host "Enter the last name"
$password = Read-Host "Enter password" -AsSecureString
$extemail = Read-Host "Enter the TARGET email address for the contact"

$database = "GC-Temp"
$orgunit = "MEL"
$contactorgunit = "Users"

$alias = $fname + "." + $lname
$name = $fname + " " + $lname
$upn = $fname + "." + $lname + "@target.com.au"

$mymailbox = New-Mailbox -UserPrincipalName $upn -Alias $alias -Database $database -Name $name -OrganizationalUnit $orgunit -Password $password -FirstName $fname -LastName $fname -DisplayName $name -ResetPasswordOnNextLogon $false

start-sleep -s 5

new-mailcontact -Name $name -ExternalEmailAddress $extemail -OrganizationalUnit $contactorgunit

Set-Mailbox $mymailbox -ForwardingAddress $extemail


You might like to perform a PST backup of the target mailboxes before they are removed. Remember you must have Outlook 2010 installed on the Exchange server to do this: -

Get-mailbox | where {$_.PrimarySmtpAddress –eq $useremailorgB} | Export-mailbox –PSTFolderPath C:\PSTBackup


Now we must do something funky to "convert" the user mailbox and contact into a mail-enabled user that old emails will still reply to. To do this, the destination mail-user should have the following properties: -
a) An X500 address that matches the LegacyExchangeDN of the mailbox
b) An X500 address that matches the LegacyExchangeDN of the contact
c) All email addresses that were contained on the mailbox and contact
d) An email address xyz@orga.com.au where the contact forwarded to xyz@orga.com.au - this one is very important as in this case the X500 address does not appear to quite be enough.

To automate this, create a script that goes a little like below ). For this to work you will need to list users to be modifed in a CSV file that contains the following headings:
TargetUserName, CommonEmailAddress
(Note that this email address must exist on both the source and target mailboxes)

#IMPORT LIST OF USERS FROM CSV
$LIST = Import-CSV UserList.CSV

#CYCLE THROUGH EACH ROW IN CSV
FOREACH($USER in $LIST) {
$targetusername = $USER.TargetUserName
$commonSMTPaddress = $USER.commonemailaddress

#Locate Target Mailbox
$TargetMailbox = Get-Mailbox $targetusername
$TargetMailboxDN = $TargetMailbox.distinguishedname

#Locate Target Contact
$TargetContactDN = $TargetMailbox.ForwardingAddress.DistinguishedName
$TargetContact = Get-MailContact $TargetContactDN

#Determine Target Contact External Address
$TargetContactExternalAddress = $TargetContact.ExternalEmailAddress
$TargetContactExternalAddressString = [string]$TargetContactExternalAddress.AddressString

#Determine Target Mailbox Primary Address
$TargetMailboxPrimaryAddress = $TargetMailbox.PrimarySMTPAddress
$TargetMailboxPrimaryAddressString = [string]$TargetMailboxPrimaryAddress

#Retrieve email addresses on the Mailbox
$TargetMailboxLegacyExchangeDN = [string]$TargetMailbox.LegacyExchangeDN
$EmailAddresses = $TargetMailbox.EmailAddresses
$EmailAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]("X500:" + $TargetMailboxLegacyExchangeDN)

#Retrieve email addresses on the Contact
$TargetContactLegacyExchangeDN = [string]$TargetContact.LegacyExchangeDN
$EmailAddresses += $TargetContact.EmailAddresses
$EmailAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]("X500:" + $TargetContactLegacyExchangeDN)

#take the ALIAS of the contact target path and join it to the domain name of the mailbox then add it to the email addresses
$TargetContactExternalAddressAliasLocation = $TargetContactExternalAddressString.indexof("@")
$TargetContactExternalAddressAlias = $TargetContactExternalAddressString.Substring(0,$TargetContactExternalAddressAliasLocation)
$TargetMailboxDomainLocation = $TargetMailboxPrimaryAddressString.indexof("@")
$TargetMailboxDomain = $TargetMailboxPrimaryAddressString.Substring($TargetMailboxDomainLocation)
$FreeEmailAddress = $TargetContactExternalAddressAlias + $TargetMailboxDomain
If (-not $EmailAddresses -eq $FreeEmailAddress) {
$EmailAddresses += [Microsoft.Exchange.Data.proxyaddress] ($FreeEmailAddress)
Write-Host "Adding new email address..."
}
If ($EmailAddresses -eq $FreeEmailAddress) {
$FreeEmailAddress = "Already in list..."
}
#Provide information back to user
Write-Host "===================================="
Write-Host "MIGRATION OF:" $targetusername
Write-Host "===================================="
Write-Host "TargetMailbox: "$TargetMailbox.DisplayName
Write-Host "Target Mailbox Primary Email Address: "$TargetMailboxPrimaryAddress
Write-Host
Write-Host "TargetContact: "$TargetContact.DisplayName
Write-Host "Forwarding Address: "$TargetContact.ExternalEmailAddress.AddressString
Write-Host "Common Email Address (for matching purposes): "$commonSMTPaddress
Write-Host
Write-Host "Providing new email address free of charge: "$FreeEmailAddress
$EmailAddresses Format-Table Prefix,AddressString -wrap -autosize

#Confirm to proceed with merging the contact and mailbox
Write-Host "PLEASE PERFORM AN EXPORT OF ALL MAILBOXES AND CONTACTS TO BE MERGED PRIOR TO PERFORMING THIS TASK. USE GET-USER, GET-MAILBOX, and GET-MAILCONTACT TO PERFORM THIS BACKUP."
$myInput = Read-Host "Please confirm the merging of the above mailbox and contact by pressing y to continue consolidation"
if ($myInput -ne "y") {
"Conversion aborted at users request"
BREAK
}

#Disable the mailbox and contact
Disable-Mailbox $TargetMailbox -confirm:$false
Remove-MailContact $TargetContact -confirm:$false

#Mail-enable the user object
$TargetMailUser = Enable-MailUser -Identity $TargetUserName -ExternalEmailAddress $TargetContactExternalAddress
Write-Host "If there are no errors then the consolidation is complete for this user."

}

"Conversion of user from Mailbox to Mailuser complete."

Now once we define the above variables, we just run this script against it - your mailbox and contact will disappear and a new mail-user will appear in its place. and hopefully keep delivering mail, even replies to older emails!

There, now we have:

Mailuser B --> Mailbox A

Ready to migrate


We have now configured co-existence and prepared our environment for the migration. Now we need to make sure there is a common proxy address on each Mailuser B and Mailbox A. This would probably be alias@orgb.com. If there is not a common proxy address, you will need to make one by modifying the email policies.

Then we prepare the migration with the prepare-moveerquest:

#Now we need to make sure there is a common proxy address on each Mailuser B and Mailbox A. This would probably be alias@orgb.com. If there is not a common proxy address, you will need to make one by modifying the email policies.

#This command prepares the migration by linking the source and target mailboxes. Note that this step will convert the target mailuser into a mailbox object.

$useremailorgB = "user.name@target.local"
$RemoteDomainController = "source.DC.local"

Prepare-MoveRequest.ps1 -Identity $useremailorgB -RemoteForestDomainController $RemoteDomainController –UseLocalObject

This Prepare-MoveRequest creates a mailbox in the destination organization to correspond with the specified user, and with all required attributes (such as MsExchGUID – spelling?). The “UseLocalObject” is required if there is already an object in the destination with the same proxy addresses. In this case there is (we have a mail-enabled object that we created earlier). It will then delete the existing object and create a new one as per requirements. Mail should continue to flow as per normal at this stage. Note that you can only do this with a contact or mail enabled user in the target forest, you cannot use it to merge to an existing mailbox (this is why we converted the mailbox to a mail-enabled user in an earlier step!).

Then we go ahead and migrate the mailbox when we are ready:

#This step moves mailboxes between organisations - but must be run following the Prepare-MoveRequest command. Note that this step will create a contact in the source organisation which will continue to facilitate mail flow.
$UserEmailOrgB = "user.name@target.local"
$Cred = Get-Credential
new-moverequest -identity $useremailorgB -RemoteLegacy -TargetDatabase "Mailbox Database 0698034315" -RemoteGlobalCatalog source.DC.local -RemoteCredential $Cred -TargetDeliveryDomain 'target.local'

The new-moverequest handily also creates a contact in the source organization once the mailbox has been moved across.

Now that was easy wasn't it!

Option 2:
Second option is to export the mailbox from OrgA and import it into the mailbox in Org B.
This option requires installing the Exchange 2007 SP2 admin tools on a workstation with Office 2007 or later. This workstation will be used to export the mailboxes to PST.

The process would have to go a little like this:
1. Start of outage
2. Disable forwarder in OrgB (Powershell)
3. Remove contact in OrgB (Powershell)
4. Assign SOURCE email address to mailbox in OrgB (Powershell)
5. Enable the forwarder in OrgA (Powershell)
6. Export mailbox from Exchange 2007 to PST (Powershell)
7. Import mailbox to Exchange 2010 (Powershell)
8. Assume that there are no special email addresses on the OrgA mailbox.

$useremailorgA = user@orgA.com
$useremailorgB = user@orgB.com
$usernameorgB = useraccountname

Disable the forwarder in OrgB:
get-mailbox where {$_.PrimarySmtpAddress -eq $useremailorgb} set-mailbox -ForwardingAddress $disabled
Remove mail properties from the contact in OrgB:
get-contact where {$_.WindowsEmailAddress -eq $useremailorgA} disable-mailcontact
Assign SOURCE email address to proxy addresses to mailbox in OrgB:
$mailboxes = Get-Mailbox where {$_.PrimarySmtpAddress -eq $useremailorgb}
foreach ($mailbox in $mailboxes)
{
$newaddress = $mailbox.samAccountname + "@secondaddress.contoso.com"
$mailbox.EmailAddresses += $newaddress
Set-Mailbox -Identity $mailbox.alias -EmailAddresses $mailbox.EmailAddresses
}
Note: ADModify would probably work just as well here.
Enable the forwarder in OrgA
get-mailbox where {$_.PrimarySmtpAddress -eq $useremailorgb} set-mailbox -ForwardingAddress ghunt@uniqueaddress.com

I am up to here, because forwarding to an address in the other org will not be possible unless we first remove the target.com.au address from the orgA user.........TBC!!!