Set up Microsoft Graph as Email Provider

Self-hosted

Configure Entropy Data to send outbound emails (invitations, notifications, access request updates) through the Microsoft Graph API instead of SMTP.

Overview

By default, Entropy Data sends email via SMTP using Spring Mail. For self-hosted and enterprise customers on Microsoft 365 tenants where SMTP AUTH is disabled (the Microsoft-recommended default since 2020), SMTP is not available. The Microsoft Graph mail provider uses OAuth 2.0 client credentials to call POST /users/{from}/sendMail, so no SMTP is involved.

Customers choose between the two providers with a single property:

  • application.mail.provider=smtp (default)
  • application.mail.provider=graph

Prerequisites

  • A Microsoft 365 / Entra ID tenant with permission to register applications and grant admin consent.
  • An Exchange Online user mailbox to send from (not a distribution list, not a shared mailbox without a license, not a room resource).
  • Permission to run Exchange Online PowerShell, if you want to restrict the app to a single mailbox (strongly recommended).

Step 1: Register an Application in Entra ID

  1. Go to Entra admin center -> App registrations -> New registration.
  2. Set the Name (for example, Entropy Data Mail Sender).
  3. Choose Accounts in this organizational directory only (single-tenant).
  4. Leave the Redirect URI empty. This app uses the client credentials flow, so no redirect URI is needed.
  5. Click Register.

From the Overview page, note down:

  • Application (client) ID
  • Directory (tenant) ID

Create a Client Secret

  1. Go to Certificates & secrets -> Client secrets -> New client secret.
  2. Add a description and choose an expiration.
  3. Copy the Value immediately. This is the secret you will use in the application configuration.

Add Microsoft Graph API Permission

  1. Go to API permissions -> Add a permission -> Microsoft Graph.
  2. Choose Application permissions (not Delegated permissions).
  3. Search for Mail.Send, tick it, and click Add permissions.
  4. Back on the API permissions page, click Grant admin consent for <tenant> and confirm.

Important: The Grant admin consent step is mandatory. Without it, the access token Entropy Data receives has no roles claim, and every call to Graph returns 403 Access is denied. If you miss this step on the initial setup, it is the single most common cause of failures.

(Strongly recommended) Restrict the App to a Single Mailbox

By default, an app with Mail.Send application permission can send as any mailbox in the tenant. Use an Exchange Online Application Access Policy to scope the app down to the sender mailbox only.

Run this in Exchange Online PowerShell:

New-ApplicationAccessPolicy `
  -AppId <client-id> `
  -PolicyScopeGroupId <sender-mailbox> `
  -AccessRight RestrictAccess `
  -Description "Restrict to sender mailbox"

Test-ApplicationAccessPolicy `
  -Identity <sender-mailbox> `
  -AppId <client-id>

The Test-ApplicationAccessPolicy call should return AccessCheckResult: Granted for the sender mailbox, and Denied for any other mailbox in the tenant.

Step 2: Configure Entropy Data

Set the following environment variables on the Entropy Data deployment:

Environment VariableDescription
APPLICATION_MAIL_PROVIDERSet to graph to enable the Microsoft Graph provider. Default is smtp.
APPLICATION_MAIL_GRAPH_TENANT_IDDirectory (tenant) ID from the Entra app registration Overview page.
APPLICATION_MAIL_GRAPH_CLIENT_IDApplication (client) ID from the Entra app registration Overview page.
APPLICATION_MAIL_GRAPH_CLIENT_SECRETThe Value of the client secret (not the Secret ID).
APPLICATION_MAIL_GRAPH_SAVE_TO_SENT_ITEMSOptional. true to keep a copy in the sender's Sent Items folder. Defaults to false.
APPLICATION_MAIL_FROMThe sender mailbox. Must be a real Exchange Online user mailbox in the tenant.

Important: APPLICATION_MAIL_FROM must match the mailbox the app is permitted to send as. If you created an Application Access Policy in Step 1, this must be that mailbox.

When APPLICATION_MAIL_PROVIDER=graph, the SPRING_MAIL_* variables are ignored and can be removed from your deployment configuration.

Troubleshooting

Access is denied. Check credentials and try again. on sendMail

Almost always a permissions problem. The common causes:

  • Mail.Send was added under Delegated permissions instead of Application permissions.
  • Admin consent was never clicked after adding the permission.
  • The application access policy denies the sender mailbox (run Test-ApplicationAccessPolicy to confirm).

Verify the access token carries the expected role. Request a token and decode the payload:

TOKEN=$(curl -s -X POST \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "client_secret=$CLIENT_SECRET" \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'scope=https://graph.microsoft.com/.default' \
  "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" | jq -r .access_token)

echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq '{roles, appid, aud, tid}'

The roles claim must contain "Mail.Send". If roles is null, the permission is either delegated or has no admin consent. Fix the app registration and retry.

AADSTS7000215: Invalid client secret

You copied the Secret ID instead of the Value. Go back to Certificates & secrets, create a new secret, and copy the Value column before navigating away. The Value is only shown once.

MailboxNotEnabledForRESTAPI

The address in application.mail.from is not a real Exchange Online mailbox. Common causes:

  • The address is a distribution list or shared mailbox without an Exchange Online license.
  • The address is a room or equipment resource mailbox.
  • The user exists in Entra ID but has no Exchange Online mailbox provisioned.

Pick a licensed user mailbox in the tenant and update application.mail.from accordingly.

Changes seem to have no effect

Application permission and admin consent changes can take 1 to 2 minutes to propagate through Entra. Wait, request a fresh token with the curl snippet above, and check the roles claim again.

Switching Back to SMTP

Set application.mail.provider=smtp (or remove the property, since smtp is the default) and restore the standard SPRING_MAIL_* variables. No data migration is required. The two providers are fully interchangeable at runtime.

Reference