Troubleshooting Mailbox Migration Error "You can't use the domain because it's not an accepted domain for your organization."

While migrating users via MRS between organizations (especially to Exchange Online), a pretty common error that I run across is:

You can't use the domain because it's not an accepted domain for your organization.

This error is generated because the MailUser object of the user you're attempting to migrate has a proxy address attached to it that is NOT an accepted domain in your target organization or tenant. For organizations that are divesting or only moving a subset of users and have accumulated domains over the years, this can be frustrating. This would be easier to troubleshoot if the error told you *what* proxy address or domain was causing the problem.

But if wishes were fishes, we'd all have a fry and I probably wouldn't have a job. If you read my previous blog post on removing proxy addresses, some of this will seem familiar.

Here's a process that I go through that can help you resolve this error.

1. Get a list of Accepted Domains in the target environment. This is easy enough by running:

 Get-AcceptedDomain

However, we want to be able to process it in a meaningful way, so we should put it into a variable. So, instead, I'd do this:

 [array]$AcceptedDomains = (Get-AcceptedDomain).DomainName

2. Next, we probably want a list of users. You can get your list from a failed migration batch, or just query your entire directory.
From a failed migration batch:

 $Users = (Get-MigrationUser -Status Failed | ? { $_.ErrorSummary -match "not an accepted domain" }).Identity

From a group of users or mailboxes:

 $Users = (Get-Mailbox).PrimarySmtpAddress

3. In my previous blog post, I used an array to hold the list of domains I wanted to remove. In this post, I'm going to do exactly the opposite (which makes for a cooler, more elegant solution). It's much easier to know what you *do* have than what you *don't.* RegEx is your friend here. We're going build a regular expression that contains all of the domains that I want to match against (note the "@" included in the -join operator, so we are capturing an exact domain match and properly identify invalid subdomains):

 [regex]$AcceptedDomainsRegex = ‘(?i)(‘ + (($Domains |foreach {[regex]::escape($_)}) –join “|@”) + ‘)$’

4. Now, the fun part--loop through an object's email addresses and match them against our regular expression, noting which addresses need to be removed. If you're running this in the target environment, you won't be able to remove the offending addresses, but you'll get an idea of what needs to be fixed in the on-premises or source environment.

 Foreach ($user in $users)
    {
    Write-host processing $user
    $obj = Get-MailUser $user
    for ($i=($obj.EmailAddresses.count)-1; $i -ge 0; $i--)
        {
        $address = $obj.EmailAddresses[$i]
        if ($address -notlike "*@*")
            {
            Continue
            }
        Write-Host "     Testing proxy address $address"
        if ($address -inotlike "*x500:*" -and $address -like "*@*" -and $address -notmatch $AcceptedDomainsRegex)
                {
                Write-Host -ForegroundColor Red "     Address $($address) doesn't match"
                write-Host "-----"
                # if object is not synchronized, you can uncomment the next line
                # $obj.EmailAddresses.RemoveAt($i)
                }
            else
                {
                Write-Host -ForegroundColor Green "     Address $($address) matches"
                write-Host "-----"
                }
        }
      # if object is not synchronized, you can uncomment the next line   
      # $obj | Set-MailUser -EmailAddresses $obj.EmailAddresses
      }

If you're running this in the on-premises environment to figure out what proxy addresses would need to be removed, you'll want to create an array value containing the target environment's accepted domains:

 $Domains = @('domain1.com','domain1.net','domain2.com','domain3.com')
[regex]$AcceptedDomainsRegex = ‘(?i)(‘ + (($Domains |foreach {[regex]::escape($_)}) –join “|@”) + ‘)$’
$Users = Get-Mailbox -ResultSize Unlimited
Foreach ($user in $users)
    {
    Write-Host processing $user
    for ($i=($user.EmailAddresses.count)-1; $i -ge 0; $i--)
        {
        $address = $user.EmailAddresses[$i]
        if ($address -notlike "*@*")
            {
            Continue
            }
        Write-Host "     Testing proxy address $address"
        if ($address -inotlike "*x500:*" -and $address -like "*@*" -and $address -notmatch $AcceptedDomainsRegex)
                {
                Write-Host -ForegroundColor Red "     Address $($address) doesn't match"
                Write-Host "-----"
                # To remove from proxy address array, uncomment the next line
                # $user.EmailAddresses.RemoveAt($i)
                }
            else
                {
                Write-Host -ForegroundColor Green "     Address $($address) matches"
                Write-Host "-----"
                }
        }
      # To update the mailbox, uncomment the next line   
      # $user | Set-Mailbox -EmailAddresses $user.EmailAddresses
      }

As always, run on a test mailbox and make a backup before you go bulk deleting things. :-)