Introduction to Exchange Online PowerShell
Exchange Online PowerShell is a command-line management interface for administering and automating tasks in Exchange Online, which is a part of Microsoft 365. It allows administrators to manage user mailboxes, configure organizational settings, and perform bulk operations efficiently through scripting. Here are some benefits of using PowerShell for Exchange Online management:
- Write scripts to automate repetitive tasks, like mailbox creation and permissions assignment.
- Manage objects in bulk, such as update or modify multiple user accounts, mailboxes, or groups in one execution, as well as export and import data via CSV files.
- Connect remotely to Exchange Online from any supported device and perform administrative tasks securely over encrypted sessions.
- Get advanced reporting and auditing. For example, generate customized reports in CSV, Excel, or HTML formats, and you can audit mailbox access and administrative actions with precise filters.
- Access to hidden or advanced settings that are not exposed in the EAC web interface.
Prerequisites for Connecting to Exchange Online PowerShell
To connect to Exchange Online PowerShell, you need to meet specific prerequisites.
System Requirements
- Operating System: Windows 10, Windows 11, or Windows Server 2016/2019/2022
- Windows PowerShell 5.1 or later
- .NET Framework 4.7.2 or later
Network Requirements
- Ensure outbound HTTPS (TCP 443) traffic is allowed
- TLS 1.2 must be enabled
- Internet access and ability to connect to outlook.office365.com, login.microsoftonline.com, and graph.microsoft.com
Required Module
- Exchange Online Management module
Authentication Requirements
- For Microsoft Entra ID, the account should have the necessary permissions, such as:
- Global Administrator
- Exchange Administrator
- Accounts with MFA enabled require the Exchange Online PowerShell module for modern authentication
Required Permissions
Your account should have the appropriate RBAC (Role-Based Access Control) roles:
- Organization Management
- Recipient Management
How to Connect to Exchange Online PowerShell
The different methods to connect to Exchange Online PowerShell are:
Connect-ExchangeOnline Module (Modern Method)
You can connect to Exchange Online using the Exchange Online Management Module (EXO V2). This method is recommended for day-to-day administration and management tasks. It supports modern authentication (OAuth) and MFA.
Azure Cloud Shell (Browser-Based Connection)
This method allows admins to use Exchange Online PowerShell directly from the Azure Portal without requiring local installation. Exchange Online PowerShell is accessible from any device with a browser, and it has pre-installed modules and tools. This method is recommended for admins who prefer managing via browser or have limited access to PowerShell tools locally. The access path is: Azure Portal > Cloud Shell > PowerShell.
Exchange Online Remote PowerShell (Deprecated)
This legacy method that uses Remote PowerShell (WSMan protocol) to connect to Exchange Online PowerShell. It is deprecated and is not recommended for new deployments, but it can be used for legacy scripts or systems that do not support the newer Exchange Online Management Module. This method does not support MFA.
Using Service Principal (Certificate-Based Authentication)
This method enables unattended or script-based administration via Service Principal Accounts and certificate-based authentication. It is recommended for automation, CI/CD Pipelines, and background processes. As a prerequisite, it requires: Azure AD App Registration and certificate setup.
Comparison of the Connection Methods
Method | Best For | Supports MFA | Supports Automation |
Connect-ExchangeOnline (EXO V2 Module) | Day-to-day admin tasks | Yes | Yes |
Azure Cloud Shell | Quick browser access | Yes | No |
Remote PowerShell (WSMan) | Legacy scripts | No | Yes |
Service Principal (Certificate Auth) | Automation, CI/CD | No | Yes |
Understanding Modern Authentication and its Advantages
Modern authentication is an identity management method that leverages OAuth 2.0 and Active Directory Authentication Library (ADAL) or Microsoft Authentication Library (MSAL) for secure sign-ins. It replaces traditional authentication methods like basic authentication.
Modern authentication is the recommended and secure way to connect to Exchange Online PowerShell as it offers the following advantages:
- Enhances security as it uses OAuth 2.0 for token-based authentication instead of passing credentials directly.
- Enables the use of MFA, adding an extra layer of security.
- Allows administrators to enforce policies based on device compliance, location, or risk level, which helps limit access to Exchange Online resources based on defined conditions.
- Seamless integration with Microsoft Entra ID and third-party identity providers, with support for single sign-on (SSO).
Microsoft is deprecating basic authentication, so migration to modern authentication is critical.
Requirements for Connecting to Exchange Online PowerShell with or without MFA
Here are the requirements for connecting to Exchange Online PowerShell with or without MFA.
Without MFA (Basic Authentication – Deprecated Legacy Method) | Microsoft Entra ID account must not have MFA enabledBasic authentication must still be allowed (if not blocked organization-wide) |
With MFA (Modern Authentication) | The Microsoft Entra ID account must have MFA configuredOAuth 2.0 must be supported (default in Exchange Online) |
Step-by-Step Guide to Connecting
Here are the brief steps to connect to Exchange Online PowerShell:
- Install the Exchange Online PowerShell module.
- Connect to Exchange Online using the Connect-ExchangeOnline cmdlet. Provide your Microsoft 365 Exchange admin credentials when prompted.
- Once connected to the Exchange Online environment, you can use the cmdlets available in the Exchange Online PowerShell module to manage Exchange Online settings and objects such as mailboxes, contacts, and calendars.
Install the Exchange Online Management Module
The Exchange Online Management module can be installed on Windows, Mac, and Linux systems. Open PowerShell as an administrator and run the following command to install the latest Exchange Online Management module:
Install-Module -Name ExchangeOnlineManagement -Force
Run the following cmdlet to verify that the Exchange Online Management module is installed:
Get-Module -ListAvailable -Name ExchangeOnlineManagement
If installed correctly, it should display the module details.
The Exchange Online PowerShell module uses modern authentication for connecting to all Exchange-related PowerShell environments.
Update the module
To update the existing Exchange Online Management module, use the following cmdlet:
Update-Module ExchangeOnlineManagement
Import the module
Load the module into your PowerShell session using the following cmdlet:
Import-Module ExchangeOnlineManagement
Set Execution Policy
When connecting to Exchange Online PowerShell, the execution policy set for PowerShell determines how scripts are run on your system. RemoteSigned is the recommended policy as it ensures that:
- Locally created scripts can run without requiring a digital signature
- Scripts downloaded from the internet must be signed by a trusted publisher
Use the following cmdlet to set the execution policy to RemoteSigned:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Connect Using Basic Authentication (Deprecated)
Microsoft has permanently disabled basic authentication for Exchange Online as of October 2022. It has been replaced by modern authentication (OAuth 2.0).
Connect Using Modern Authentication
Modern authentication (OAuth 2.0) is the recommended and secure method to connect to Exchange Online PowerShell. Different methods to connect are:
Method | Connection Info |
Interactive Authentication (GUI Prompt) | This is the default connection method for most tenants, such as standard Microsoft 365 commercial tenants. Use this cmdlet to connect using modern authentication: Connect-ExchangeOnline -UserPrincipalName admin@yourdomain.com Replace admin@yourdomain.com with your Exchange Online admin account.A sign-in window will pop up; complete the login process, including multi-factor authentication (MFA) if required. |
Device Code Authentication (For Non-GUI Environments) | If you’re working in a non-GUI environment, use the -Device parameter: Connect-ExchangeOnline -UserPrincipalName admin@yourdomain.com -Device Copy the provided Device Code.Open https://microsoft.com/devicelogin in a browser.Enter the Device Code.Authenticate with your account and complete MFA (if required). |
Connect with Certificate-Based Authentication (Non-Interactive) | For automation or unattended scripts: Connect-ExchangeOnline -CertificateThumbprint “<CertificateThumbprint>” -AppId “<AppId>” -Organization “<YourTenant>” Replace: “<CertificateThumbprint>” with your certificate thumbprint”<AppId>” with the Microsoft Entra ID App ID.”<YourTenant>” with your domain (such as yourdomain.onmicrosoft.com). |
Connection Examples for Different Exchange Online Environments (GCC, GCC High, DoD)
Different Exchange Online environments require specific connection URIs and configurations when using modern authentication. Examples for these environments are:
Environment | Connection Info |
Microsoft 365 GCC (Government Community Cloud) | Use Case: US Government customers (GCC) Connect-ExchangeOnline -UserPrincipalName admin@contoso.onmicrosoft.com Replace admin@contoso.onmicrosoft.com with your Exchange Online admin account.A sign-in window will pop up; complete the login process, including multi-factor authentication (MFA), if required. |
Microsoft 365 GCC High | Use Case: US Government customers with high-security requirements Connect-ExchangeOnline -UserPrincipalName admin@yourdomain.com -ExchangeEnvironmentName O365USGovGCCHigh -ExchangeEnvironmentName – Specifies the GCC High environment explicitly |
Microsoft 365 DoD (Department of Defense) | Use Case: Reserved for the US Department of Defense (DoD) tenants Connect-ExchangeOnline -UserPrincipalName admin@yourdomain.com -ExchangeEnvironmentName O365USGovDoD -ExchangeEnvironmentName: Explicitly sets the environment to the Office 365 US Government DoD environment |
Using Multi-Factor Authentication
Step-by-step connection process with MFA enabled
Connection with Managed Identities
Using Managed Identities to connect to Exchange Online PowerShell enables secure, password-less authentication in Microsoft Entra.
What are Managed Identities?
Managed Identities allow Microsoft Entra resources to authenticate to supported services without storing credentials in scripts or code. Exchange Online supports this feature for unattended scripting using Azure Automation or similar scenarios.
System-Assigned vs. User-Assigned Managed Identities
Feature | System-Assigned | User-Assigned |
Tied to a Resource | Linked to a single Microsoft Entra resource (such as VM, Logic App). It is deleted when the resource is deleted. | Can be shared across multiple resources |
Management Scope | Automatically managed for its resource | Managed independently and reusable |
Use Case | Suitable for single-resource scenarios | Ideal for shared or multi-resource use |
Connect to Exchange Online PowerShell Using Managed Identities
Prerequisites
- Ensure your Azure resource (e.g., VM, Function App, App Service) has a system-assigned or user-assigned managed identity enabled.
- Assign the Managed Identity the necessary Microsoft Entra ID role for Exchange Online. For example:
- Exchange Administrator
- Global Reader or Global Administrator (if broader permissions are needed).
- Install and import the Exchange Online PowerShell module.
How to Connect
Use Connect-ExchangeOnline with the -ManagedIdentity parameter.
- Example for a system-assigned managed identity:
Connect-ExchangeOnline -ManagedIdentity -Organization <YourDomain>.onmicrosoft.com
- Example for a user-assigned managed identity:
# Specify the Client ID of the User-Assigned Managed Identity
Connect-ExchangeOnline -ManagedIdentity -Organization <YourDomain>.onmicrosoft.com -ManagedIdentityAccountId <UserAssignedManagedIdentityClientIdValue>
For unattended scenarios, such as automation tasks or CI/CD pipelines:
- Store the script in a secure location, such as Azure Automation, Azure DevOps, or a VM with Managed Identity enabled.
- Use Managed Identities to authenticate, avoiding the need to handle credentials explicitly.
Example Script:
# Connect to Exchange Online
Connect-ExchangeOnline -ManagedIdentity
# Example Exchange Online commands
Get-Mailbox -RecipientTypeDetails UserMailbox | Select-Object DisplayName, PrimarySmtpAddress
# Disconnect the session
Disconnect-ExchangeOnline -Confirm:$false
See the Use Azure managed identities to connect to Exchange Online PowerShell article by Microsoft for additional information.
Syntax and Common Connection Parameters
Syntax
The Connect-ExchangeOnline cmdlet has the following syntax:
Connect-ExchangeOnline
[[-ConnectionUri] <String>]
[[-AzureADAuthorizationEndpointUri] <String>]
[[-ExchangeEnvironmentName] <ExchangeEnvironment>]
[[-PSSessionOption] <PSSessionOption>]
[[-DelegatedOrganization] <String>]
[[-Prefix] <String>]
[[-CommandName] <String[]>]
[[-FormatTypeName] <String[]>]
[-AccessToken <String>]
[-AppId <String>]
[-BypassMailboxAnchoring]
[-Certificate <X509Certificate2>]
[-CertificateFilePath <String>]
[-CertificatePassword <SecureString>]
[-CertificateThumbprint <String>]
[-Credential <PSCredential>]
[-Device]
[-EnableErrorReporting]
[-InlineCredential]
[-LoadCmdletHelp]
[-LogDirectoryPath <String>]
[-LogLevel <LogLevel>]
[-ManagedIdentity]
[-ManagedIdentityAccountId <String>]
[-Organization <String>]
[-PageSize <UInt32>]
[-ShowBanner]
[-ShowProgress <Boolean>]
[-SigningCertificate <X509Certificate2>]
[-SkipLoadingCmdletHelp]
[-SkipLoadingFormatData]
[-TrackPerformance <Boolean>]
[-UseMultithreading <Boolean>]
[-UserPrincipalName <String>]
[-UseRPSSession]
[<CommonParameters>]
Common Parameters
Some basic parameters are:
Parameter | Description |
-UserPrincipalName | Specifies the account that you want to use to connect to Exchange Online PowerShell. This parameter lets you skip entering a username in the modern authentication credentials prompt. |
-Credential | Specifies the username and password that is used to connect to Exchange Online PowerShell |
-DelegatedOrganization | Specifies the customer organization you want to manage when acting as a delegated admin |
-ConnectionUri | Specifies the Exchange Online connection endpoint (used in specialized environments like GCC or China tenants) |
-CertificateThumbprint | Connects using a certificate instead of username/password. A valid value is the thumbprint value of the certificate. |
-AppId | Used with -CertificateThumbprint to specify a Microsoft Entra ID application ID |
-AccessToken | Specifies an OAuth 2.0 access token for authentication |
-Organization | Specifies the organization when you connect using CBA or managed identity |
Some optional parameters are:
Parameter | Description |
-ShowProgress | Specifies whether to show or hide the progress bar of imported cmdlets when you connect. Valid values are $true and $false. |
-SkipLoadingFormatData | Speeds up connections by skipping the loading of formatting and type data files |
-InlineCredential | Directly passes credentials in the command line to avoid prompts when connecting to Exchange Online PowerShell |
-LogDirectoryPath | Specifies the location of the log file |
-LogLevel | Specifies the logging level. Valid values are Default and All. |
-ConnectionTimeout | Specifies the timeout value (in seconds) for the connection attempt |
-Device | Typically used on computers without web browsers. You don’t need to specify a value with this switch. |
-ManagedIdentity | Specifies that you are using managed identity to connect. You do not need to specify a value with this switch. |
Specific parameters for connections in high-security environments:
For GCC environments
Parameter | Description |
-ConnectionUri | Specifies the endpoint for GCC tenants |
-EntraIDAuthorizationEndpointUri | Specifies the authorization endpoint for GCC |
-ExchangeEnvironmentName | Specifies the GCC High environment explicitly |
For DoD environments
Parameter | Description |
-ConnectionUri | Points to the DoD-specific endpoint |
-ExchangeEnvironmentName | Explicitly sets the environment to DoD |
Automating Connections
App-Only Authentication for Unattended Scripts
Certificate based authentication (CBA) or app-only authentication supports unattended script and automation scenarios by using Microsoft Entra apps and self-signed certificates.
App-only authentication allows services, scripts, or background jobs to securely access APIs and resources without the need for user interaction. This is ideal for automation scenarios such as scheduled tasks, data sync, or backend processing.
Steps to Configure App-Only Authentication
- Go to your identity provider, such as Microsoft Entra ID, and register the app. Then note down the Client ID, Tenant ID, and generate a Client Secret or upload a certificate.
- Assign the required API permissions. You should grant Application API permissions instead of Delegated API permissions.
- Create and configure a self-signed X.509 certificate. This is used to authenticate your application against Microsoft Entra ID, when requesting the app-only access token.
- Register the certificate with your application. This will enable you to use the private key (.pfx file) or the thumbprint for authentication.
- To assign appropriate RBAC roles to the application, use any of the supported built-in roles in Microsoft Entra.
Now you can connect to Exchange Online PowerShell using the cmdlets provided in the Connect Using Modern Authentication section.
See the App-only authentication for unattended scripts in Exchange Online PowerShell and Security & Compliance PowerShell article by Microsoft for additional information.
Example PowerShell Script for Unattended Authentication
$TenantId = “your-tenant-id”
$ClientId = “your-client-id”
$ClientSecret = “your-client-secret”
$Resource = “https://graph.microsoft.com/”
# Get token
$Body = @{
grant_type = “client_credentials”
client_id = $ClientId
client_secret = $ClientSecret
scope = “$Resource/.default”
}
$TokenResponse = Invoke-RestMethod -Uri “https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token” -Method Post -Body $Body
$AccessToken = $TokenResponse.access_token
Write-Output “Access Token: $AccessToken”
Connecting with Certificates
Using certificates for automation provides an added layer of security compared to client secrets. Certificates are ideal for app-only authentication in scripts or background jobs, as they avoid storing sensitive secrets as plain text.
Step-by-Step Guide to Using Certificates for Automation
- Generate a self-signed certificate. You can use tools like PowerShell, OpenSSL, or any certificate management tool to generate it.
Here is how you can generate it using PowerShell:
# Generate a self-signed certificate
$cert = New-SelfSignedCertificate -DnsName “yourapp.domain.com” -CertStoreLocation “Cert:\CurrentUser\My” -KeyExportPolicy Exportable
# Export the certificate and private key as a PFX file
$certPath = “C:\path\to\certificate.pfx”
$certPassword = ConvertTo-SecureString -String “yourpassword” -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath $certPath -Password $certPassword
- Register the application with your identity provider, such as Microsoft Entra ID. You must also upload the certificate’s public key. For that:
- Go to the app registration section.
- Add a key credential using the .crt file (public key).
- Note the App ID and Tenant ID.
- The application will use the private key to sign a JWT for app-only authentication.
Security Best Practices for Certificate-Based Connections
- Store certificates in a secure location, such as Azure Key Vault. Avoid hardcoding paths or keys in scripts.
- Use certificates with a short validity period. Rotate certificates before they expire.
- Revoke compromised or unused certificates immediately.
- Limit access to the app and its resources using the principle of least privilege, and define precise API scopes.
- Log certificate usage for auditing purposes.
- Monitor app authentication to detect unauthorized access.
- Use encryption to secure private key files, such as .pfx.
- Protect private keys with strong passwords.
- Require MFA for managing app configurations. This may require enforcing MFA for admins.
Managing Sessions and Disconnecting
Managing and terminating Exchange Online PowerShell sessions properly is crucial for maintaining security, optimizing resource usage, and preventing session exhaustion. Here are some best practices that you should follow.
Best Practices for Managing Exchange Online PowerShell Sessions
- Use the Exchange Online Management Module (EXO V2) for modern authentication and better security.
- Log in with an account that has only the permissions necessary for your tasks, such as roles like Exchange Admin and Security Admin.
- Exchange Online has a maximum session limit (3 concurrent sessions per user). Make sure sessions are closed after completing tasks to avoid hitting this limit.
- Be aware of the default timeout for Exchange Online sessions (usually 15 minutes of inactivity). If idle timeouts are frequent, optimize scripts for efficiency.
- Run scripts in a single session when possible. Avoid leaving sessions idle for long periods.
Best Practices for Terminating Exchange Online PowerShell Sessions
- Always disconnect your session when finished. Simply closing the PowerShell window without disconnecting can leave orphaned sessions. Always explicitly disconnect.
- The Remove-PSSession cmdlet doesn’t fully clean up Exchange Online sessions. Always prefer:
Disconnect-ExchangeOnline -Confirm:$false
- If you suspect orphaned sessions are consuming resources, terminate them using:
Get-PSSession | Remove-PSSession
- If a session times out, reconnect explicitly rather than assuming the session is still valid.
Enable or Disable Access to Exchange Online PowerShell for a User
You must have sufficient administrative privileges, such as the Global Administrator or Exchange Administrator role, to enable or disable user access to Exchange Online PowerShell. Moreover, membership in the Organization Management or Recipient Management role groups is also required.
Disabling PowerShell access only affects the user’s ability to connect to Exchange Online PowerShell. It does not affect their access to other services like the Microsoft 365 Admin Center.
Disable access for a user
When you disable PowerShell access, the user will not be able to connect to Exchange Online PowerShell using their credentials. Here’s the cmdlet to disable access:
Set-User -Identity <UserPrincipalName> -EXOModuleEnabled $false
Enable access for a user
When you enable PowerShell access, the user can connect to Exchange Online PowerShell. Here’s the cmdlet to enable access:
Set-User -Identity <UserPrincipalName> -EXOModuleEnabled $true
Check a user’s PowerShell access status
To verify whether a user has PowerShell access enabled or disabled, use the following command:
Get-User -Identity “<UserPrincipalName>” | Format-List EXOModuleEnabled
To get all users who do not have access to Exchange Online PowerShell, use the following cmdlet:
Get-User -ResultSize unlimited -Filter ‘RemotePowerShellEnabled -eq $false’
To get all users who have access to Exchange Online PowerShell, use the following cmdlet:
Get-User -ResultSize unlimited -Filter ‘RemotePowerShellEnabled -eq $true’
Disconnect from Exchange Online
If you’re using Exchange Online PowerShell V2 (EXO V2):
If you connected with the Connect-ExchangeOnline cmdlet, you can disconnect using the following command:
Disconnect-ExchangeOnline -Confirm:$false
The -Confirm parameter is optional and used to suppress confirmation prompts. By default, some cmdlets might ask for confirmation before proceeding with an action (like disconnecting a session).
$false indicates that you do not want to be prompted for confirmation. This allows the command to execute automatically without asking you if you are sure you want to disconnect.
If you’re using the older Exchange Online PowerShell module:
If you were using the older remote PowerShell session (for example, connecting with New-PSSession), you can disconnect by removing the session as follows:
Remove-PSSession $Session
In this case, $Session is the variable where you stored your PowerShell session object when you first connected.
Common Connection Issues and Troubleshooting
When working with Exchange Online PowerShell, you might encounter connection issues. Let’s have a look at these issues and their solutions.
Module Not Installed or Outdated
You see errors like:
- The term ‘Connect-ExchangeOnline’ is not recognized.
- Module ‘ExchangeOnlineManagement’ is not installed.
Solution:
The Exchange Online Management Module (EXO V2) should be installed and updated. Use this cmdlet to verify the module is installed correctly:
Get-Module -ListAvailable -Name ExchangeOnlineManagement
Incorrect Credentials or Authentication Issues
You may encounter issues such as:
- There is an authentication error
- MFA prompts are failing
Solution:
- Use modern authentication with the correct credentials.
- Ensure your account supports MFA and you are not blocked.
- Clear any cached credentials.
- If your account has conditional access policies, verify they allow Exchange Online access.
Session Limit Exhaustion
Too many open sessions prevent you from connecting, and you may receive an error:
- Maximum number of concurrent sessions exceeded.
Solution:
- Disconnect stale sessions.
- Ensure you disconnect properly after each session.
- Monitor active sessions.
Proxy or Firewall Blocking the Connection
The connection hangs or fails due to a proxy or firewall restriction, and you receive this error:
- Unable to connect to remote server.
Solution:
- Ensure your proxy settings are correctly configured:
- Allow Exchange Online PowerShell endpoints through the firewall:
- *.outlook.office365.com
- *.office365.com
- *.microsoftonline.com
- Test connectivity with:
Test-NetConnection outlook.office365.com -Port 443
Outdated TLS Version
You may encounter this error:
- The underlying connection was closed: An unexpected error occurred on a send.
Solution:
- Ensure your system supports TLS 1.2.
- Check your .NET version (4.6.2 or later is recommended).
Missing Permissions
You get errors like:
- Access Denied. You do not have sufficient permissions.
Solution:
- Your account must have the Exchange Administrator or appropriate role assigned.
Incorrect PowerShell Version
You might see compatibility errors if you’re using an unsupported PowerShell version.
Solution:
- Ensure you are using PowerShell 5.1 or higher:
- For PowerShell Core (7.x), ensure EXO V2 Module is compatible.
Account Lockout or Disabled Account
You get errors like:
- Your account has been locked or disabled.
Solution:
- Verify the account status in Microsoft 365 Admin Center.
- Unlock the account or reset the password if required.
DNS Resolution Issues
You get the following error:
- The remote name could not be resolved.
Solution:
- Check DNS resolution for Exchange Online endpoints.
- Use public DNS servers (e.g., 8.8.8.8 or 1.1.1.1) if DNS resolution fails.
Errors Related to PowerShell Module Conflicts
Module conflicts in PowerShell can cause various errors, such as cmdlets not being recognized, overlapping functionality, or version mismatches.
You may get errors like:
- The term ‘<cmdlet>’ is not recognized.
- Cmdlet is available in multiple modules.
- Ambiguous cmdlet reference.
Solution:
- Check all currently loaded modules and their versions using this cmdlet:
Get-Module -ListAvailable
- If a cmdlet is causing conflict, find which module the cmdlet belongs to:
Get-Command <Cmdlet-Name>
- Explicitly import the required module and force the correct module version:
Import-Module -Name ExchangeOnlineManagement -RequiredVersion 2.x.x -Force
- If an outdated or conflicting module is loaded, remove it using:
Remove-Module -Name <Module-Name>
- If multiple versions of a module are installed, uninstall older versions using:
Uninstall-Module -Name ExchangeOnlineManagement -RequiredVersion 1.x.x
REST API Connection Errors
To handle REST API connection errors in PowerShell, you need to diagnose and address issues related to authentication, network connectivity, or misconfigured requests.
Issue | Solution |
Authentication Issues Error: Authentication failures or invalid credentials. | Ensure you’re using the correct credentials and modern authentication (OAuth).Verify that your account has sufficient permissions (for example, Exchange Administrator or similar role).Use Secure Application Model or Certificate-based authentication if accessing programmatically. |
Endpoint or Module Issues Error: Unable to connect to the required endpoint. | Verify you are using the correct Exchange Online PowerShell V2 module (ExchangeOnlineManagement).Update the module to the latest version:Check the connectivity to the Exchange Online REST endpoint using the following cmdlet. It should resolve and be reachable: https://outlook.office365.com/powershell-liveid |
Network Connectivity Error: Timeouts or connection refused errors. | The required endpoints should not be blocked by firewalls or proxies. These include: *.office365.com *.microsoftonline.com Test internet connectivityIf behind a corporate proxy, ensure the proxy is configured correctly for PowerShell. |
Token Expiry Error: Authentication token expiration during the session. | Use Connect-ExchangeOnline with a persistent session, as shown below: Connect-ExchangeOnline -UserPrincipalName <your-admin-email> -ShowProgress $true Refresh your session if the token expires using the following cmdlet: Disconnect-ExchangeOnline Connect-ExchangeOnline |
TLS/SSL Protocol Issues Error: TLS errors during connection. | Ensure TLS 1.2 is enabled |
Service Outages Error: Service unavailable or intermittent connectivity. | Check the Microsoft 365 Service Health Dashboard for any ongoing issues. |
HTTP Errors These errors occur when the server returns an HTTP status code indicating failure. Common Codes: 400 Bad Request: The request is malformed (e.g., invalid JSON or parameters)401 Unauthorized: Invalid or missing authentication credentials403 Forbidden: Access is denied even though authentication is correct404 Not Found: The requested endpoint or resource does not exist500 Internal Server Error: An issue on the API server | Ensure the payload and headers meet the API documentation requirements.Verify API keys, tokens, or other credentials.Ensure your account has access rights to the requested resource.Use logs or a tool like Postman to check raw request/response data. |
SSL/TLS Errors Secure connections (HTTPS) may fail due to certificate issues. | Ensure the server’s SSL certificate is valid and trusted.For local testing, you can bypass SSL validation, but avoid this in production.Ensure your client libraries (e.g., Python requests, Node.js https) are up to date to support modern TLS versions. |
Timeout Errors These occur when the API server does not respond within the expected timeframe. | Adjust the timeout parameter in your API client to increase timeout settings.Avoid sending excessively large payloads or slow queries.Contact the API provider if timeouts are frequent as there may be server load issues. |
Rate-Limiting and Quotas APIs often have usage limits, which can lead to errors when exceeded. Error: HTTP 429 Too Many Requests | Check Rate Limits. Refer to the API documentation for request limits.Implement Throttling to space out requests to comply with the rate limits.Contact the API provider to request higher quotas. |
Key PowerShell Cmdlets for Exchange Online
To get a list of all available Exchange Online PowerShell cmdlets, use the following cmdlet:
Get-command -Module ExchangeOnlineManagement
Here’s a quick overview of key Exchange Online cmdlets, including Get-Mailbox, Get-EXOMailboxStatistics, and others, to manage mailboxes, users, and their configurations effectively.
Get-Mailbox
This cmdlet retrieves information about mailboxes in Exchange Online. You can also display specific mailboxes, such as user mailboxes, shared mailboxes, etc.
Syntax
Get-Mailbox [-Identity] <String> [-RecipientTypeDetails <RecipientTypeDetails>] [other parameters]
Common Usage Examples
- Get all mailboxes:
Get-Mailbox -ResultSize Unlimited
- Get all shared mailboxes:
Get-Mailbox -RecipientTypeDetails SharedMailbox
- Filter mailboxes by domain:
Get-Mailbox -Filter “EmailAddress -like ‘*@domain.com'”
Get-EXOMailboxStatistics
This cmdlet retrieves detailed statistics about mailboxes in Exchange Online, providing information such as mailbox size, item count, and last logon time.
Syntax
Get-EXOMailboxStatistics [-Identity] <String>
Common Usage Examples
- Get mailbox statistics for a user:
Get-EXOMailboxStatistics -Identity user@domain.com
- Retrieve all mailboxes’ sizes:
Get-EXOMailboxStatistics | Select DisplayName, ItemCount, TotalItemSize
- Get mailboxes with sizes over a specific threshold:
Get-EXOMailboxStatistics | Where-Object { $_.TotalItemSize -gt 10GB }
Get-MailboxStatistics
This cmdlet is similar to Get-EXOMailboxStatistics but works with on-premises Exchange or hybrid environments. It provides mailbox size and item count details.
Syntax
Get-MailboxStatistics [-Identity] <String>
Common Usage Examples
- Get statistics for a specific user:
Get-MailboxStatistics -Identity “user@domain.com”
- Get all mailbox sizes and last logon times:
Get-MailboxStatistics | Select DisplayName, LastLogonTime, TotalItemSize
Get-MailboxPermission
This cmdlet retrieves permissions assigned to a mailbox, including delegate access.
Syntax
Get-MailboxPermission [-Identity] <String>
Common Usage Examples
- View all permissions for a mailbox:
Get-MailboxPermission -Identity user@domain.com
- Filter for non-default permissions:
Get-MailboxPermission -Identity “user@domain.com” | Where-Object { $_.IsInherited -eq $false }
Set-Mailbox
This cmdlet modifies mailbox settings, such as quota limits, forwarding, and enabling features.
Syntax
Set-Mailbox [-Identity] <String> [-Parameters]
Common Usage Examples
- Enable mailbox forwarding:
Set-Mailbox -Identity “user@domain.com” -ForwardingSMTPAddress “forwardto@domain.com” -DeliverToMailboxAndForward $true
- Change mailbox quota:
Set-Mailbox -Identity “user@domain.com” -ProhibitSendQuota 50GB
New-Mailbox
This cmdlet creates a new mailbox for a user in Exchange Online. This cmdlet can be used for various scenarios, including creating mailboxes for individual users, shared mailboxes, and resource mailboxes like room or equipment mailboxes.
Syntax
New-Mailbox -Name <Name> -MicrosoftOnlineServicesID <UserPrincipalName> -Password (ConvertTo-SecureString -String “<Password>” -AsPlainText -Force)
Common Usage Examples
- Create a user mailbox:
New-Mailbox -Name “John Doe” -MicrosoftOnlineServicesID “johndoe@domain.com” -Password (ConvertTo-SecureString -String “P@ssw0rd!” -AsPlainText -Force)
- Create a shared mailbox:
New-Mailbox -Shared -Name “Support Team” -MicrosoftOnlineServicesID “support@domain.com”
- Create a room mailbox:
New-Mailbox -Room -Name “Conference Room 1” -MicrosoftOnlineServicesID conference1@domain.com
- Create a Shared Mailbox for a Team:
New-Mailbox -Shared -Name “HR Team” -MicrosoftOnlineServicesID “hr@domain.com” -Alias “HRTeam”
Remove-Mailbox
This cmdlet deletes a mailbox from Exchange Online. his action can be applied to various mailbox types, including user mailboxes, shared mailboxes, and resource mailboxes (such as room or equipment mailboxes).
Syntax
Remove-Mailbox -Identity <MailboxIdentity>
Common Usage Examples
- Delete a user mailbox (soft-deletes the mailbox, making it recoverable within the retention period.):
Remove-Mailbox -Identity “johndoe@domain.com”
- Permanently delete a mailbox (deletes without giving a retention period):
Remove-Mailbox -Identity “johndoe@domain.com” -Permanent
- Delete an archive mailbox only (leaves the primary mailbox intact for the specified user):
Remove-Mailbox -Identity “johndoe@domain.com” -Archive
Get-MailTrafficSummaryReport
This cmdlet retrieves a summary of mail traffic for your organization (available in Microsoft 365 environments).
Syntax
Get-MailTrafficSummaryReport [-StartDate] <DateTime> [-EndDate] <DateTime>
Common Usage Example
- Get mail traffic for the last 7 days:
$StartDate = (Get-Date).AddDays(-7)
$EndDate = Get-Date
Get-MailTrafficSummaryReport -StartDate $StartDate -EndDate $EndDate
Search-Mailbox
This cmdlet searches for specific content in a mailbox or across multiple mailboxes.
Syntax
Search-Mailbox [-Identity] <String> [-SearchQuery <Query>] [-TargetMailbox <String>]
Common Usage Examples
- Search for emails containing a specific keyword:
Search-Mailbox -Identity “user@domain.com” -SearchQuery “Subject:’Invoice'”
- Copy search results to another mailbox:
Search-Mailbox -Identity “user@domain.com” -SearchQuery “Keyword” -TargetMailbox “admin@domain.com” -TargetFolder “SearchResults”
Get-MailboxAutoReplyConfiguration
This cmdlet retrieves automatic reply (out-of-office) settings for a mailbox.
Syntax
Get-MailboxAutoReplyConfiguration [-Identity] <String>
Common Usage Example
- Get auto-reply settings for a specific user:
Get-MailboxAutoReplyConfiguration -Identity “user@domain.com”
Get-Recipient
This cmdlet retrieves all recipients (mailboxes, groups, contacts, etc.).
Syntax
Get-Recipient [-Filter] <String>
Common Usage Examples
- Get all recipients:
Get-Recipient
- Filter for specific types of recipients:
Get-Recipient -RecipientTypeDetails MailUser
Cmdlet Filters
Use filters to narrow results based on specific attributes.
Syntax
Filters are enclosed in { } and use a property operator value structure:
-Filter {Property -Operator ‘Value’}
Example
Get-Mailbox -Filter {DisplayName -like “*Test*”}
Common Operators
- -eq: Equal
- -ne: Not equal
- -like: Wildcard match (* for zero or more characters)
- -notlike: Negates -like
- -gt: Greater than
- -lt: Less than
Examples of Using Filters with Cmdlets
- Retrieve Mailboxes for a Specific Domain
Get-Mailbox -Filter {EmailAddresses -like ‘*@example.com’}
- Find Mailboxes Created After a Specific Date
Get-Mailbox -Filter {WhenCreated -gt ‘2023-01-01’}
- Get Mailboxes with Specific Display Name Patterns
Get-Mailbox -Filter {DisplayName -like ‘*Test*’}
- Get Disabled Mailboxes
Get-Mailbox -Filter {AccountDisabled -eq $true}
Examples of Combining Multiple Conditions
You can combine filters using logical operators like -and and -or.
- Get Users with Specific UPN and Display Name
Get-Mailbox -Filter {UserPrincipalName -like ‘*@example.com’ -and DisplayName -like ‘*John*’}
- Find Mailboxes Enabled but Over a Size Threshold
Get-Mailbox -Filter {AccountDisabled -eq $false -and ProhibitSendQuota -gt 10GB}
Examples of Filtering with Pipeline
Filters can also be combined with Where-Object for advanced filtering.
- Filter Mailboxes by Custom Attribute
Get-Mailbox | Where-Object { $_.CustomAttribute1 -eq ‘Value1’ }
- Get Active Mailboxes Logged In Last 30 Days
Get-MailboxStatistics | Where-Object { $_.LastLogonTime -gt (Get-Date).AddDays(-30) }
Advanced Configurations
- Use Select-Object to refine the output and only display relevant properties.
Get-Mailbox | Select-Object DisplayName, PrimarySmtpAddress
- Export results to CSV for reporting.
Get-Mailbox | Export-Csv -Path “Mailboxes.csv” -NoTypeInformation
- Default limit is 1000 results; use -ResultSize Unlimited to fetch all items.
Migrate to Exchange Online using PowerShell
Migrating to Exchange Online using PowerShell involves several steps, including preparing the on-premises environment, configuring the migration endpoints, and managing the migration process.
Prerequisites
Before performing the migration, make sure you have:
- An active Microsoft 365 or Office 365 subscription with Exchange Online.
- Admin credentials for both your on-premises Exchange server and Exchange Online.
- The Exchange Online PowerShell V2 module (EXO V2) installed.
- The Exchange Online (Hybrid) configuration set up if using hybrid migration.
Hybrid Migration (for organizations with both on-premises Exchange and Exchange Online)
In a hybrid environment, you can migrate mailboxes while maintaining coexistence between on-premises and cloud-based mailboxes.
- Install and configure the Hybrid Configuration Wizard (HCW).
The Hybrid Configuration Wizard (HCW) is the primary tool for configuring a hybrid Exchange environment. It ensures that your on-premises Exchange server is ready for hybrid coexistence with Exchange Online. You can download and run it from the Exchange Admin Center (EAC).
- Prepare the on-premises Exchange server:
- Run the Get-ExchangeServer cmdlet to ensure the correct version is being used.
- Run the New-RemoteMailbox cmdlet to create a remote mailbox for users being migrated.
- Start a migration by creating a migration batch using the New-MigrationBatch cmdlet:
New-MigrationBatch -Name “MigrationBatch” -SourceEndpoint <OnPremisesExchangeEndpoint> -TargetEndpoint <ExchangeOnlineEndpoint> -MailboxList <MailboxesToMigrate> -AutoStart -AutoComplete
Replace placeholders:
- <OnPremisesExchangeEndpoint> – The endpoint for your on-premises Exchange server
- <ExchangeOnlineEndpoint> – The endpoint for Exchange Online
- <MailboxesToMigrate> – The list of mailboxes to migrate
- To monitor the migration process:
Get-MigrationBatch | Get-MigrationUser
- Once the migration is finished, you can complete it using:
Set-MigrationBatch -Identity “MigrationBatch” -Complete
Cutover Migration (for small environments, typically fewer than 150 mailboxes)
In cutover migration, all mailboxes are migrated from on-premises Exchange to Exchange Online in a single batch.
- Use the New-MigrationEndpoint cmdlet to create an endpoint for the on-premises Exchange server:
New-MigrationEndpoint -Name “CutoverEndpoint” -ExchangeServer “<OnPremisesExchangeServer>” -Type “ExchangeRemoteMove”
- Use the New-MigrationBatch cmdlet to create a migration batch for all the mailboxes:
New-MigrationBatch -Name “CutoverMigrationBatch” -SourceEndpoint “CutoverEndpoint” -MailboxList “user1@example.com”, “user2@example.com” -TargetDeliveryDomain “<ExchangeOnlineDomain>” -AutoStart -AutoComplete
- Use the Get-MigrationBatch cmdlet to monitor the migration:
Get-MigrationBatch “CutoverMigrationBatch” | Get-MigrationUser
- After the migration is complete, you can complete it using the Set-MigrationBatch cmdlet:
Set-MigrationBatch -Identity “CutoverMigrationBatch” -Complete
Staged Migration (for medium-sized environments)
In staged migration, mailboxes are migrated in stages (typically in batches) from on-premises Exchange to Exchange Online.
- Create an endpoint for the on-premises Exchange:
New-MigrationEndpoint -Name “StagedEndpoint” -ExchangeServer “<OnPremisesExchangeServer>” -Type “ExchangeRemoteMove”
- To migrate mailboxes in stages, create a migration batch using the New-MigrationBatch cmdlet:
New-MigrationBatch -Name “StagedMigrationBatch” -SourceEndpoint “StagedEndpoint” -MailboxList “user1@example.com”, “user2@example.com” -TargetDeliveryDomain “<ExchangeOnlineDomain>” -AutoStart -AutoComplete
- Monitor the migration using:
Get-MigrationBatch “StagedMigrationBatch” | Get-MigrationUser
- Once the migration is complete, finalize it:
Set-MigrationBatch -Identity “StagedMigrationBatch” -Complete
Security Best Practices
Ensure Secure Connections
Use Secure Authentication Methods
Leverage modern authentication with OAuth instead of basic authentication. You must also enable multi-factor authentication (MFA) for all user accounts accessing Exchange Online.
Use Conditional Access Policies
Configure Conditional Access in Microsoft Entra to enforce restrictions like location, device compliance, and user risk levels. Make sure you block or limit access from unknown or risky locations.
Limit PowerShell Access
Use Role-Based Access Control (RBAC) to limit PowerShell access to only those users who need it. As a further precaution, disable remote PowerShell for accounts that do not require administrative access.
Enforce TLS Encryption
Ensure all connections to Exchange Online use TLS 1.2 or higher. You should also regularly audit systems to confirm compliance with modern encryption protocols.
Use Privileged Access Workstations (PAWs)
Restrict administrative tasks to secure, isolated workstations to reduce exposure to malware or attacks.
Use Secure Application Tokens
For unattended scripts, replace user credentials with secure app registrations in Microsoft Entra ID.
Manage User Permissions and Access Control in Exchange Online
Implement Role-Based Access Control (RBAC)
Assign predefined roles to users based on the principle of least privilege. Only assign broad roles like Global Administrator when absolutely necessary.
Monitor and Review Permissions Regularly
Periodically audit permissions and remove unnecessary access. As a routine practice, use reports from Microsoft 365 Security & Compliance Center to review access logs.
Separate Administrative Roles
Use separate accounts for administrative tasks and day-to-day user activities. Even better, assign different roles for different administrative functions like mailbox management and compliance management.
Use Just-in-Time (JIT) Access
Implement JIT access policies using Microsoft Entra ID Privileged Identity Management (PIM) to provide temporary elevated permissions.
Enable Mailbox Auditing
Enable auditing for all mailboxes to track changes and detect unauthorized access.
Recommendations for using PowerShell Securely in Production Environments
Secure Your Scripts
Avoid hardcoding credentials; use secure storage mechanisms like Azure Key Vault or Windows Credential Manager. Also use parameterized scripts and secure input handling to avoid injection vulnerabilities.
Monitor and Log PowerShell Activity
Enable PowerShell logging (module, script block, and transcript logs). You may also integrate logging with a SIEM system for real-time monitoring.
Use Signed Scripts
Sign PowerShell scripts with a trusted certificate to ensure integrity. To support it, set the PowerShell execution policy to AllSigned as it only allows signed scripts.
Run PowerShell with Least Privilege
Avoid using accounts with elevated permissions unnecessarily. Rather, use granular permissions for specific tasks.
Keep PowerShell and Modules Updated
Regularly update PowerShell to the latest version to address security vulnerabilities. Not only that, update the Exchange Online Management module to leverage the latest features and fixes.
Limit Network Access
Restrict access to Exchange Online endpoints to known IP addresses using firewall rules or Microsoft Entra ID Named Locations.
Encrypt Sensitive Data
Use SecureString or other encryption methods to store and pass sensitive data securely.
Conclusion
PowerShell for Exchange Online offers powerful capabilities for managing and automating administrative tasks, enabling administrators to handle complex operations like bulk user updates, reporting, and configuration changes. By adopting modern authentication, including OAuth and MFA, organizations can secure access to Exchange Online. Automation through PowerShell minimizes manual effort, reduces human errors, and improves overall operational consistency and scalability.
For advanced configurations and deeper learning, visit Microsoft’s official documentation, PowerShell training modules, and community forums.
Microsoft Documentation
- Exchange Online PowerShell Documentation – Comprehensive guides on connecting, managing mailboxes, compliance tasks, and more.
- Microsoft Learn – Free training modules on Exchange Online, PowerShell scripting, and security best practices.
FAQs
How do I Connect to Exchange Online via PowerShell?
You can connect to Exchange Online PowerShell using the Exchange Online Management Module (EXO V2). Azure Cloud Shell, and Service Principal (certificate-based authentication).
How to install Exchange Online in PowerShell?
To manage Exchange Online via PowerShell, you need to install the Exchange Online PowerShell V2 module (EXO V2). Use the following cmdlet to install it:
Install-Module -Name ExchangeOnlineManagement
How to connect O365 through PowerShell?
To connect to Office 365 (O365) via PowerShell, you need to use the Microsoft Online Services Sign-In Assistant and the AzureAD module or the MSOnline module, depending on the specific Office 365 services you’re working with.
- Download and install the Microsoft Online Services Sign-In Assistant.
- Run this command to install the AzureAD module:
Install-Module -Name AzureAD
Alternatively, you can use the MSOnline module if you are working with older Office 365 features:
Install-Module -Name MSOnline
- Connect to Office 365.
- For AzureAD module:
Connect-AzureAD
This cmdlet will prompt you to enter your Office 365 administrator credentials. Once logged in, you can run your PowerShell commands for Office 365.
- For MSOnline module (if you are using it):
Connect-MsolService
Again, this will prompt you for your administrator credentials.
How do I disconnect PowerShell Connect Exchange Online?
To disconnect from an Exchange Online session in PowerShell, use the following cmdlet:
Disconnect-ExchangeOnline -Confirm:$false
What is Exchange Online PowerShell
Exchange Online PowerShell is a command-line interface that allows administrators to manage and automate tasks in Exchange Online, a cloud-based email service part of Microsoft 365. Using PowerShell cmdlets, administrators can configure mailboxes, manage users, set policies, and perform other administrative functions efficiently through scripts and commands.
How to install Connect ExchangeOnline in PowerShell?
Use the following cmdlet to install the latest Exchange Online Management module:
Install-Module -Name ExchangeOnlineManagement
What is the command to connect to Exchange Online PowerShell?
To connect to Exchange Online PowerShell, use the following cmdlet from the Exchange Online PowerShell V2 (EXO V2) module:
Connect-ExchangeOnline -UserPrincipalName admin@yourdomain.com
How do I migrate to Exchange Online using PowerShell?
Migrating to Exchange Online using PowerShell typically involves hybrid migration, cutover migration, or staged migration depending on your environment. Steps for different migration types are discussed in the Migrate to Exchange Online using PowerShell section.