Skip to main content

About Exchange Online

Exchange Online is Microsoft’s cloud email and calendaring service, part of Microsoft 365. The Serval integration runs Exchange Online PowerShell on an isolated Serval worker, which makes it the only way to automate things the Microsoft Graph API can’t write - including distribution groups, mail-enabled security groups, and dynamic distribution groups. It is a separate integration from Microsoft Graph (Microsoft 365): connecting one does not grant the other, so teams using both need both connected. Serval signs in through Microsoft’s identity service at login.microsoftonline.com and connects to Exchange Online at outlook.office365.com. Authentication: Microsoft Entra ID (Azure AD) app registration, using either a Client Secret (simpler to set up) or a Certificate (PEM) (more secure - no bearer tokens). Data sync: On-demand only. There is no background sync, entity ingestion, or scheduled polling - each action opens a fresh Exchange Online session on the Serval worker, runs, and disconnects.

What the Exchange Online integration enables

Anything Exchange Online PowerShell can do can be run through the Invoke Exchange Online Command action.

Get your credentials

You’ll create an Entra ID (Azure AD) app registration, grant it the Exchange Online admin permission, and - critically - register it inside Exchange Online itself with a short PowerShell script that Serval generates for you after you save the connection. Microsoft’s official guide is App-only authentication for Exchange Online PowerShell.
1

Create the app registration

In the Azure Portal, go to Azure Active Directory → App registrations → New registration. Choose Accounts in this organizational directory only, leave the Redirect URI blank, and register. From the app’s Overview page, copy the Application (client) ID and the Directory (tenant) ID - you’ll paste both into Serval.
2

Grant the Exchange Online permission

In the app registration, go to API permissions → Add a permission → APIs my organization uses → Office 365 Exchange Online → Application permissions, select Exchange.ManageAsApp, click Add, then click Grant admin consent.
3

Create your credential (choose one method)

In the app registration, go to Certificates & secrets → New client secret. Copy the secret value immediately - Microsoft shows it only once.
4

Note your tenant domain

Find your Microsoft 365 tenant domain under Azure AD → Overview → Primary domain - it typically ends in .onmicrosoft.com (for example, contoso.onmicrosoft.com). This goes in Serval’s Organization field.
5

Find the Enterprise App Object ID

In the Microsoft Entra admin center, go to Enterprise Applications (not App registrations), open your app, and copy its Object ID. Serval’s setup script asks for this value - the field is labeled Enterprise App Object ID, “Found in Entra admin center → Enterprise Applications (not App registrations) → your app → Object ID”.
Granting admin consent in Entra is not enough by itself. The app must also be registered inside Exchange Online with a management role assignment, or every command will fail even though authentication succeeds. After you save the connection, Serval provides an “Exchange Online PowerShell Setup” script that does this for you - see “Connect in Serval” below.

Connect in Serval

1

Open the Exchange Online connect form

In Serval, open the Exchange Online integration and start a new connection. Required fields are marked with an asterisk - if you leave one blank, the form flags it with “This field is required”.
2

Enter your app details

  • App (Client) ID (required) - “The Application (Client) ID of your Azure AD app registration”.
  • Tenant (Directory) ID (required) - “The Directory (Tenant) ID from your Azure AD app registration”.
  • Organization (required) - “Your Microsoft 365 tenant domain (e.g. contoso.onmicrosoft.com)”. Serval trims whitespace and lowercases this value automatically.
3

Choose an Authentication Method

Select Client Secret (the default) or Certificate (PEM). As the form notes: “Client Secret is simpler to set up. Certificate is more secure (no bearer tokens).” Only the field for the method you select is shown.
  • Client Secret - “A client secret from your Azure AD app registration (Certificates & secrets)”. Saving without it fails with an error that includes “Client Secret is required”.
  • Certificate (PEM) - “PEM-encoded certificate and private key. Paste the combined contents of your cert and key files.” Saving without it fails with an error that includes “Certificate (PEM) is required”, and pasting only the certificate (or only the key) fails with an error that includes “Invalid certificate PEM”.
4

Name the connection (optional)

Instance Name (Optional) - “A friendly name to identify this Exchange Online connection”. If left blank, the connection is named after your Organization value.
5

Save, then run the setup script

After saving, open the connection’s settings page and expand the Exchange Online PowerShell Setup section: “After saving your configuration above, run this script in PowerShell to register the service principal in Exchange Online.” Enter your Enterprise App Object ID and copy the script. Run it in PowerShell as an Exchange admin - it installs the Exchange Online PowerShell module if needed, registers your app’s service principal in Exchange Online, assigns it the “Application Exchange Full Access” management role, and disconnects. Commands will fail until this script has run.
Editing the connection later: any field you leave blank keeps its saved value, including the secret fields. To rotate a Client Secret or Certificate, paste the complete new value; to keep the current one, leave the field blank. Never re-submit the masked value (bullets) you see when viewing the connection - through the Serval web form this is handled for you, but an API client that resubmits the masked secret will overwrite the real one and break authentication until it’s re-entered.

Verifying the connection

Serval runs three health checks against your tenant: If a check connects but gets no data back, you’ll see messages like “Connected to Exchange Online but received no data from Get-OrganizationConfig. The account may lack sufficient permissions.” For distribution groups specifically, the failure message also allows for the benign case: “Connected to Exchange Online but received no distribution group data. The account may lack sufficient permissions or there are no distribution groups.”
If these checks are green but your user, calendar, or Teams workflows still fail, you’re probably hitting the Microsoft 365 (Graph) integration - that’s a separate connection. Exchange Online being healthy says nothing about Graph, and vice versa; connect both if you use both.

Gotchas and troubleshooting

This is the classic symptom of skipping the post-save setup script. Entra admin consent alone lets the app sign in, but Exchange Online won’t accept its commands until the app’s service principal is registered inside Exchange Online and assigned the “Application Exchange Full Access” management role - exactly what the “Exchange Online PowerShell Setup” script does. Make sure you used the Enterprise Application Object ID, not the App registration’s Object ID. Also confirm the Exchange.ManageAsApp permission has admin consent granted - when access is denied, the health check advises: “Ensure the Azure AD app has the required admin consent and Exchange Online permissions (Exchange.ManageAsApp).” Microsoft can take a little while to apply new permissions and role assignments, so a just-fixed connection may keep failing briefly before it starts working.
Connecting Microsoft 365 (Graph) does not give you Exchange Online, and connecting Exchange Online does not give you Graph. They are different apps with different credentials - a team using both needs both connected, even though both use Entra app registrations.
Distribution groups, mail-enabled security groups, and dynamic distribution groups are read-only in Microsoft Graph - writes only work through Exchange Online. Plain distribution groups have dedicated Serval actions; mail-enabled security groups and dynamic distribution groups require the Invoke Exchange Online Command action.
Serval requires the certificate and the private key combined in a single paste - the text must contain both a certificate block and a private key block. Upload only the certificate file to Entra, but paste the combined certificate-plus-key file into Serval.
Changing the Authentication Method on an existing connection requires the new credential in the same save - otherwise the save fails with an error that includes “Client Secret is required when switching to client secret authentication” or “Certificate (PEM) is required when switching to certificate authentication”. Switching wipes the previously stored secrets, and even within the same method, saving a new client secret clears any stored certificate (and vice versa).
Every action runs in a fresh session - Serval connects to Exchange Online at the start and disconnects at the end, with a default timeout of 120 seconds. Scripts that exceed the timeout are forcibly stopped and surface as an error. For long operations (large-tenant listings, bulk updates), raise the timeout setting on the Invoke Exchange Online Command action - the dedicated actions don’t expose a timeout control.
The Exchange Online module writes formatting escape codes straight to the console, so raw output text can look corrupted. Read your results from the action’s structured JSON result (the last value your script returns is serialized automatically; it’s null if the script returns nothing), not from the console output. Errors are treated strictly - any failing command stops the script.
Exchange Online is action-only: there are no installable workflow templates, no synced entities, and no background data ingestion. Everything happens on demand when a workflow runs an Exchange Online action or a health check fires.

Need help? Contact support@serval.com for assistance with your Exchange Online integration.