Exchange Online Cross-tenant mailbox migration (preview)

Hi All,

There is a Preview for M365 Tenant to Tenant Migration of Exchange Mailboxes. I've tested this in my Lab. Took me several Days to complete the Migration or until i understand everything correctly and had everything fixed.

Cross-tenant mailbox migration (preview)

I've created this Overview to explain it a bit more. Here are all prerequisits to create a Tenant to Tenant (aka Cross-tenant) Mailbox Migration.



Target Tenant

Azure AD Application


Create a new Azure AD App registration


Give it a Name, select Multitenant and Redirect URL is "Web" "https://office.com"


Add a ClientSecret


Add Permissions from "APIs my organization uses" and search for "Office 365 Exchange"


Select Application Permission and select "Mailbox.Migration"


The default Permission "User.read" can be removed. Afterwards cklick on "Grant Admin Consent"


That's how it should look at the end


Migration Endpoint

Check the OrganizationCustomization

# Enable customization if tenant is dehydrated
$dehydrated = Get-OrganizationConfig | select isdehydrated
if ($dehydrated.isdehydrated -eq $true)
{
    Enable-OrganizationCustomization
}


Now you can create a new Migration Endpoint with the AzureAD AppId and the ClientSecret as Password.

#New MigrationEndpoint
$AppId = "6aa3cf87-4754-43e2-8ec6-606f6b938ae8"
$ClientSecret = "YourClientSecret"
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, (ConvertTo-SecureString -String $ClientSecret -AsPlainText -Force)
New-MigrationEndpoint -RemoteServer outlook.office.com -RemoteTenant "serveralive.onmicrosoft.com" -Credentials $Credential -ExchangeRemoteMove:$true -Name "ServerAliveMigrationEndpoint" -ApplicationId $AppId



Organization Relationship

Create a new Organization Relationship with MailboxMoveCapability Inbound

#OrganizationRelationship
$SourceTenantName="serveralive.onmicrosoft.com"
$SourceTenantId="ebc81bf5-2cef-414c-a948-2bbb116fae48"
$OrgRels = Get-OrganizationRelationship
$ExistingOrgRel = $OrgRels | ?{$_.DomainNames -like $sourceTenantId}
If ($null -ne $ExistingOrgRel)
{
    Set-OrganizationRelationship $existingOrgRel.Name -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound
}
If ($null -eq $existingOrgRel)
{
    New-OrganizationRelationship $SourceTenantName -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound -DomainNames $sourceTenantId
}

Get-OrganizationRelationship -Identity serveralive.onmicrosoft.com | fl



Source Tenant

Grant the Permissions to the Azure AD App in the Source Tenant

$AppID="6aa3cf87-4754-43e2-8ec6-606f6b938ae8"
$SourceTenant = "serveralive.onmicrosoft.com"
$URL = "https://login.microsoftonline.com/$SourceTenant/adminconsent?client_id=$AppID&redirect_uri=https://office.com"
$URL




Use the URL in the Browser



Accept the Permissions


Create a Mail enabled Security Group

Create the Mail enabled Security Group. Only Members of that Group can be migrated later on.

#Create MailEnabled Security Group
New-DistributionGroup -Name "T2TMigrationEXO" -Alias T2TMigrationEXO -Type security


Create Organization Relationship

Now we need to create an Organization Relationship with the MailboxMoveCapability RemoteOutbound

#Organization Relationship in Source
$TargetTenantName="icewolfch.onmicrosoft.com"
$TargetTenantId="46bbad84-29f0-4e03-8d34-f6841a5071ad"
$AppID="6aa3cf87-4754-43e2-8ec6-606f6b938ae8"
$scope="T2TMigrationEXO"
$OrgRels = Get-OrganizationRelationship
$ExistingOrgRel = $OrgRels | ?{$_.DomainNames -like $targetTenantId}
If ($null -ne $existingOrgRel)
{
    Set-OrganizationRelationship $existingOrgRel.Name -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}
If ($null -eq $existingOrgRel)
{
    New-OrganizationRelationship $TargetTenantName -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -DomainNames $targetTenantId -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}

Get-OrganizationRelationship -Identity icewolfch.onmicrosoft.com | fl



Source Mailbox

Now it's time to Gather Infos from the Source Mailbox
We need:
  • PrimarySMTPAddress
  • MailboxGUID
  • LegacyExchangeDN
  • All X500 EmailAdresses

Target Mail User

The Target needs to be a Mail user.

