Primer: Using Exchange Online PowerShell in Azure Automation Runbooks
Exchange Online PowerShell Assumes Administrators Run Its Cmdlets
My last primer article in the Azure Automation series covered how to send email using the Exchange Online High-Volume Email (HVE) facility. HVE is still in preview (Microsoft is targeting September 2025 for general availability) but it still does a nice job of sending email from scheduled automation jobs.
This article discusses how to create and execute Azure Automation Exchange runbooks using PowerShell cmdlets from the Exchange Online management module. Unlike HVE, which doesn’t require any Exchange cmdlets, Automation accounts that use the Exchange module in their jobs need some special configuration. This is because the Exchange module assumes that anyone running its cmdlets is an Exchange administrator. There’s no concept of least privilege implemented in the module: once a process loads the module, it can act like a human administrator.
Loading Exchange Online PowerShell into an Automation Account
At least, an app can be all-powerful for Exchange if it meets three conditions. First, it can load the Exchange Online management module. For Azure automation accounts, this means that module is loaded as a resource into the account (Figure 1).

At the time of writing, Exchange Online PowerShell only supports PowerShell V5.1 for automation runbooks, so be sure to install that version of the module. Due to module dependencies, you must install the PackageManagement and PowerShellGet modules (loaded jn that order) before installing the Exchange Online module.
Assigning Exchange Online Permissions and Roles for the Automation Account
Second, the service principal for the app must be assigned the Exchange administrator RBAC role. For Azure Automation, this means the service principal for the automation account. The assignment can be done through the Entra admin center (Figure 2) or with PowerShell. Make sure that you select the correct automation account from the set of enterprise applications listed in the picker.

Third, the app must be assigned the Exchange.ManageAsApp permission. This is not a Microsoft Graph permission. It is an Office 365 Exchange Online permission designed to allow apps to act as administrators. The assignment can only be made through PowerShell. Here’s how to do the job with the Microsoft Graph PowerShell SDK:
$ExoApp = Get-MgServicePrincipal -Filter "AppId eq '00000002-0000-0ff1-ce00-000000000000'" $TargetSP = Get-MgServicePrincipal -filter "displayname eq 'M365Automation'" $Role = $ExoApp.AppRoles | Where-Object {$_.DisplayName -eq "Manage Exchange As Application"} $AppRoleAssignment = @{} $AppRoleAssignment.Add("PrincipalId",$TargetSP.Id) $AppRoleAssignment.Add("ResourceId",$ExoApp.Id) $AppRoleAssignment.Add("AppRoleId",$Role.Id) $RoleAssignment = New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $TargetSP.Id -BodyParameter $AppRoleAssignment If ($RoleAssignment.AppRoleId) { Write-Host ("{0} permission granted to {1}" -f $Role.Value, $TargetSP.DisplayName) }
Creating a Runbook to use Exchange Online Cmdlets
With the three prerequisites in place, you can create a runbook. To test that everything works as expected, create a V5.1 PowerShell runbook with the following code (replace the organization name with your tenant):
Connect-ExchangeOnline -ManagedIdentity -Organization Office365itpros.com (Get-OrganizationConfig).DisplayName
Save the runbook and use the test pane to execute it. The output should be the display name for your organization. If that’s all you see, you can go ahead and build out the runbook with code to do more useful work.
As a demonstration, I took the script to report missing properties for user mailboxes and copied it into the runbook. The only changes that I made were:
- Remove the code that checks for an active connection to Exchange Online at the start of the script and replace it with the Connect-ExchangeOnline -ManagedIdentity command.
- Remove the Clear-Host cmdlet (Azure Automation doesn’t have a host to clear).
- Replace the Write-Host cmdlet with Write-Output (Azure Automation outputs everything together (a stream) at the end of a job).
- Remove the code to output the results as an CSV file at the end of the script.
Figure 3 shows the output of the runbook in the test pane. Everything works and we know that there are some mailboxes with missing properties that should be addressed.

Azure Automation can create an output file on the headless server where the runbook executes, but the question is then how to copy the file to somewhere more accessible later. The easy answer is to use HVE to send the file as an email attachment or to include the data in the body of a message. Something more complicated, like creating a file in a SharePoint Online site, will require more effort.
Not So Difficult
Running Exchange Online scripts in Azure Automation isn’t difficult once the initial setup for the automation account is in place. Some tweaking of the script code is probably necessary, but it’s not difficult to make the changes and will become second nature after a while. If you need to run jobs that process large numbers of Exchange objects (like mailboxes), Azure Automation is an excellent platform choice.
Need some assistance to write and manage PowerShell scripts for Microsoft 365? Get a copy of the Automating Microsoft 365 with PowerShell eBook, available standalone or as part of the Office 365 for IT Pros eBook bundle.