
Microsoft Exchange PowerShell V3
Summary
This comprehensive guide covers all modern methods for connecting to Microsoft Exchange Online using the Exchange Online PowerShell V3 module. All legacy authentication methods, including Basic Authentication and Remote PowerShell (RPS), have been deprecated and are no longer supported.
Installing the Exchange Online PowerShell Module
Step 1: Check for Existing Module
First, verify if the module is already installed:
Get-Module -ListAvailable -Name ExchangeOnlineManagement
Step 2: Install or Update the Module
To install the latest version of the Exchange Online Management module:
Install-Module -Name ExchangeOnlineManagement -Force -AllowClobber
If the module is already installed, update it to the latest version:
Update-Module -Name ExchangeOnlineManagement
To install for the current user only (no administrator rights required):
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -Force
Step 3: Verify Installation
Confirm the module is installed correctly:
Get-InstalledModule -Name ExchangeOnlineManagement
Step 4: Import the Module (Optional)
While the module loads automatically when you run connection commands, you can manually import it:
Import-Module ExchangeOnlineManagement
Connection Method 1: Interactive Authentication (with MFA Support)
This is the recommended method for manual administrative tasks. It supports multi-factor authentication and provides an interactive sign-in experience.
Basic Interactive Connection
Connect-ExchangeOnline -UserPrincipalName admin@365adviser.com
What happens:
- A browser window or authentication prompt appears
- Enter your password
- Complete MFA verification if enabled (Microsoft Authenticator app, SMS code, etc.)
- Upon success, you’re connected to Exchange Online PowerShell
Interactive Connection Without Showing Banner
To suppress the connection banner message:
Connect-ExchangeOnline -UserPrincipalName admin@365adviser.com -ShowBanner:$false
Connection with Specific Cmdlet Help Loading
To enable Get-Help for Exchange Online cmdlets (version 3.7.0 or later):
Connect-ExchangeOnline -UserPrincipalName admin@365adviser.com -LoadCmdletHelp
Complete Example Script
# Import the module Import-Module ExchangeOnlineManagement # Connect to Exchange Online Connect-ExchangeOnline -UserPrincipalName admin@365adviser.com -ShowBanner:$false # Verify connection Get-ConnectionInformation # Run Exchange Online commands Get-Mailbox -ResultSize 10 # Disconnect when finished Disconnect-ExchangeOnline -Confirm:$false Connection Method 2: Non-Interactive Authentication (Stored Credentials)
This method allows connection without interactive prompts using stored credentials. Note: This method is less secure and should only be used in trusted environments. MFA must be disabled on the account.
Storing Credentials Securely
# Prompt for credentials and store them $UserCredential = Get-Credential # Connect using stored credentials Connect-ExchangeOnline -Credential $UserCredential
Using Encrypted Password
# Convert password to secure string $Password = ConvertTo-SecureString -String 'YourPassword' -AsPlainText -Force # Create credential object $Credential = New-Object System.Management.Automation.PSCredential ('admin@365adviser.com', $Password) # Connect to Exchange Online Connect-ExchangeOnline -Credential $Credential
Complete Script Example
# Define credentials $Username = "admin@365adviser.com" $Password = ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force $Credential = New-Object System.Management.Automation.PSCredential ($Username, $Password) # Connect to Exchange Online Connect-ExchangeOnline -Credential $Credential -ShowBanner:$false # Verify connection Get-EXOMailbox -Identity admin@365adviser.com # Disconnect Disconnect-ExchangeOnline -Confirm:$false
Security Warning: Never hardcode passwords in scripts. Use Azure Key Vault or secure credential storage solutions for production environments.
Connection Method 3: Certificate-Based Authentication (App-Only for Automation)
Certificate-based authentication enables unattended scripts and automation scenarios without storing user credentials. This is the recommended approach for automated tasks, scheduled scripts, and CI/CD pipelines.
Prerequisites for Certificate-Based Authentication
- Azure AD app registration
- Self-signed or CA-issued certificate
- Exchange Administrator role assigned to the app
- API permissions configured
Step 1: Create a Self-Signed Certificate
Generate a self-signed certificate using PowerShell:
# Define certificate parameters $CertificateName = "ExchangeOnlineAutomation" $CertificateSubject = "CN=$CertificateName" $ExpirationYears = 2 # Create the certificate $Certificate = New-SelfSignedCertificate ` -Subject $CertificateSubject ` -CertStoreLocation "Cert:\CurrentUser\My" ` -KeyExportPolicy Exportable ` -KeySpec Signature ` -KeyLength 2048 ` -KeyAlgorithm RSA ` -HashAlgorithm SHA256 ` -NotAfter (Get-Date).AddYears($ExpirationYears) # Display certificate thumbprint (save this for later) Write-Host "Certificate Thumbprint: $($Certificate.Thumbprint)" -ForegroundColor Green
Step 2: Export the Certificate
Export the certificate for upload to Azure AD:
# Export certificate to .cer format (public key only) $CertificatePath = "C:\Certificates\ExchangeOnlineAutomation.cer" Export-Certificate -Cert $Certificate -FilePath $CertificatePath # Export certificate with private key to .pfx format (for backup or other machines) $PfxPassword = ConvertTo-SecureString -String "SecurePassword123!" -AsPlainText -Force $PfxPath = "C:\Certificates\ExchangeOnlineAutomation.pfx" Export-PfxCertificate -Cert $Certificate -FilePath $PfxPath -Password $PfxPassword
Step 3: Register an Application in Azure AD
- Navigate to Azure Portal > Azure Active Directory > App registrations
- Click New registration
- Provide an application name (e.g., “Exchange Online PowerShell Automation”)
- Select Accounts in this organizational directory only
- Click Register
- Copy and save the Application (client) ID and Directory (tenant) ID
Step 4: Upload Certificate to the Application
- In your app registration, go to Certificates & secrets
- Click Upload certificate
- Upload the .cer file created in Step 2
- Note the certificate Thumbprint displayed
Step 5: Configure API Permissions
- In your app registration, go to API permissions
- Click Add a permission
- Select APIs my organization uses
- Search for and select Office 365 Exchange Online
- Select Application permissions
- Expand Exchange and select Exchange.ManageAsApp
- Click Add permissions
- Click Grant admin consent for [your organization]
- Click Yes to confirm
Step 6: Assign Azure AD Role to the Application
The application needs the Exchange Administrator role:
Option A: Using Azure Portal
- Navigate to Azure Active Directory > Roles and administrators
- Search for and select Exchange Administrator
- Click Add assignments
- Search for your application name
- Select it and click Add
Option B: Using PowerShell
# Install Microsoft Graph module if not already installed Install-Module Microsoft.Graph -Scope CurrentUser -Force # Connect to Microsoft Graph Connect-MgGraph -Scopes RoleManagement.ReadWrite.Directory # Get the service principal for your app $AppId = "YOUR-APP-ID-HERE" $ServicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$AppId'" # Get the Exchange Administrator role definition $RoleDefinition = Get-MgRoleManagementDirectoryRoleDefinition ` -Filter "DisplayName eq 'Exchange Administrator'" # Assign the role to the service principal New-MgRoleManagementDirectoryRoleAssignment ` -PrincipalId $ServicePrincipal.Id ` -RoleDefinitionId $RoleDefinition.Id ` -DirectoryScopeId "/" Write-Host "Exchange Administrator role assigned successfully" -ForegroundColor Green
Step 7: Connect Using Certificate-Based Authentication
Using Certificate Thumbprint
# Define connection parameters $AppId = "12345678-1234-1234-1234-123456789012" $CertificateThumbprint = "1234567890ABCDEF1234567890ABCDEF12345678" $Organization = "contoso.onmicrosoft.com" # Connect to Exchange Online Connect-ExchangeOnline ` -AppId $AppId ` -CertificateThumbprint $CertificateThumbprint ` -Organization $Organization ` -ShowBanner:$false # Verify connection Get-EXOMailbox -ResultSize 5 # Disconnect Disconnect-ExchangeOnline -Confirm:$false
Using Certificate File Path
# Define connection parameters $AppId = "12345678-1234-1234-1234-123456789012" $CertificatePath = "C:\Certificates\ExchangeOnlineAutomation.pfx" $CertificatePassword = ConvertTo-SecureString -String "SecurePassword123!" -AsPlainText -Force $Organization = "365adviser.com" # Connect to Exchange Online Connect-ExchangeOnline ` -AppId $AppId ` -CertificateFilePath $CertificatePath ` -CertificatePassword $CertificatePassword ` -Organization $Organization ` -ShowBanner:$false
Complete Automation Script Example
<# .SYNOPSIS Exchange Online automation script using certificate-based authentication .DESCRIPTION This script connects to Exchange Online using app-only authentication and performs automated mailbox management tasks #> # Import required module Import-Module ExchangeOnlineManagement # Define connection parameters $AppId = "12345678-1234-1234-1234-123456789012" $CertificateThumbprint = "1234567890ABCDEF1234567890ABCDEF12345678" $Organization = "contoso.onmicrosoft.com" try { # Connect to Exchange Online Write-Host "Connecting to Exchange Online..." -ForegroundColor Cyan Connect-ExchangeOnline ` -AppId $AppId ` -CertificateThumbprint $CertificateThumbprint ` -Organization $Organization ` -ShowBanner:$false ` -ErrorAction Stop Write-Host "Connected successfully!" -ForegroundColor Green # Perform automated tasks Write-Host "Retrieving mailbox statistics..." -ForegroundColor Cyan $Mailboxes = Get-EXOMailbox -ResultSize Unlimited $MailboxStats = $Mailboxes | ForEach-Object { Get-EXOMailboxStatistics -Identity $_.UserPrincipalName } # Export results $MailboxStats | Export-Csv -Path "C:\Reports\MailboxStats_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation Write-Host "Report generated successfully!" -ForegroundColor Green } catch { Write-Error "An error occurred: $_" } finally { # Disconnect from Exchange Online Write-Host "Disconnecting from Exchange Online..." -ForegroundColor Cyan Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue Write-Host "Disconnected" -ForegroundColor Green }
Connection Method 4: Managed Identity Authentication (Azure Resources)
Managed identities provide an identity for Azure resources to use when connecting to Exchange Online, eliminating the need to manage credentials. This method is ideal for Azure Automation, Azure Functions, and Azure Virtual Machines.
Prerequisites
- Azure resource with managed identity enabled (Automation Account, VM, or Function App)
- Exchange Administrator role assigned to the managed identity
- Exchange.ManageAsApp API permission granted
Step 1: Enable Managed Identity on Azure Resource
For Azure Automation Account
# Connect to Azure Connect-AzAccount # Define parameters $ResourceGroupName = "rg-ExchangeAutomation" $AutomationAccountName = "aa-ExchangeOnline" $Location = "East US" # Create resource group if it doesn't exist New-AzResourceGroup -Name $ResourceGroupName -Location $Location -Force # Create Automation Account with system-assigned managed identity New-AzAutomationAccount ` -ResourceGroupName $ResourceGroupName ` -Name $AutomationAccountName ` -Location $Location ` -AssignSystemIdentity # Or enable managed identity on existing account Set-AzAutomationAccount ` -ResourceGroupName $ResourceGroupName ` -Name $AutomationAccountName ` -AssignSystemIdentity
For Azure VM
# Enable system-assigned managed identity on VM $VM = Get-AzVM -ResourceGroupName "YourResourceGroup" -Name "YourVMName" Update-AzVM -ResourceGroupName "YourResourceGroup" -VM $VM -IdentityType SystemAssigned
Step 2: Get Managed Identity Principal ID
# For Automation Account $AutomationAccount = Get-AzAutomationAccount ` -ResourceGroupName $ResourceGroupName ` -Name $AutomationAccountName $PrincipalId = $AutomationAccount.Identity.PrincipalId Write-Host "Managed Identity Principal ID: $PrincipalId" -ForegroundColor Green
Step 3: Assign API Permissions to Managed Identity
# Connect to Microsoft Graph Connect-MgGraph -Scopes AppRoleAssignment.ReadWrite.All, Application.Read.All # Get the service principal for Exchange Online $ExoServicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '00000002-0000-0ff1-ce00-000000000000'" # Get the Exchange.ManageAsApp permission $AppRole = $ExoServicePrincipal.AppRoles | Where-Object {$_.Value -eq "Exchange.ManageAsApp"} # Get the managed identity service principal $ManagedIdentitySP = Get-MgServicePrincipal -Filter "Id eq '$PrincipalId'" # Assign the permission New-MgServicePrincipalAppRoleAssignment ` -ServicePrincipalId $ManagedIdentitySP.Id ` -PrincipalId $ManagedIdentitySP.Id ` -ResourceId $ExoServicePrincipal.Id ` -AppRoleId $AppRole.Id Write-Host "Exchange.ManageAsApp permission granted" -ForegroundColor Green
Step 4: Assign Exchange Administrator Role
# Connect to Microsoft Graph with required permissions Connect-MgGraph -Scopes RoleManagement.ReadWrite.Directory # Get the Exchange Administrator role $RoleDefinition = Get-MgRoleManagementDirectoryRoleDefinition ` -Filter "DisplayName eq 'Exchange Administrator'" # Assign the role to the managed identity New-MgRoleManagementDirectoryRoleAssignment ` -PrincipalId $PrincipalId ` -RoleDefinitionId $RoleDefinition.Id ` -DirectoryScopeId "/" Write-Host "Exchange Administrator role assigned" -ForegroundColor Green
Step 5: Install Exchange Online Module on Azure Resource
For Azure Automation
- Navigate to Azure Portal > Automation Account > Modules
- Click Browse gallery
- Install modules in this order:
- PackageManagement
- PowerShellGet
- ExchangeOnlineManagement (version 3.0 or later)
PowerShell Alternative
# Install required modules to Automation Account $Modules = @("PackageManagement", "PowerShellGet", "ExchangeOnlineManagement") foreach ($Module in $Modules) { New-AzAutomationModule ` -ResourceGroupName $ResourceGroupName ` -AutomationAccountName $AutomationAccountName ` -Name $Module ` -ContentLink "https://www.powershellgallery.com/api/v2/package/$Module" Write-Host "Installing $Module..." -ForegroundColor Cyan Start-Sleep -Seconds 30 # Wait between installs }
Step 6: Connect Using System-Assigned Managed Identity
In Azure Automation Runbook
# Azure Automation runbook script # Runtime: PowerShell 5.1 Import-Module ExchangeOnlineManagement # Connect using system-assigned managed identity $Organization = "contoso.onmicrosoft.com" try { Write-Output "Connecting to Exchange Online with Managed Identity..." Connect-ExchangeOnline ` -ManagedIdentity ` -Organization $Organization ` -ShowBanner:$false ` -ErrorAction Stop Write-Output "Connected successfully!" # Perform Exchange Online operations $Mailboxes = Get-EXOMailbox -ResultSize 10 Write-Output "Retrieved $($Mailboxes.Count) mailboxes" # Example: Get mailbox statistics foreach ($Mailbox in $Mailboxes) { $Stats = Get-EXOMailboxStatistics -Identity $Mailbox.UserPrincipalName Write-Output "$($Mailbox.DisplayName): $([math]::Round($Stats.TotalItemSize.Value.ToMB(),2)) MB" } } catch { Write-Error "Connection failed: $_" throw } finally { Write-Output "Disconnecting..." Disconnect-ExchangeOnline -Confirm:$false }
In Azure VM
# Script to run on Azure VM with managed identity Import-Module ExchangeOnlineManagement # Connect using the VM's managed identity Connect-ExchangeOnline ` -ManagedIdentity ` -Organization "contoso.onmicrosoft.com" # Run Exchange commands Get-Mailbox -ResultSize 10 # Disconnect Disconnect-ExchangeOnline -Confirm:$false
Step 7: Connect Using User-Assigned Managed Identity
# If using user-assigned managed identity $ManagedIdentityAccountId = "12345678-1234-1234-1234-123456789012" $Organization = "contoso.onmicrosoft.com" Connect-ExchangeOnline ` -ManagedIdentity ` -ManagedIdentityAccountId $ManagedIdentityAccountId ` -Organization $Organization
Complete Azure Automation Example
<# .SYNOPSIS Azure Automation runbook for Exchange Online management .DESCRIPTION This runbook connects to Exchange Online using managed identity and performs scheduled maintenance tasks .NOTES Runtime: PowerShell 5.1 Required Modules: ExchangeOnlineManagement 3.0+ #> param( [Parameter(Mandatory=$true)] [string]$Organization ) # Import module Import-Module ExchangeOnlineManagement # Connect using managed identity try { Write-Output "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Connecting to Exchange Online..." Connect-ExchangeOnline ` -ManagedIdentity ` -Organization $Organization ` -ShowBanner:$false ` -ErrorAction Stop Write-Output "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Connected successfully!" # Example task: Find and report on inactive mailboxes Write-Output "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Checking for inactive mailboxes..." $InactiveDate = (Get-Date).AddDays(-90) $AllMailboxes = Get-EXOMailbox -ResultSize Unlimited -Properties WhenChanged $InactiveMailboxes = $AllMailboxes | Where-Object { $_.WhenChanged -lt $InactiveDate } | Select-Object DisplayName, UserPrincipalName, WhenChanged if ($InactiveMailboxes) { Write-Output "Found $($InactiveMailboxes.Count) inactive mailboxes:" $InactiveMailboxes | ForEach-Object { Write-Output " - $($_.DisplayName) ($($_.UserPrincipalName)) - Last changed: $($_.WhenChanged)" } } else { Write-Output "No inactive mailboxes found" } Write-Output "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Task completed successfully" } catch { Write-Error "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Error occurred: $_" throw } finally { Write-Output "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Disconnecting..." Disconnect-ExchangeOnline -Confirm:$false }
Connection Method 5: Delegated Organization Access (CSP/GDAP)
This method is for Microsoft Partners who need to manage customer Exchange Online environments using Cloud Solution Provider (CSP) or Granular Delegated Admin Privileges (GDAP).
Prerequisites
- Partner admin account with delegated access
- Appropriate GDAP or CSP relationship with customer tenant
Connect to Customer Organization
# Partner admin credentials $PartnerAdmin = "admin@partner.onmicrosoft.com" $CustomerTenant = "customer.onmicrosoft.com" # Connect with delegated access Connect-ExchangeOnline ` -UserPrincipalName $PartnerAdmin ` -DelegatedOrganization $CustomerTenant ` -ShowBanner:$false # Verify connection to customer tenant Get-OrganizationConfig | Select-Object Name, Identity # Perform customer management tasks Get-Mailbox -ResultSize 10 # Disconnect Disconnect-ExchangeOnline -Confirm:$false
Connect to Multiple Customer Tenants
# Define partner admin and customer list $PartnerAdmin = "admin@partner.onmicrosoft.com" $Customers = @( "customer1.onmicrosoft.com", "customer2.onmicrosoft.com", "customer3.onmicrosoft.com" ) # Loop through customers foreach ($Customer in $Customers) { try { Write-Host "Connecting to $Customer..." -ForegroundColor Cyan Connect-ExchangeOnline ` -UserPrincipalName $PartnerAdmin ` -DelegatedOrganization $Customer ` -ShowBanner:$false # Perform tasks for this customer $MailboxCount = (Get-EXOMailbox -ResultSize Unlimited).Count Write-Host "$Customer has $MailboxCount mailboxes" -ForegroundColor Green # Disconnect before moving to next customer Disconnect-ExchangeOnline -Confirm:$false } catch { Write-Warning "Failed to connect to ${Customer}: $_" } }
Verifying and Managing Connections
Check Current Connection Status
# Get information about current Exchange Online connections Get-ConnectionInformation # Output includes: # - ConnectionId # - OrganizationName # - UserPrincipalName (if applicable) # - ConnectionUri # - TokenStatus
Multiple Simultaneous Connections
You can maintain multiple Exchange Online connections simultaneously:
# Connect to primary tenant Connect-ExchangeOnline -UserPrincipalName admin@primary.onmicrosoft.com -Prefix Primary # Connect to secondary tenant (with different prefix) Connect-ExchangeOnline -UserPrincipalName admin@secondary.onmicrosoft.com -Prefix Secondary # Use prefixed cmdlets to target specific tenant Get-PrimaryMailbox -Identity user@primary.com Get-SecondaryMailbox -Identity user@secondary.com # View all connections Get-ConnectionInformation # Disconnect specific connection Disconnect-ExchangeOnline -ConnectionId "connection-guid-here" # Disconnect all connections Get-ConnectionInformation | ForEach-Object { Disconnect-ExchangeOnline -ConnectionId $_.ConnectionId -Confirm:$false }
Disconnect from Exchange Online
# Disconnect with confirmation prompt Disconnect-ExchangeOnline # Disconnect without confirmation Disconnect-ExchangeOnline -Confirm:$false # Disconnect specific connection by ID $ConnectionId = (Get-ConnectionInformation)[0].ConnectionId Disconnect-ExchangeOnline -ConnectionId $ConnectionId -Confirm:$false
Optimized Cmdlets for Better Performance
The Exchange Online PowerShell V3 module includes optimized Get-EXO* cmdlets that use REST API for faster data retrieval. Use these cmdlets for large-scale operations:
Standard vs. Optimized Cmdlets
Standard Cmdlet | Optimized EXO Cmdlet | Performance Benefit |
---|---|---|
Get-Mailbox | Get-EXOMailbox | 5-10x faster for bulk operations |
Get-Recipient | Get-EXORecipient | Optimized for large result sets |
Get-MailboxStatistics | Get-EXOMailboxStatistics | Reduced memory footprint |
Get-CasMailbox | Get-EXOCasMailbox | REST API-based retrieval |
Get-MailboxFolderStatistics | Get-EXOMailboxFolderStatistics | Faster folder enumeration |
Get-MailboxFolderPermission | Get-EXOMailboxFolderPermission | Improved for large mailboxes |
Get-MobileDeviceStatistics | Get-EXOMobileDeviceStatistics | Enhanced mobile device data |
Example: Using Optimized Cmdlets
# Standard cmdlet (slower for large datasets) $Mailboxes = Get-Mailbox -ResultSize Unlimited # Optimized EXO cmdlet (recommended) $Mailboxes = Get-EXOMailbox -ResultSize Unlimited # Using property sets for even better performance $Mailboxes = Get-EXOMailbox -PropertySets All -ResultSize Unlimited # Retrieve specific properties only $Mailboxes = Get-EXOMailbox -Properties DisplayName, UserPrincipalName, ProhibitSendQuota
Troubleshooting Common Issues
Issue 1: Module Import Errors
Problem: “The term ‘Connect-ExchangeOnline’ is not recognized”
Solution:
# Verify module is installed Get-Module -ListAvailable -Name ExchangeOnlineManagement # If not found, install it Install-Module -Name ExchangeOnlineManagement -Force # Import module manually Import-Module ExchangeOnlineManagement -Force
Issue 2: Authentication Failures
Problem: “Authorization_RequestDenied” or “Access Denied” errors
Solution:
# Verify account has Exchange admin rights # Check Azure AD role assignments # Ensure MFA is not blocking automated connections # For app-only: Verify API permissions and admin consent
Issue 3: Certificate Authentication Failures
Problem: “Certificate not found” or “The role assigned to application isn’t supported”
Solution:
# Verify certificate is installed Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "YourThumbprint"} # Verify Exchange Administrator role is assigned to app # Check Exchange.ManageAsApp API permission is granted and consented
Issue 4: Managed Identity Connection Failures
Problem: “UnAuthorized” when using -ManagedIdentity
Solution:
# Verify managed identity is enabled on the resource # Confirm Exchange.ManageAsApp permission is granted # Verify Exchange Administrator role is assigned # Wait 5-10 minutes after role assignment for propagation
Issue 5: Connection Timeout
Problem: Connection hangs or times out
Solution:
# Verify network connectivity Test-NetConnection outlook.office365.com -Port 443 # Check proxy settings if behind corporate firewall # Clear cached tokens [Microsoft.Exchange.Management.ExoPowershellSnapin.ConnectionManager]::DisconnectAllConnections()
Best Practices
Security Best Practices
- Use certificate-based authentication for all automation scenarios
- Enable MFA on all interactive admin accounts
- Apply principle of least privilege – assign only necessary permissions
- Rotate certificates regularly (recommend 1-2 year expiration)
- Store credentials securely using Azure Key Vault or similar solutions
- Never hardcode passwords in scripts or source code
- Use managed identities for Azure resources instead of service principals when possible
- Monitor and audit all Exchange Online PowerShell connections
- Implement conditional access policies for admin accounts
- Regularly review API permissions and role assignments
Performance Best Practices
- Use Get-EXO* cmdlets for large-scale data retrieval operations
- Limit result sets with -ResultSize parameter to avoid memory issues
- Use property sets to retrieve only needed properties
- Disconnect sessions when finished to free resources
- Avoid running Get-Mailbox -ResultSize Unlimited unless absolutely necessary
- Batch operations in automation scenarios to reduce API calls
- Implement error handling with try-catch blocks
- Use -ShowBanner:$false to reduce output in automated scripts
Scripting Best Practices
<# .SYNOPSIS Template for Exchange Online PowerShell scripts .DESCRIPTION Best practice template with error handling and logging #> # Import required module Import-Module ExchangeOnlineManagement -ErrorAction Stop # Define parameters $AppId = "YOUR-APP-ID" $CertificateThumbprint = "YOUR-THUMBPRINT" $Organization = "contoso.onmicrosoft.com" $LogFile = "C:\Logs\ExchangeScript_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" # Function for logging function Write-Log { param([string]$Message) $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $LogMessage = "[$Timestamp] $Message" Write-Output $LogMessage Add-Content -Path $LogFile -Value $LogMessage } try { Write-Log "Script started" # Connect Write-Log "Connecting to Exchange Online..." Connect-ExchangeOnline ` -AppId $AppId ` -CertificateThumbprint $CertificateThumbprint ` -Organization $Organization ` -ShowBanner:$false ` -ErrorAction Stop Write-Log "Connected successfully" # Perform operations Write-Log "Performing Exchange operations..." # Your code here Write-Log "Operations completed successfully" } catch { Write-Log "ERROR: $_" Write-Error $_ exit 1 } finally { # Always disconnect Write-Log "Disconnecting from Exchange Online..." Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue Write-Log "Script completed" }
Prerequisites
Before connecting to Exchange Online PowerShell, ensure the following requirements are met:
System Requirements
- PowerShell Version: Windows PowerShell 5.1 or PowerShell 7.x (or later)
- Operating Systems: Windows, macOS, or Linux
- Network: TCP port 80 open between your computer and Microsoft 365
- Modules: PowerShellGet and PackageManagement modules (required for REST API connections)
Administrative Requirements
- Exchange Online administrator credentials or appropriate RBAC role
- Account must be enabled for PowerShell access
- For MFA scenarios: Multi-factor authentication configured on the account
- For automation scenarios: Azure AD app registration with appropriate permissions
Execution Policy
Set your PowerShell execution policy to allow script execution:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Additional Resources
Microsoft Official Documentation
- Exchange Online PowerShell Module Overview
- Connect to Exchange Online PowerShell
- App-Only Authentication Guide
- Managed Identity Authentication
- Exchange Online PowerShell Module Release Notes
PowerShell Gallery
Community Resources
Version History
Current Module Version: 3.9.0 (as of September 2025)
Key Updates in V3:
- REST API-based cmdlets (no WinRM Basic Authentication required)
- Managed identity support for Azure resources
- Certificate-based authentication improvements
- Enhanced performance with optimized Get-EXO* cmdlets
- Cross-platform support (Windows, macOS, Linux)
- PowerShell 7.x compatibility
Deprecated Features:
- Basic Authentication (permanently disabled October 2022)
- Remote PowerShell (RPS) protocol
- MSOnline V1 module (use Microsoft Graph PowerShell instead)
- New-PSSession method for Exchange Online
Leave a Reply
Want to join the discussion?Feel free to contribute!