Sending Email through Microsoft 365¶
The m365 transport sends email through the Microsoft Graph API's sendMail action, authenticated with an Entra ID (Microsoft's identity platform) client-credentials OAuth2 grant. It's the transport to reach Microsoft 365 or Exchange Online without speaking SMTP at all — see SMTP if you would rather use Exchange Online's own SMTP AUTH OAuth2 replacement instead.
Profile fields¶
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
tenant_id |
string | yes | — | the Entra tenant id |
client_id |
string | yes | — | the Entra app registration's client id |
client_secret |
string | yes | — | use _env:VAR_NAME — see Keeping Secrets Out of the Database |
sender |
string | yes | — | the mailbox to send from, as a user principal name or object id |
save_to_sent_items |
boolean | no | false |
whether Graph saves a copy to the sender's Sent Items folder |
timeout_seconds |
integer | no | 30 (capped at 120) |
The token is requested with Graph's fixed .default scope for sendMail and cached until shortly before it expires; a cached token that gets rejected (an HTTP 401) triggers exactly one automatic refresh and retry before the send is given up on.
Message fields¶
| Field | Required | Notes |
|---|---|---|
to |
at least one address | |
cc |
no | |
bcc |
no | |
reply_to |
no | |
subject |
no | |
body_text / body_html |
at least one | Graph carries only a single body — see below |
attachments |
no | array of {filename, content_type, content_base64}; Graph limits an inline attachment to roughly 3 MB |
Unlike the SMTP transport, Graph's message shape has room for only one body. If you supply both body_text and body_html, body_html wins — the plain-text version is simply not sent.
What success means¶
A 202 Accepted response from Graph is treated as success, and the request's request-id response header becomes the provider reference recorded against the notification. This means Graph has accepted the send request — it is not proof that the message reached, or will reach, the recipient's inbox. Graph's own delivery, filtering, and mailbox rules all still apply after this point, exactly as they would for any other message sent through Microsoft 365.
Failure classification¶
Graph's 429 (throttling — you're sending too fast) is transient and goes through the normal retry chain, as are 5xx responses and outright network failures. Every other 4xx response — a malformed message, a sender Graph doesn't recognise, a permission Graph has revoked — is a permanent failure, resolved immediately with no retry.
Continue to Sending Email through Azure Communication Services.