PowerShell: Office365 / Exchange Online migration


We had an Exchange Server 2007 and we wanted to go to the cloud, because lets face it, the cloud is cool.
So we got a consultant to set up ADFS and all necessary connections so we could start migrating to the cloud.
Problem was, now we had to “migrate” mailboxes and we where not going to do that manually.


We got a manual describing all the manual actions we had to do to start a migration and we even got a few scripts to “automatically” finalize the migration.


The steps that where necessary to migrate a mailbox where:

  1. Create a .csv file with EmailAdresses of all the user you want to migrate
  2. Create a Migration Batch by uploading the .csv file on the ExchangeOnline portal site
  3. Start the MigrationBatch you just created
  4. Wait until the MigrationBatch is completed (you never know how long this will take)
  5. Run the migration scripts. These bad boys disable the local mailbox and create local mailusers and fill up the new mailuser object with the correct information
  6. Enable licenses on the migrated users
  7. And since it’s a migration from 2007 to O365 you need to remove the mail profile for all migrated users. We just ended up removing the entire profile, because that was easyer


The end result is a script that uses a .csv file that has both the username and the email address of a user and can be found in a folder “Migrationbatch” in the same directory as the script.
It also uses two other scripts that should be located in a folder “O365MigrateScripts”. I can only take credit for altering them a bit to suit my needs for use in combination with my script, I got the code from our consultant.

Since the script has a lot of specific information about my company I replaced all specific information with “…”. But I hope the code is still useful.

# Import ExchangeOnline session for powershell commands
$importresults = Import-PSSession … -Prefix Online
# Import Exchange session for powershell commands
$importresults = Import-PSSession …
# Set other parameters

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$MigrationCSVFileName = "$dir\Migrationbatch\Migrationbatch_{0:yyyyMMdd}.csv" -f (Get-Date)
if(-not (Test-Path $MigrationCSVFileName)){
	Write-Host "No batch for today." -ForegroundColor Red
#Import user list from migration.csv file
$MigrationCSV = Import-Csv $MigrationCSVFileName

#region Create MigrationBatchCSVFile
$MigrationBatchCSVFileName = ".\migration.csv"
$MigrationBatchCSV = @()
foreach($record in $MigrationCSV) {
	$objMigrationBatchRecord = New-Object System.Object
	$objMigrationBatchRecord | Add-Member -Type NoteProperty -Name EmailAddress -Value $record.EmailAddress
	$MigrationBatchCSV += $objMigrationBatchRecord
#Check for existing csv file and overwrite if needed
if(Test-Path $MigrationBatchCSVFileName)
		Write-Host "Deleting existing migration.csv file" -ForeGroundColor Red
		Remove-Item $MigrationBatchCSVFileName
$MigrationBatchCSV | Export-CSV -Path $MigrationBatchCSVFileName -notype
(Get-Content $MigrationBatchCSVFileName) | %{$_ -replace '"', ''} | Set-Content $MigrationBatchCSVFileName -Encoding Unicode #"

#region Create and start MigrationBatch

$MigrationEndpoint = Get-OnlineMigrationEndpoint -Identity …
$MigrationBatch = New-OnlineMigrationBatch -Name ("ScriptedBatch_{0:yyyyMMdd}" -f (Get-Date)) -SourceEndpoint $MigrationEndpoint.Identity -CSVData ([System.IO.File]::ReadAllBytes($MigrationBatchCSVFileName)) –AutoStart

$Time = [System.Diagnostics.Stopwatch]::StartNew()
Write-Host "Syncing..." -ForegroundColor Yellow
while((Get-OnlineMigrationBatch $MigrationBatch.Identity.Name).Status.value.ToLower().Equals("syncing")){
	Start-Sleep -Seconds 2
Write-Host ("Syncing is done and it took {0} seconds." -f $Time.Elapsed.TotalSeconds) -ForegroundColor Yellow

If((Get-OnlineMigrationBatch $MigrationBatch.Identity.Name).Status.Value.ToLower().Equals("synced")){
	Write-Host "Synced!" -ForegroundColor Green	
#region Run migration scripts
	Write-Host "Running migration scripts..." -ForegroundColor Yellow
	# Create cloud.csv file with required user information to finalize user objects after migration
	.\O365MigrateScripts\ExportO365UserInfo.ps1 -migrationCSVFileName $MigrationBatchCSVFileName -Credentials …
	# Disable Mailboxes and create MailUsers and add all information saved in cloud.csv (requires imported Exchange session)
	.\O365MigrateScripts\Exchange2007MBtoMEU.ps1 -DomainController …
	Write-Host "Completed migration scripts." -ForegroundColor Yellow
	#region Enable Licenses
	Write-Host "Enabling Licenses..." -ForegroundColor Yellow
	# Connect to MicrosoftOnline using the MSOnline module
	try {
		Connect-MsolService -Credential … –ErrorAction stop
		Write-Host "Connected" -ForegroundColor Green
	} catch {
		Write-Error "Could not connect to MSOnline. Check proxy settings."
	# Get user list from CSV file
	foreach($record in $MigrationCSV){
		# Set ExchangeOnline license
		$strUPN = (“{0}@...” -f $record.UserName)
		# Remove all current licenses
		foreach($lic in ((Get-MsolUser -UserPrincipalName $strUPN).Licenses)){
			Set-MsolUserLicense -UserPrincipalName $strUPN -RemoveLicenses $lic.AccountSkuId
		# Add E1 license
		Set-MsolUserLicense -UserPrincipalName $strUPN -AddLicenses …
		# Add E3 License
		#Set-MsolUserLicense -UserPrincipalName $strUPN -AddLicenses …
			Write-Host "License enabled for $strUPN" -ForegroundColor Green
	Write-Host "Completed licensing" -ForegroundColor Yellow
	#region Remove profiles
	Write-Host "Removing profiles..." -ForegroundColor Yellow
	The code for removing profiles to specific to my company. Just add your code here.
} else {
	Write-Host "Oops, somthing went wrong." -ForegroundColor Red

Tags: , , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: