Short answer
You run it from the target tenant. Buy a Cross Tenant User Data Migration license for each user, register a multi-tenant Entra app with the Mailbox.Migration permission, and have the source admin consent to it. Create an organization relationship in both tenants, scoped by a mail-enabled security group in the source. Stamp target MailUsers with the source ExchangeGuid, ArchiveGuid and X500 addresses, then create a migration batch and complete it.
Key facts
- Every migrated user needs a one-time Cross Tenant User Data Migration license, assigned on the source or target user; Microsoft offers no exceptions.
- The target tenant is configured first, and the migration batch is created in the target tenant.
- The source tenant scopes which mailboxes can leave with a mail-enabled security group set as MailboxMovePublishedScopes.
- Mailboxes on any type of hold are not migrated, and the move for them is blocked.
- Microsoft recommends no more than 2,000 mailboxes per batch and submitting batches about two weeks before cutover.
- Microsoft 365 Groups, mailbox signatures and Outbox items do not migrate, and cross-cloud moves (for example Worldwide to Government) are not supported.
Prerequisites and licensing
Cross-tenant mailbox migration uses the Mailbox Replication Service (MRS) and the New-MigrationBatch cmdlet. It works for cloud-only tenants, hybrid tenants, or a mix. The two tenants must use different domain names, and both must be in the same Microsoft cloud.
Licensing is the step people skip. Each user needs a Cross Tenant User Data Migration add-on license (a one-time, per-user fee). You can assign it on the source or the target user, and it also covers OneDrive cross-tenant migration. Without it the move fails with CrossTenantMigrationWithoutLicensePermanentException. Users in both tenants also need an Exchange Online license.
- Organization Management (organization administrator) in Exchange Online in each tenant for the one-time setup. Only this role can change -MailboxMoveCapability on an organization relationship.
- Move Mailboxes role in the target tenant for whoever creates and runs the batches.
- Rights in the Microsoft Entra admin center to register an app and grant admin consent in each tenant.
- The other tenant's tenant ID (a GUID, not a domain name). Find it in Microsoft Entra admin center > Overview > Tenant ID.
- The ExchangeOnlineManagement module: Install-Module ExchangeOnlineManagement, then Connect-ExchangeOnline in each tenant.
- At least one mail-enabled security group in the source tenant. Over 10,000 users, Microsoft recommends several groups. Nested groups work but are not recommended.
Step 1: Create the migration app in the target tenant
Do the target tenant first. Separate admins can handle each tenant; nobody needs credentials for both.
- Sign in to the Microsoft Entra admin center (entra.microsoft.com) as a target tenant admin.
- Go to Microsoft Entra ID > App registrations > New registration.
- Under Supported account types, choose Accounts in any organizational directory (Any Microsoft Entra directory - Multi-tenant). Under Redirect URI, select Web and enter https://office.com. Select Register.
- Open the new app and copy the Application (client) ID from Essentials.
- Select API permissions. Remove the default User.Read if you want (it is not needed).
- Select Add a permission > APIs my organization uses, search for Office 365 Exchange Online, choose Application permissions, expand Mailbox, select Mailbox.Migration, then Add permissions.
- Select Certificates & secrets > Client secrets > New client secret. Set a description and expiry, then copy the secret value now. It is shown only once.
- Go to Enterprise applications, open the app, select API Permissions, then Grant admin consent for [your tenant] and Accept.
- Send the source admin this consent URL, with their onmicrosoft.com name and your app ID filled in: https://login.microsoftonline.com/contoso.onmicrosoft.com/adminconsent?client_id=[application_id]&redirect_uri=https://office.com
Step 2: Source tenant consent, scope group and organization relationship
- The source admin opens the consent URL and selects Accept. The app then appears under Enterprise applications in the source tenant.
- The source admin connects to Exchange Online PowerShell and runs the script below. It creates the mail-enabled security group if needed and an organization relationship with -MailboxMoveCapability RemoteOutbound.
- Add every mailbox that is allowed to move to that group. Anything outside the group fails with MailboxNotInCrossTenantMigrationScopeException.
# Source tenant: scope group and RemoteOutbound organization relationship (Microsoft's documented script)
# SOURCE tenant: scope group + organization relationship that allows outbound moves
Connect-ExchangeOnline -UserPrincipalName [email protected]
$targetTenantId = "[target tenant ID GUID]"
$appId = "[application ID of the migration app you consented to]"
$scope = "[mail-enabled security group of users allowed to migrate]"
$orgrelname = "[name of your new organization relationship]"
$dehydrated = Get-OrganizationConfig | select isdehydrated
if ($dehydrated.isdehydrated -eq $true) { Enable-OrganizationCustomization }
if (!(New-DistributionGroup -Type Security -Name $scope)) { Write-Host "Group already exists." }
$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 $orgrelname -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability RemoteOutbound -DomainNames $targetTenantId -OAuthApplicationId $appId -MailboxMovePublishedScopes $scope
}
# Add each in-scope mailbox to the group
Add-DistributionGroupMember -Identity $scope -Member [email protected]
Step 3: Migration endpoint and organization relationship in the target tenant
Wait until the source admin has consented. If not, New-MigrationEndpoint fails with an authentication error.
# Target tenant: create the cross-tenant migration endpoint
# Run in the TARGET tenant after the source admin has consented to the app
Install-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName [email protected]
$AppId = "[Application (client) ID of the migration app]"
$name = "[name of your new migration endpoint]"
$remote = "contoso.onmicrosoft.com" # source tenant onmicrosoft.com name
$secret = "[client secret value saved earlier]"
# Enable customization if tenant is dehydrated
$dehydrated = Get-OrganizationConfig | select isdehydrated
if ($dehydrated.isdehydrated -eq $true) {Enable-OrganizationCustomization}
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, (ConvertTo-SecureString -String $secret -AsPlainText -Force)
New-MigrationEndpoint -RemoteServer outlook.office.com -RemoteTenant $remote -Credentials $Credential -ExchangeRemoteMove:$true -Name $name -ApplicationId $AppId
# Target tenant: Inbound organization relationship
# TARGET tenant: organization relationship that allows inbound moves
$sourceTenantId = "[source tenant ID GUID]"
$orgrelname = "[name of your new organization relationship]"
$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 $orgrelname -Enabled:$true -MailboxMoveEnabled:$true -MailboxMoveCapability Inbound -DomainNames $sourceTenantId
}
Step 4: Prepare target MailUsers
Each user must already exist in the target tenant as a MailUser with attributes copied from the source mailbox. The move will not start without them.
Do not assign the target Exchange Online license before ExchangeGuid is stamped. If you do, Exchange creates a new empty mailbox and the move fails. Microsoft suggests licensing after the move, inside the 30-day grace period. If the target object once had a mailbox, Set-User <identity> -PermanentlyClearPreviousMailboxInfo clears it. That is permanent, so check first.
- ExchangeGuid: must match the source mailbox.
- ArchiveGuid: must match, if the source has an archive.
- X500 proxies: add x500:<source LegacyExchangeDN> plus every X500 address already on the source mailbox. This also keeps replies to old mail working.
- UserPrincipalName and PrimarySmtpAddress: the user's new identity in the target tenant.
- ExternalEmailAddress: the user's current source mailbox address (for example [email protected]). Set PrimarySmtpAddress too, or this value becomes the primary address and the move fails.
- Only SMTP proxies for domains the target tenant owns. A foreign domain causes NotAcceptedDomainException or blocks the MailUser to mailbox conversion.
- If you sync from on-premises with Microsoft Entra Connect, stamp these on the on-premises object and let it sync.
Source tenant: export the needed attributes
# SOURCE tenant: export the attributes the target MailUser needs
Get-Mailbox [email protected] |
Select-Object PrimarySMTPAddress,Alias,DisplayName,ExchangeGuid,ArchiveGuid,LegacyExchangeDn,EmailAddresses |
Export-Clixml "$home\desktop\UsersToMigrate.xml"
# Target tenant: stamp GUIDs and X500 addresses on the MailUser
# TARGET tenant (cloud-only): stamp an existing MailUser
# ExternalEmailAddress = the user's mailbox address in the SOURCE tenant
$m = Import-Clixml "$home\desktop\UsersToMigrate.xml"
$x500 = "x500:" + $m.LegacyExchangeDn
Set-MailUser [email protected] -ExchangeGuid $m.ExchangeGuid -ArchiveGuid $m.ArchiveGuid -EmailAddresses @{add = $x500}
# Copy every existing X500 proxy from the source mailbox too
$m.EmailAddresses | Where-Object { $_ -match "x500" } | ForEach-Object {
Set-MailUser [email protected] -EmailAddresses @{add = "$_"}
}
# Check for an old cloud mailbox on the target object
Get-User [email protected] | select Name, *recipient* | Format-Table -AutoSize
Step 5: Create, sync and complete the migration batch
Batches run from the target tenant. The CSV must list the target tenant addresses, not the source ones. -TargetDeliveryDomain tells MRS which target proxy to write as the forwarding address on the source object after the move. Keep each batch at or under 2,000 mailboxes and move delegates with the people they work for, since cross-tenant mailbox and calendar permissions are not supported.
In the portal: Exchange admin center > Migration > Add migration batch, then choose the cross-tenant migration option and the endpoint you created. When the batch shows Synced, select it and choose Complete migration batch.
# Target tenant: test, create and complete the batch
# TARGET tenant: test the endpoint against one prepared MailUser
Test-MigrationServerAvailability -EndPoint "[migration endpoint name]" -TestMailbox "[email protected]"
# users.csv uses TARGET tenant addresses
# EmailAddress
# [email protected]
New-MigrationBatch -Name T2Tbatch -SourceEndpoint "[migration endpoint name]" -CSVData ([System.IO.File]::ReadAllBytes('C:\Migration\users.csv')) -Autostart -TargetDeliveryDomain northwindtraders.onmicrosoft.com
# When the batch shows Synced, finalize it
Complete-MigrationBatch -Identity T2Tbatch
What does not migrate, and what changes for users
Only user-visible mailbox content moves: email, contacts, calendar, tasks, notes and the Recoverable Items folders. After completion the source mailbox is deleted and becomes a MailUser that forwards to the target, so the source tenant can no longer search it with eDiscovery.
- Not migrated: Microsoft 365 Groups, Teams chat folder content, Outbox items, mailbox signatures and sensitivity labels.
- Teams meetings move, but their join links break. Users must recreate them.
- Send on Behalf (GrantSendOnBehalfTo) does not move. Re-add it with Set-Mailbox after the move.
- Users rebuild their Outlook profile with the new UPN and address, then resync the OST.
- Archives move, including up to 12 auxiliary archives.
- Afterward, remove the endpoint and organization relationships with Remove-MigrationEndpoint and Remove-OrganizationRelationship.
Common errors and fixes
| Error | Cause | Fix |
|---|---|---|
| CrossTenantMigrationWithoutLicensePermanentException | No Cross Tenant User Data Migration license on the source or target user. | Assign the license, then resume the batch. |
| MailboxNotInCrossTenantMigrationScopeException | User not in the source scope group, or MailboxMovePublishedScopes not set. | Add the user to the group, check the source organization relationship, resume the batch. |
| MissingExchangeGuidException | Target MailUser lacks the correct ExchangeGuid. | Set-MailUser <id> -ExchangeGuid <source GUID>, then resume. |
| NotAcceptedDomainException | Target MailUser has a proxy address for a domain the target tenant does not own. | Set-MailUser <id> -EmailAddress @{remove="smtp:..."}, then resume. |
| UserDuplicateInOtherBatchException | User is already in another batch. | Get-MigrationUser -Identity <id> -IncludeAssociatedUsers | Remove-MigrationUser, then add to one batch. |
| SourceMailboxAlreadyBeingMovedPermanentException | An existing move request (possibly an internal Microsoft move). | Remove the user, wait for or remove the other move, then re-add. |
| UserAlreadyHasDemotedArchiveException | User previously had a disabled archive. | Remove the disabled archive (irreversible) or re-enable it and update ArchiveGuid on the target. |
| MailboxExceedsTargetQuotaPermanentException (and related quota errors) | Source mailbox or archive is larger than the target quota. | Enable archive or auto-expanding archive in the source to shrink the primary mailbox, then retry. |
How to verify it worked
- Before the batch, run Test-MigrationServerAvailability against the endpoint with one prepared MailUser. Microsoft also publishes a validation script at aka.ms/crosstenantmailboxmigrationvalidationscript.
- In Exchange admin center > Migration, select the batch, then under Migration details select View details to see each user's status, items synced and items skipped.
- Select a user and choose Download the report for this user for a detailed report.
- After completion, confirm the target object is now a mailbox and the source object is a MailUser whose ExternalEmailAddress points at the target delivery domain.
# Check batch, user and move status
# TARGET tenant
Get-MigrationBatch -Identity T2Tbatch
Get-MigrationUser -BatchId T2Tbatch
Get-MigrationUser -EmailAddress [email protected] | Get-MigrationUserStatistics
# Only cross-tenant moves, then per-user detail and report
Get-MoveRequest -Flags "CrossTenant"
Get-MoveRequestStatistics -Identity [email protected]
Get-MoveRequestStatistics -Identity [email protected] -IncludeReport | Export-CSV C:\Migration\MRStats.csv
# SOURCE tenant: the old mailbox should now be a MailUser pointing at the target
Get-MailUser [email protected] | select ExternalEmailAddress, EmailAddresses
When to call a consultant
Tell us about both tenants and your timeline. We will tell you plainly whether native migration fits and what a pilot would look like.
Take the 2-min fit check Talk to a specialist
How Accred Consulting approaches it
We start with a free call to understand both tenants, the user count and the deadline. Then you get a written plan covering licensing, the app and organization relationship setup, how target MailUsers will be built and synced, batch groupings that keep delegates together, and the Outlook profile steps users will need. We run a pilot batch with a few real mailboxes before any bulk moves and fix attribute problems there. Our US-based team scopes the work as fixed-fee or hourly, and we coordinate with the other company's admins when they own the source tenant.
Track record: 475+ client projects, 2,000+ migration workstreams and 210,000+ users migrated by a US-based team. Company facts · Case studies
Related questions
Sources
- Microsoft Learn: Cross-tenant mailbox migration
- Microsoft Learn: New-MigrationBatch
- Microsoft Learn: Get-MoveRequestStatistics
- Microsoft Learn: Migration users status report in Exchange Online
Want this scoped for your environment?
Book a free consultation. After discovery you get a written plan with scope, pricing (fixed fee, hourly, retainer or block of hours) and a timeline.
Book a free consultation