Sometimes when you want to move a mailbox from Exchange 2010 to Exchange 2013 or 2016 the move request stops with the following error:
MigrationMRSPermanentException:
MapiExceptionUnexpectedType: Unable to query table rows
StoreEc: 0x80040304
And you have already installed Exchange 2010 Update Rollup 10, see article below.
Microsoft Support article
Then you have to export the mailbox, disable the mailbox, create the mailbox at the new server and import mailbox data from pst. For that process, I created a script that exports the mailbox data to pst file and creates an XML file with the sAMAccountName, WindowsEmailAddress, Email addresses (proxy addresses) and legacyExchangeDN. These attributes are required to avoid conflicts on other mailboxes and the cached recipients.
param(
[parameter(Mandatory=$true)]
[net.mail.mailaddress]$EmailAddress,
[parameter(Mandatory=$false)]
$Type = 'Export',
[parameter(Mandatory=$false)]
$ImportFile
)
if (-not(Get-Command -Name 'Get-Mailbox' -ErrorAction SilentlyContinue)) {
Add-PSSnapin -Name Microsoft.Exchange.*
}
# Reset/Set variables
$Mailbox,$MailboxInfo = $null
$PathExport = '<Path to Exchange export directory>'
$Server = (Get-ADDomain).PDCEmulator
# Test if Mailbox exists
try {
# Export part of script
if ($Type -eq 'Export') {
# Get Mailbox
$Mailbox = Get-Mailbox -Identity $EmailAddress.ToString()
Write-Host "Getting Mailbox information from: $($EmailAddress)..." -ForegroundColor Green
# Getting information from mailbox
$MailboxInfo = @{
'Name' = $Mailbox.SamAccountName
'LegacyExchangeDN' = $Mailbox | Select-Object -ExpandProperty legacyExchangeDN
'EmailAddresses' = $Mailbox | Select-Object -ExpandProperty EmailAddresses
'PrimaryEmaiAddress' = $Mailbox | Select-Object -ExpandProperty WindowsEmailAddress
}
# Print Hashtable to console
$MailboxInfo
# Export HashTable
$MailboxInfo | Export-Clixml -Path ('{0}\Documents\{1}.xml' -f $env:PUBLIC, $EmailAddress) -Force
#Get Date
$StringDate = Get-Date -Format 'yyy-MM-dd_hh-mm'
# Set Batchname for New-MailboxExportRequest
$BatchName = ('{0}_{1}' -f $MailboxInfo.Name, $StringDate)
# Start export process
Write-Host "Starting mailbox export request..." -ForegroundColor Yellow
New-MailboxExportRequest `
-Mailbox $EmailAddress.ToString() `
-FilePath ('{0}\{1}_{2}.pst' -f $PathExport, $MailboxInfo.Name, $StringDate) `
-Name $BatchName `
-BatchName $BatchName
# Import part of script
} elseif ($Type -eq 'Import') {
# Check if XML file is available
if ($ImportFile -and (Test-Path -Path $ImportFile -ErrorAction SilentlyContinue)) {
# try block for import mailbox data
try{
# Load mailbox information from XML file
$Mbx = Import-Clixml -Path $ImportFile
# Build new X500 address
$X500 = ('X500:{0}' -f $Mbx.legacyExchangeDN)
Write-Host "Set Mailbox for User $($Mbx.Name)"
# only if mailbox does not exist
if (-not(Get-Mailbox -Identity $Mbx.Name -ErrorAction SilentlyContinue)) {
Enable-Mailbox -Identity $Mbx.Name -PrimarySmtpAddress $Mbx.PrimaryEmaiAddress -DomainController $Server
}
# If additional email addresses are present import the addresses
if ($Mbx.EmailAddresses) {
Set-Mailbox -Identity $Mbx.Name -EmailAddresses $Mbx.EmailAddresses -DomainController $Server
}
# Set old X500 address to proxyaddresses
Set-Mailbox -Identity $Mbx.Name -EmailAddresses @{Add=$X500} -DomainController $Server
# Get new Mailbox information
Get-Mailbox -Identity $Mbx.Name -DomainController $Server |
Select-Object DisplayName,ServerName,Database,WindowsEmailAddress,EmailAddresses
Write-Host "Bite denken Sie daran, die PST Datei wieder zu importieren!" -ForegroundColor Yellow
# Display all PST files for this user
Get-ChildItem -Path $PathExport -Filter ('{0}*.pst' -f $Mbx.Name)
} catch {
# get error record
[Management.Automation.ErrorRecord]$e = $_
# retrieve information about runtime error
$info = [PSCustomObject]@{
Exception = $e.Exception.Message
Reason = $e.CategoryInfo.Reason
Target = $e.CategoryInfo.TargetName
Script = $e.InvocationInfo.ScriptName
Line = $e.InvocationInfo.ScriptLineNumber
Column = $e.InvocationInfo.OffsetInLine
}
# output information. Post-process collected info, and log info (optional)
$info
}
} else {
Write-Host "Importfile ($($ImportFile)) is not accessable!"
}
}
} catch {
Write-Warning "Mailbox $($EmailAddress) does not exist!"
}
Have fun