Determine if a Mailbox is On-Premises or in Office 365 with PowerShell

One of the companies that I support is currently in the process of migrating from an on-premises Exchange Server environment to Office 365. They’re currently running in hybrid mode. While it seems like wanting to know what mailboxes still exist onsite versus which ones are in the cloud would be an all too common task, there doesn’t seem to be an easy way to get that information with PowerShell. You would think that you’d be able to run a PowerShell command and it would return the results. Well, not unless I’m missing something. There’s no such command, or at least not one that’s straight forward.

Note: This blog article is written using Windows 10 version 1803 and Windows PowerShell version 5.1. Your mileage may vary with different operating systems and/or different versions of PowerShell.

Follow the first few steps in this previous blog article to install the MSOnline PowerShell module and connect to your Office 365 subscription. The Get-MsolUser cmdlet which is part of the MSOnline PowerShell module will be used in this blog article.

At first, it doesn’t appear that Get-MsolUser returns any usable results for this type of information, but it does return a MSExchRecipientTypeDetails property which is a numeric value that can be translated into the mailbox’s location. One thing that’s disappointing about this cmdlet is there are almost no filters for it. Want unlicensed users, no problem, use the -UnlicensedUsersOnly parameter. Want the opposite condition, we’ll you’re out of luck with the exception of retrieving all of the users and piping them to Where-Object. Not real efficient when you have thousands of users and the majority of them have yet to be licensed. Luckily, for these users, a usage location hasn’t been assigned and won’t be until they’re ready to be licensed. All of them reside in the United States so filtering using the -UsageLocation parameter is possible. Others may not be so lucky.

The previous command is written so that any users with a usage location of “US” that have a license will be returned in the results. The filter can easily be changed to meet your own needs. For example, to show unlicensed users and all of those will definitely be on-premises.

Another option is to use the Get-Recipient function that’s part of the Exchange online PowerShell cmdlets. More information about those cmdlets can be found in this blog article. Get-Recipient seems to have better options for filtering, but at the expense of being less accurate. It doesn’t seem to show mailboxes that only exist in Office 365 (ones that weren’t migrated) and things like the Discovery mailbox would need to be filtered out. Mailboxes that have been migrated have a RecipientType of “UserMailbox” and the ones that still exist on-premises have a RecipientType of “MailboxUser“.

If you know of an easier way to accomplish this task, please post it as a comment to this blog article.



  1. Michael B. Smith

    MailboxPlan from Get-Mailbox will be populated for an Office 365 mailbox but not for an on-premises mailbox.

    You can also acquire a list of on-premises servers (Get-ExchangeServer) and get all mailboxes for that server (Get-Mailbox -Server …). You can also acquire a list of on-premises mailbox databases (Get-MailboxDatabase) and get all mailboxes for that database (Get-Mailbox -Database …).

  2. Tim Davis

    If your goal is to determine which mailboxes are still on prem, than the EXO shell should not be your first stop. EXO will only report mailboxes that are in AADC sync scope. By going to the on perm Exchange server, you can get a definitive list.

    From the on perm Exchange shell:

    #To get a list of all mailboxes on premise. if you have any child domains, set ad-serversettings
    set-adserversettings -viewentireforest $true
    get-mailbox -resultsize unlimited | export-csv

  3. Barry

    A search lead me here, posting my solution in case others follow the same path here.
    We had migrated 2 different on prem exchanges into a 3rd and then moved what we thought was everything to 365. We had checked mailboxes left on prem, there were none. We have over 20,000 users which makes some of the commands not helpful without filters.

    What we found were mailusers, i think of these as pointers to a mailbox elsewhere, either on prem or on another domain.

    Finding and tidying the on prem mailusers was fairly easy most were for leavers where we hadn’t migrated them between domains.

    My challenge was ensuring I didn’t have accounts 365 thought were on prem when they were not.

    What I used was on the exchange 365 powershell
    Get-MailUser -Filter {RecipientTypeDetails -ne ‘GuestMailUser’} | select Name, PrimarySmtpAddress, Alias, RecipientTypeDetails,UserPrincipalName | Export-Csv C:\temp\365mailuserNotGuest2.csv -NoTypeInformation

    Without the RecipientTypeDetails bit it listed external guest users which i didn’t care about.

  4. David

    When I connect to the On-pre Exchange shell, I can retrieve the EOL Malboxes with Cmdlet: Get-RemoteMailbox
    # On prem
    get-mailbox -identity IDENTITY

    # Online
    get-remotemailbox -identity IDENTITY

  5. Josh (Windos) King (@WindosNZ)

    I’ve recently had to edit some of my scripts to account for user’s mailboxes being either of On-Prem or Cloud. I ended up using AD to determine the mailbox location via the ‘msExchRemoteRecipientType’ attribute.

    If this is null, the mailbox is on-prem (or doesn’t exist), any other values tell you details like if they are in the cloud, if they have an archive, etc.

    This only works for synced users (which works for us, as all our users are born On-Prem).

  6. boe dillard

    Josh – could you please give the full command? I want to know who is still on premise – they are all ad synced – some may have licenses but not be migrated yet

  7. Ed

    My issue is not so much User mailboxes, but Shared Mailboxes. How do I determine which Shared mailboxes are still OnPrem? I’m sure that I have some OnPrem, but when I look at the EMC Shared Mailboxes and add the column, DATABASE, it doesn’t look like that is populating correctly.

    • Geoff

      You all are much deeper than I so please help. Is there a way for an end user to verify that they are working in O365 not on-prem?

  8. Paul Gee

    Get-MsolUser -UsageLocation US |
    Where-Object isLicensed -eq $true |
    Select-Object -Property DisplayName,
    @{N=’Is Licensed?’;E={$_.islicensed}},
    @{N=’License Type’;E={$_.Licenses.AccountSkuId}},
    @{label=’MailboxLocation’;expression={switch ($_.MSExchRecipientTypeDetails) {1 {‘Onprem’; break}2147483648 {‘Office365’; break}default {‘Unknown’}}}} | Sort -Property DisplayName | Format-Table | Export-CSV c:\scripts\mailusers.csv -NoTypeInformation

  9. Derek

    And simple way to determine where a mailbox resides is to look at the target address and see if it is populated with a Microsoft tenant namespace.

  10. Jon W

    This script works for me, but I want to know how to send the output to a text file.

  11. Ben I

    Can someone share a shell command to list all mailboxes migrated from Office 365 to On-Prem servers? And, shell command to list mailboxes who are still hosted on Office 365? Thanks


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: