Recreate Exchange Mailbox with legacyExchangeDN and emailaddresses

Written by Arne Tiedemann on Monday July 2, 2018

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 :-)