Connect to Exchange Online with PowerShell

Managing Exchange Online with PowerShell makes a lot of daily tasks a lot easier (and quicker). Not only for your daily tasks you may need PowerShell, but some settings in Exchange Online can only be changed with PowerShell. So how do you connect to Exchange Online with PowerShell?

connect to exchange online powershell

The latest version of Exchange Online Powershell Module, EXO V3, that we are going to use supports modern authentication and MFA. So you don’t need to create an app password anymore. Also, the new module is faster compared to the old Exchange Online module and more secure.

Install Exchange Online Module

Requirements for EXO V3

The previous version of the Exchange Online PowerShell module (EXO v2) was only supported on Windows and required PowerShell 5.x. EXO V3 module however fully supports PowerShell 7, macOS, and Linux. So that is great news.

You will need to configure PowerShell to run remote scripts. By default this is disabled.

  1. Open PowerShell in an elevated mode
    Press Windows key + X and choose Windows PowerShell (admin)
  2. Set the execution policy to Remote Signed:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

You only need to set this once per computer. If haven’t set the execution policy and try to connect to Exchange Online you will get an error:

Files cannot be loaded because running scripts is disabled on this system. Provide a valid certificate with which to sign the files.

Install the Exchange Online V3 Module in PowerShell

We need to install the EXO V3 Module in PowerShell before we can connect to Exchange Online. Again open an Elevated Windows PowerShell window:

  1. Open PowerShell in an elevated mode
    Press Windows key + X and choose Windows PowerShell (admin)
  2. Install PowerShellGet
    We need to install PowerShellGet before we can install the EXO V3 Module.
# Close and re-open your PowerShell window when done
Install-Module -Name PowerShellGet -Force
  1. Install EXO V3 module
    We can now install the latest Exchange Online PowerShell module with the Install-Module cmdlet
# Add -Force to it when you need to update EXO V3.
Install-Module -Name ExchangeOnlineManagement -Force

Automatically check if EXO Module is installed

Are you going to use the Exchange Online module in a script? Then make sure you automatically check if the module is installed before your try to connect.

Using a single cmdlet, we can list all installed modules in PowerShell. You can prevent unnecessary errors by verifying that the ExchangeOnlineManagement module is available.

if ($null -ne (Get-Module -ListAvailable -Name ExchangeOnlineManagement)){
 # Your script goes here
}

The cmd above should return a list of installed Exchange Online modules. If the result is empty (null), then we know that the module isn’t installed.

Update Exchange Online PowerShell Module

PowerShell modules are often updated, including the Exchange Online Module. The latest version EXO v3 comes with a couple of improvements that make it worth updating your PowerShell Module.

  • Better performance – New EXO cmdlets are REST API-based
  • More secure – V3 uses Modern Authentication
  • More reliable
  • Certificate-based authentication
  • UseRPSSession Switch – Gives access to all existing remote PowerShell cmdlets.

To update the Exchange Online PowerShell Module we can use the following command in an elevated PowerShell window:

Update-Module -Name ExchangeOnlineManagement

And verify the update with:

Get-Module ExchangeOnlineManagement

To benefit from the new features, make sure that you update your Get-* cmdlet’s to their Get-EXO* counterparts. You can find an up-to-date list of the new cmdlets in the documentation.

Connect to Exchange Online with PowerShell

With the Exchange Online Module installed, we can now easily connect to Exchange Online with a single cmd in PowerShell:

Connect-ExchangeOnline -UserPrincipalName [email protected]

After you connected to Exchange Online you will get by default output with information about the EXO module. We can hide the banner by using the parameter -ShowBanner:$false

-ShowBanner:$falseConnect-ExchangeOnline -UserPrincipalName [email protected] -ShowBanner:$false

The new EXO V3 module also supports connecting to another tenant. If you are a Microsoft Partner or when you are managing multiple tenants, then you can connect to another tenant by adding the -DelgatedOrganization switch:

Connect-ExchangeOnline -UserPrincipalName [email protected] -DelegatedOrganization contoso.onmicrosoft.com

Connect to Exchange Online Function for PowerShell

The complete function below can be used in scripts to connect to Exchange Online. This function checks if the Exchange Online module is installed, and when it gives the option to automatically install it for you.

It also checks for any existing Exchange Online connections in PowerShell, preventing multiple connections from the same session.

