PowerShell Script: Bulk move Mailboxes using a CSV Input File (HMC 4.0)
This script can be used to move mailboxes, specified within a CSV input file, between mailbox servers. It will also update the MPS Resource Manager database.
# Author: Johan Vosloo
# Date: 12/10/2009
# Purpose: Bulk move mailboxes from a CSV input file.
# Disclaimer: This script is provided as-is without any support. The script was tested against HMC 4.0, Exchange Server 2007 SP1 and Powershell 1.0. Please test in a test environment prior to production use.
# Process:
# 1. Use the Exchange Management Shell to get the source server name with Get-ExchangeServer | Select Name
# 2. Use the Exchange Management Shell to populate the input CSV file with Get-MailboxDatabase | where {$_.ServerName.Contains("sourceservername") -eq "true"} | Get-Mailbox | Select Alias,Database | Export-Csv C:\Temp\MbxsToBeMoved.csv –NoTypeInformation
# 3. Change ‘Database’ field header to ‘TargetDB’
# 4. Modify database/targetdb field entries as required in the CSV
# 5. Change preferredDomainController in mailbox move script
# 6. Run mailbox move script:
# CSV Example:
# Alias,TargetDB
# bloggsj,mytargetservername
$path = "C:\jv\MoveMailbox\MbxsToBeMoved.csv";
Write-Host;
Write-Host "*******************";
Write-Host "Move Mailbox Script" -Foregroundcolor Blue -Backgroundcolor White;
Write-Host "*******************";
Write-Host;
Write-Host "A CSV is required (i.e. $path)"
$Ver1 = Read-Host "CONTINUE script execution? [Y] to continue or [ANY OTHER KEY] to exit"
if ($Ver1 -ne "Y")
{exit;
}
Write-Host;
Write-Host "Valid entries in CSV:" -Foregroundcolor Blue -Backgroundcolor White;
# Note: Checks are not performed to avoid scenarios where sourcedb = targetdb in this version of the script. This is the administrators responsibility.
Write-Host;
Write-Host "Alias,TargetDB";
Import-csv -path $path |
foreach `
{
$TDBs = Get-MailboxDatabase $_.TargetDB -ErrorVariable MyError -ErrorAction SilentlyContinue;
# Note: Checks are not performed to avoid scenarios where the Alias is invalid in this version of the script. This is the administrators responsibility.
$A = $_.Alias
Write-Host "$A,$TDBS";
}
If ($MyError -ne $null)`
{
Write-Host;
Write-Host "*******";
Write-Host "Error" -Foregroundcolor Red -Backgroundcolor White;
Write-Host "*******";
Write-Host "Invalid TargetDB in CSV. Script terminating..." -Foregroundcolor Blue -Backgroundcolor White;
Write-Host "Error Description:" -Foregroundcolor Blue -Backgroundcolor White;
$MyError;
Write-Host;
exit;
}
$Ver2 = Read-Host "CONTINUE moving ALL mailboxes in CSV? [Y] to continue or [ANY OTHER KEY] to exit"
if ($Ver2 -ne "Y")
{exit;
}
Function SendMPSRequest([string]$xmlRequestStr)
{
$oMpf = new-object -comobject "Provisioning.ProvEngineClient"
$xmlResponseStr = $oMPF.SubmitTrustedRequest($xmlRequest.get_InnerXml());
$xmlResponse = new-object "System.Xml.XmlDocument";
$xmlResponse.LoadXml($xmlResponseStr);
$xmlResponse;
}
[string]$xmlRequestStr = @"
<?xml version="1.0" encoding="utf-8"?>
<request>
<data>
<preferredDomainController>ad01.fabrikam.com</preferredDomainController>
<user>CSVPopulated</user>
<targetDatabase>CSVPopulated</targetDatabase>
</data>
<procedure>
<execute namespace="Hosted Email 2007" procedure="MoveMailbox" impersonate="1">
<before source="data" destination="executeData" mode="merge" />
<after source="executeData" destination="data" mode="merge" />
</execute>
</procedure>
</request>
"@
[string]$excXmlStr = @"
<?xml version="1.0" encoding="utf-8"?>
"@
Write-Host
Write-Host "Starting procedure..." -Foregroundcolor Blue -Backgroundcolor White;
Write-Host
$CSV = Import-csv -path $path
Foreach ($line in $CSV)`
{
$mailbox = Get-Mailbox $line.Alias | Select Alias, DistinguishedName;
$userName = $mailbox.Alias;
$userDN = $mailbox.DistinguishedName;
$TDB = $line.TargetDB
Write-Host "Moving $userName to $TDB..." -ForegroundColor White
Write-Host
$xmlRequest = new-object "System.Xml.XmlDocument";
$xmlRequest.LoadXml($xmlRequestStr);
$xmlRequest.request.data.user = "LDAP://" + $userDN;
$xmlRequest.request.data.targetDatabase = $TDB;
$xmlResponse = $null;
$xmlResponse = SendMPSRequest($xmlRequestStr.ToString());
if ($xmlResponse.Response.Data.User -ne $null)`
{
$MPSUser = New-Object System.Object;
$MPSUser | Add-Member -Type NoteProperty -Name "DistinguishedName" -Value $userDN;
$MPSUser | Add-Member -Type NoteProperty -Name "User" -Value $xmlResponse.Response.Data.user;
$MPSUser | Add-Member -Type NoteProperty -Name "TargetDB" -Value $xmlResponse.Response.Data.targetDatabase;
$MPSUser | FL;
}
}
Write-Host;
Write-Host "********************************************************************************************************************************************************************************************";
Write-Host "Script execution complete. In pre-HMC4.0 Hosted Exchange Update Rollup 5 environments, please remember to run the Managed Email 2007::RepairExchangeObject procedure on all mailboxes moved." -Foregroundcolor Blue -Backgroundcolor White;
Write-Host "********************************************************************************************************************************************************************************************";
Write-Host;