In my Environement i create the Mail User on my Exchange Server OnPrem. The ExternalEmailAddress is the PrimarySMTPAddress from the Source.

$Password = ConvertTo-SecureString "MySecretPassword" -AsPlainText -Force
New-Mailuser -Name "Hans Muster" -FirstName "Hans" -LastName "Muster" -PrimarySmtpAddress "h.muster@icewolf.ch" -ExternalEmailAddress "hans.muster@serveralive.ch" -Alias "h.muster"  -OrganizationalUnit "corp.icewolf.ch/Icewolf Users" -UserPrincipalName "h.muster@icewolf.ch" -SamAccountName "h.muster" -Password $Password

Now we ned to set the MailboxGUID und the LegacyExchangeDN and all X500 from the Soure Mailbox as X500 Addresses on the Target Mail User

$ExchangeGuid = "9e82fc17-be93-4aac-8214-0c1118700728"
$Mailuser = Get-MailUser h.muster
$EmailArray = $Mailuser.EmailAddresses
$EmailArray.Add("X500:/o=ExchangeLabs/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=4b58e230c8a64b16a4fc919c818172a0-Hans Muster")
$EmailArray.Add("x500:/o=First Organization/ou=External (FYDIBOHF25SPDLT)/cn=Recipients/cn=817c735da1b043cd9f44725d6bf06fc3")
$EmailArray.Add("X500:/o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=e7ff61a4af774705ad0872b051070535-Hans")
Set-MailUser h.muster -ExchangeGuid $ExchangeGuid -EmailAddresses $EmailArray



If there was a Mailbox before make sure it is deleted in Exchange Online completely

#Clear old Mailboxes
Set-User k.klammer -PermanentlyClearPreviousMailboxInfo




Let's wait for AAD Connect until the Mail User has been syncronized to Exchange Online


Test Migration

Connect to Exchange Online in the Target Tenant.

Now we can test if everything works. You need to use the MigrationEndpoint we created earlier with the Primary Emailadress of the Target Mail User


If you receive an Error it will look like this.
Check again if you have added all X500 from the Source Mailbox
And also added the LegacyExchangeDN from The Source Mailbox as X500 on the Target Mailuser
Don't forget to set the MailboxGUID on the Target Mailuser



Migration Batch

Now we can create a Migration Batch. The CSV Format for the Batchfiles are documented in the Link below

CSV files for mailbox migration



Now we can create the Migration Batch with the CSV File

New-MigrationBatch -Name T2TMigrationBatch -SourceEndpoint ServerAliveMigrationEndpoint -CSVData ([System.IO.File]::ReadAllBytes('C:\Temp\users.csv')) -Autostart -TargetDeliveryDomain icewolfch.onmicrosoft.com


Check the Migration Batch

Get-MigrationBatch


After a while you can see also the Moverequests

Get-MoveRequests
Get-MoveRequests | Get-MoveRequestStatistics


You can see the Migration Batch also in the Echange Online Admin Center








Every 24 Hours i receive a Status Report per Email





Complete Migration

The Sync of the Mailbox is up to 95%. Now we can complete the Migration Batch.

Get-MigrationBatch
Get-MigrationBatch -Identity T2TMigrationBatch
Complete-MigrationBatch - Identity T2TMigrationBatch



Once the Migration Batch has been completed, i receive a Completion Mail



The Moverequest has been Completed

Get-MigrationBatch
Get-MoveRequest
Get-MoveRequest -Identity <Identity> | Get-MoveRequestStatistics


Mail User in Source after Migration

After the Migration the Mailbox in the Source has been convertet to a Mail User. The ExternalEmailAddress has been set to the M365 Emailaddress. Emails to Hans.Muster@serveralive.ch will now be forwarded to h.muster@icewolfch.onmicrosoft.com.

Get-Mailuser -Identity hans.muster | fl Name, *Email*


Target Mailbox after Migration

And this is how the Mailbox in the Target Tenant looks after the Migration.

Get-Mailbox h.muster | fl name, *email*, *smtp*



Final Words

This "built-In" Method of Tenant to Tenant (or Cross-tenant) Mailbox Migration works fine.
But for a Migration for multiple Mailboxes, there is some serious Scripting needed.
Get all the Attributes from the Soure Mailboxes and create the Mailusers in the Target Tenant.

But remember, with that only the Mailboxes are moved. But there exist many more Mail enabled Objects:
  • Mail Contacts
  • Mail Users
  • Distribution Groups
  • M365 Groups / Teams
These Objects are not Covered and might have to be created also in the Target Tenant.

Regards
Andres Bohren