Function ConnectTo-EXO {
  <#
    .SYNOPSIS
        Connects to EXO when no connection exists. Checks for EXO v3 module
  #>
  param(
    [Parameter(
      Mandatory = $true
    )]
    [string]$adminUPN
  )
  
  process {
    # Check if EXO is installed and connect if no connection exists
    if ($null -eq (Get-Module -ListAvailable -Name ExchangeOnlineManagement))
    {
      Write-Host "Exchange Online PowerShell v3 module is requied, do you want to install it?" -ForegroundColor Yellow
      
      $install = Read-Host Do you want to install module? [Y] Yes [N] No 
      if($install -match "[yY]") { 
        Write-Host "Installing Exchange Online PowerShell v3 module" -ForegroundColor Cyan
        Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force
      }else{
	      Write-Error "Please install EXO v3 module."
      }
    }

    if ($null -ne (Get-Module -ListAvailable -Name ExchangeOnlineManagement)) {
      # Check which version of Exchange Online is installed
      if (Get-Module -ListAvailable -Name ExchangeOnlineManagement | Where-Object {$_.version -like "3.*"} ) {
        # Check if there is a active EXO sessions
        if ((Get-ConnectionInformation).tokenStatus -ne 'Active') {
          write-host 'Connecting to Exchange Online' -ForegroundColor Cyan
          Connect-ExchangeOnline -UserPrincipalName $adminUPN
        }
      }else{
        # Check if there is a active EXO sessions
        $psSessions = Get-PSSession | Select-Object -Property State, Name
        If (((@($psSessions) -like '@{State=Opened; Name=ExchangeOnlineInternalSession*').Count -gt 0) -ne $true) {
          write-host 'Connecting to Exchange Online' -ForegroundColor Cyan
          Connect-ExchangeOnline -UserPrincipalName $adminUPN
        }
      }
    }else{
      Write-Error "Please install EXO v3 module."
    }
  }
}

Connect to Exchange Online as Delegated Admin (partner)

When you are managing multiple tenants, you might need to connect to Exchange Online as well. Instead of using a dedicated admin login from the client’s tenant, you can also connect to Exchange Online as delegated admin.

This way, you can use your own credentials to authenticate. To do this you will need to use the parameter -DelegatedOrganization.

# Replace stonegrovebank.onmicrosoft.com with the organization that you want to manage
Connect-ExchangeOnline -DelegatedOrganization stonegrovebank.onmicrosoft.com

# Optional, you can specify your username as well
Connect-ExchangeOnline -UserPrincipalName [email protected] -DelegatedOrganization stonegrovebank.onmicrosoft.com

You can now manage all the mailboxes from the partner tenant.

Connecting Exchange Online to PowerShell without Modern Authentication

You can use the following method to connect to Exchange Online in PowerShell if your account doesn’t support Modern Authentication yet:

$cred = Get-Credential

Connect-ExchangeOnline -Credential $cred -ShowProgress $true

Check if Exchange Online is Connected

It’s a good idea to check if a connection already exists when using the Exchange Online module in scripts. Keep in mind that you can only have 5 simultaneous connections to Exchange Online. And you probably don’t want to log in if you don’t need to.

We can use the cmdlet Get-ConnectionInformation since EXO v3. If you are using an older version of Exchange Online, then you will need to use Get-PSSession.

Get-ConnectionInformation
Get-ConnectionInformation
connect exchange online powershell
Get-PSSession.

With the snippet below you can check if there is an active ExchangeOnline session for both V3 and older versions. We first check if the ExchangeOnline module is installed, and then if version 3.x is installed are not. Then depending on the version, we check for existing connections.

if ($null -ne (Get-Module -ListAvailable -Name ExchangeOnlineManagement)) {
      # Check which version of Exchange Online is installed
      if (Get-Module -ListAvailable -Name ExchangeOnlineManagement | Where-Object {$_.version -like "3.*"} ) {
        # Check if there is a active EXO sessions
        if ((Get-ConnectionInformation).tokenStatus -ne 'Active') {
          write-host 'Connecting to Exchange Online' -ForegroundColor Cyan
          Connect-ExchangeOnline -UserPrincipalName $adminUPN
        }
      }else{
        # Check if there is a active EXO sessions
        $psSessions = Get-PSSession | Select-Object -Property State, Name
        If (((@($psSessions) -like '@{State=Opened; Name=ExchangeOnlineInternalSession*').Count -gt 0) -ne $true) {
          write-host 'Connecting to Exchange Online' -ForegroundColor Cyan
          Connect-ExchangeOnline -UserPrincipalName $adminUPN
        }
      }
    }

Getting mailbox information

With the new EXO V3 module you can now easily get the mailbox details with the following shorthand:

# Old way:
Get-ExoMailbox -identity [email protected]

# With the EXO V2 module you can write the following shorthand
Get-ExoMailbox johndoe

Disconnecting your Sessions

Always make sure you disconnect your Exchange Online session before you close your PowerShell window. If you don’t close the session, you may end up using all 5 remote PowerShell connections to Exchange Online. If that happens you will need to wait for the sessions to expire before you can reconnect.

Disconnect-ExchangeOnline

Connecting PowerShell to Exchange Online Alternative

If you can’t use the new EXO v2 module, because you are using Basic Authentication for example, then you still can connect to Exchange Online. Keep in mind that this gets eventually deprecated, so when possible use the Modern Authentication option described earlier.

For the basic authentication method, we are going to import the Exchange Online cmdlets. First, make sure that you have set the execution policy to remote signed:

  1. Open PowerShell in an elevated mode
    Press Windows key + X and choose Windows PowerShell (admin)
  2. Set the execution policy to Remote Signed:
