Recently I was tasked with doing a Hybrid Exchange to Office 365 migration.  In my testing phases I converted two client mailboxes (of departed staff) to Office 365 mailboxes, but then realized when I re-allocated the licensing for each mailbox I orphaned these two mailboxes on Office 365.  The on-premises Exchange showed the mailboxes were now Office 365 mailboxes, but because the accounts no longer had any licensing they didn’t show up as mailboxes.

Fearing this would cause a problem I tried to batch-convert the mailboxes back to on-premises Exchange.  This failed. Instead of looking for a solution why the wizard failed, I decided to look for a Powershell solution.

It turns out it’s rather easy to do.  You already have the Hybrid configuration in place so the endpoints already know about one another.  Moving mailboxes around in PowerShell is the easiest solution.

Prerequisites:

  • Domain Admin credentials
  • Office 365 Global Admin credentials
  • Database name of On-Premises Exchange

Open a PowerShell instance “as administrator” and execute these commands:

  • Set-ExecutionPolicy RemoteSigned

  • $UserCredential = Get-Credential

  • $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.ofice365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection

  • Import-PSSession $Session -DisableNameChecking

  • $opcred = get-credential domain\domainadmin

  • Get-mailbox -identity user@domain.com | New-MoveRequest -OutBound -RemoteTargetDatabase ‘ON-PREM-EXCHANGE-DB’ -RemoteHostName ‘mail.domain.com’ -RemoteCredential $opcred -TargetDeliveryDomain ‘domain.com’

You can check in the status of your mailbox move:

  • Get-MoveRequest

This doesn’t really tell you a whole lot.  It shows the existence of a request, but it doesn’t give you a real status.  A better way is:

  • Get-MoveRequest | Get-MoveRequestStatistics

This shows you the stage of the request, the status of the request, the size of the mailbox being moved, and a percentage of progress. 

You can queue up as many of these as you like and monitor the progress of all of them using these commands.  

When you’re done you should remove the requests that have been completed or failed:

  • Get-MoveRequest | where {$_.status -eq “Completed”| Remove-MoveRequest

  • Get-MoveRequest | where {$_.status -eq “Failed”| Remove-MoveRequest