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. 🙂

Comments (12)

  1. turbomcp says:

    i love this error(just kidding)
    but i remeber i ran some test few months back and got diffrent results
    i created a dummy non routable even domain as accepted domain and stamped one mailbox onprem with that dummy proxy and it let me move it no problem…
    so immediatly when i saw this post i went to er check this and this time it failed with that exact error
    Thanks again for cool solution,seems the hybrid issues never end:)

    1. You can also get around this error if you license the user after the MEU is synced but before you attempt to migrate the mailbox. When you license the user, it will drop the non-accepted domains. In the event that an object hasn’t synced correctly (for example, no ExchangeGuid), it will create a cloud mailbox (which is why I don’t like to really license prior to staging the mailbox). You can do something like:

      $NotReady = Get-MailUser -ResultSize Unlimited | ? { $_.ExchangeGuid -like “*0000-0000*” }

      And then just not license users with no Guid until you fix them.

  2. turbomcp says:

    isnt this:
    [regex]$AcceptedDomainsRegex = ‘(?i)(‘ + (($Domains |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’
    supposed to be this:
    [regex]$AcceptedDomainsRegex = ‘(?i)(‘ + (($AcceptedDomains |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’

    ?

    1. Nice eye, but no. I’m cycling through the domains listed in $Domains to join them together as a regular expression:

      PS C:\> $Domains = (‘domain1.com’,’domain2.com’,’domain3.com’)
      PS C:\> [regex]$AcceptedDomainsRegex = ‘(?i)(‘ + (($Domains |foreach {[regex]::escape($_)}) -join “|”) + ‘)$’
      PS C:\> $AcceptedDomainsRegex.ToString()
      (?i)(domain1\.com|domain2\.com|domain3\.com)$
      PS C:\>

      1. turbomcp says:

        also when i test it in my lab(i do these crazy things sometimes:))
        i notice that the regex part seem odd like this:
        $Domains = @(‘domain1.com’,’domain1.net’,’domain2.com’,’domain3.com’)
        [regex]$AcceptedDomainsRegex = ‘(?i)(‘ + (($Domains |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’
        but when i check the regex expression it shows this:
        $accepteddomainsregex
        Options MatchTimeout RightToLeft
        ——- ———— ———–
        None -00:00:00.0010000 False
        when i check the syntax alone like this:
        ‘(?i)(‘ + (($Domains |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’
        i get this:
        (?i)(domain1\.com|domain1\.net|domain2\.com|domain3\.com)$

        1. Yes, that looks correct. If you want to check out how your RegEx match works, you can head over to rubular.com and try it out.

  3. turbomcp says:

    might be totaly off here but isnt this:
    Write-Host processing $user
    for ($i=($obj.EmailAddresses.count)-1; $i -ge 0; $i–)

    supposed to be this:
    Write-Host processing $user
    for ($i=($user.EmailAddresses.count)-1; $i -ge 0; $i–)

    1. turbomcp says:

      That should do it
      regex is fine,my mistake
      seem to be working like charm
      Thanks and sorry for hassle:)

  4. The hotmail server pop3 domain.

  5. The domain are like to say, com, se , it ,ur, and ect

    1. If you want a more flexible script for removing proxies, check out the previous blog post (https://blogs.technet.microsoft.com/undocumentedfeatures/2017/02/10/removing-proxy-addresses-from-exchange-recipients/). I also posted the script with a few more options in the TN Gallery.

Skip to main content