Set-ExecutionPolicy RemoteSigned
  1. To connect to Exchange Online we first need to store our credentials:
$cred = Get-Credential
  1. Next, we can create and import the Exchange Online cmdlet into PowerShell:
# Create the session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection

# Import it into your PowerShell session
Import-PSSession $Session -DisableNameChecking

Make sure you disconnect your session when you are done:

Remove-PSSession $Session

Frequently Asked Questions

Error : Files cannot be loaded because running scripts ….

If you get the error “Files cannot be loaded because running scripts is disabled on this system. Provide a valid certificate with which to sign the files.” then you have forgotten to set the execution policy.

Run the following cmd in an elevated PowerShell Window:
Set-ExecutionPolicy RemoteSigned

Cannot validate argument on parameter ‘Session’ – error

You are trying to connect to Exchange Online with an MFA-enabled account while using the basic authentication option.

Make sure you install the latest Exchange Online Module, EXO V3, as explained in the beginning of the article.

Fail to create a runspace because you have exceeded the maximum number of connections allowed

You have used all 5 available connections to Exchange Online. Make sure you disconnect your PowerShell sessions.

To close the current sessions you get to run the following cmd:

Get-PSSession | Remove-PSSession

Connecting to remote server outlook.office365.com failed with the following
error message : Access is denied

To connect to Exchange Online you will need to use an account that is global admin in Office 365. The account that you are connecting with doesn’t have the correct permissions.

Wrapping up

The new Exchange Online module is really powerful and makes working with Exchange Online a lot easier. I hope this article helped you to get started. If you have any questions, just drop a comment below.

You may also like the following articles:

Get more stuff like this

IT, Office365, Smart Home, PowerShell and Blogging Tips

I hate spam to, so you can unsubscribe at any time.

12 thoughts on “Connect to Exchange Online with PowerShell”

  1. Hey Ruud,

    I’m getting errors when I’m trying to connect to Exchange Online and I don’t know what I’m doing wrong. I’m getting the error after the “Connect-ExchangeOnline”-command:

    —————————————————————————————-
    This V3 EXO PowerShell module contains new REST API backed Exchange Online cmdlets which doesn’t require WinRM for Client-Server communication. You can now run these cmdlets after turning off WinRM Basic Auth in your client machine thus making it more secure.

    Unlike the EXO* prefixed cmdlets, the cmdlets in this module support full functional parity with the RPS (V1) cmdlets.

    V3 cmdlets in the downloaded module are resilient to transient failures, handling retries and throttling errors inherently.

    However, REST backed EOP and SCC cmdlets are not available yet. To use those, you will need to enable WinRM Basic Auth.

    For more information check https://aka.ms/exov3-module
    —————————————————————————————-

    I can’t really understand what I need to do to get it working. Could you help out by any chance?

  2. How replace below code in Exchange module V3

    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.c… -Credential $credentials -Authentication Basic -AllowRedirection

    Import-PSSession $session -CommandName Search-UnifiedAuditLog

      • Ok, so below code is fine? NewPSSession not required any more?

        1st to make connection with Exchange –

        Connect-ExchangeOnline -Credential $credentials -ErrorVariable connectEx -ShowBanner:$false

        # Check result
        If (!$?) {
        Return @{message=”Failed to connect to Microsoft Exchange Online Services.”;error=$connectEx;fail=$true}
        }

        2 step is to execute direct command for Audit Log –

        $auditEvents = Search-UnifiedAuditLog -RecordType SharePointFileOperation -Operations FileAccessed

        • Yeah almost:


          Connect-ExchangeOnline -UserPrincipalName [email protected]

          Search-UnifiedAuditLog -RecordType SharePointFileOperation -Operations FileAccessed -StartDate 01-01-2023 -EndDate 01-02-2023

          EndDate is at least required. And for Connect-ExchangeOnline, I find it easier to use the UserPrincipalName. This way MFA will also work.

          • Thanks a lot Rudy for your quick help. Really appreciate. Great article by the way. In case of any more queries ahead will connect. Thank you. 🙂

  3. The problem I have with this new connection is that I cannot import a connection any longer as we could with import-pssession.

    When I setup a connection in a runspace (created from a pool), that works great, but when I do a Disconnect-ExchangeOnline in one runspace, it is disconnected in all others as well.

    It seems there is no way to disconnect this is only one runspace.

  4. Great article. You may want to put in a comment about the Get-PSSession not working with the Exchange Online PowerShell Module, EXO V3. I kept getting no entries for Get-PSSession.

    This link: https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#updates-for-version-300-the-exo-v3-module

    contains the following note from Microsoft:

    “Use the Get-ConnectionInformation cmdlet to get information about REST-based connections to Exchange Online PowerShell. This cmdlet is required because the Get-PSSession cmdlet in Windows PowerShell doesn’t return information for REST-based connections.”

  5. I have been jumping from page to page trying a lot of code and FINALLY found one that worked! Thank you so much!!! You are man!

Leave a Comment

0 Shares
Tweet
Pin
Share
Share