Run PowerShell Against Both On-Premises and Cloud Mailboxes


In an Exchange hybrid environment, there may times when you want to access both Exchange on-premises and Exchange Online mailbox attributes from within the same PowerShell session.

For example, let's say you want to create a report of all Exchange mailboxes that are on litigation hold, whether the mailbox is still in your on-premises Exchange or has been moved to Exchange Online.  Now, Azure AD Connect does sync some mailbox hold-related attributes from on-premises AD to Azure AD including “msExchLitigationHoldDate”, “msExchLitigationHoldOwner” and “msExchUserHoldPolicies”.  These are synced from on-premises mailbox-enabled users to corresponding Azure AD mail-enabled users.  We could simply query recipient objects in Azure AD (Get-Recipient) where LitigationHoldEnabled is True but that would just be too easy.  🙂

Querying mailboxes in both premises involves open a local Exchange PS session and then opening a remote Exchange Online PS session using the -Prefix switch on session import:

  1. Open an on-premises Exchange PowerShell session
  2. Connect Exchange Online remote PS:
    • $UserCredential = Get-Credential
    • $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
    • Import-PSSession $Session -Prefix O365
  3. Get-Mailbox | ft UserPrincipalName,DisplayName,LitigationHoldEnabled | ? {$_.LitigationHoldEnabled -eq $True}
  4. Get-O365Mailbox | ft UserPrincipalName,DisplayName,LitigationHoldEnabled | ? {$_.LitigationHoldEnabled -eq $True}

As you can see, I have used "O365" as the prefix on the Exchange Online cmdlets to distinguish between the two (you can use anything you’d like).  Steps 3 and 4 simply pull on-premises and Exchange online mailbox data, respectively.  If you wanted to combine the two queries, a simple example would be something like:

  • $mbxes = @()
  • $mbxes += get-mailbox | ? {$_.LitigationHoldEnabled -eq $True}
  • $mbxes += get-o365mailbox | ? {$_.LitigationHoldEnabled -eq $True}

Now $mbxes holds a complete list of mailbox objects that have litigation hold enabled, both on-premises and in the cloud. There are lots of ways you could combine the data and report on it.  This is just a very simple example and should give good direction on the capabilities.

There are also other uses for the -Prefix option such as when connecting to both Exchange Online and Security & Compliance Center remote PS sessions where there are overlapping cmdlets.


Comments (3)
  1. GHawkins says:

    Exactly what I needed. Works like a charm. Thank you!

  2. DK says:

    Hi,
    is there a way to combine these commands in order to identify which users are hosted in the cloud and which are on premise? For example I would like to filter users with Exchange Online, so I can assigned them a specific attribute in AD.

    1. J.Beckham says:

      Sure, you should be able to do something like:

      $mbxes = @()
      $mbxes += get-mailbox -resultsize unlimited
      $mbxes += get-o365mailbox -resultsize unlimited

      The variable $mbxes would then contain a list of all mailboxes, both on-premises and Exchange Online. You should be able to identify which mailboxes are where based on a number of attributes on the objects such as database, servername, MicrosoftOnlineServicesID, etc.

      If you are in a hybrid configuration and have either migrated your mailboxes to Exchange Online or initially provisioned them as remote mailboxes, you could also use the Get-Recipient cmdlet on-premises and filter on the RecipientTypeDetails attribute (UserMailbox vs. RemoteUserMailbox).

Comments are closed.

Skip to main content