Skip to content

Sending Email through Azure Communication Services

The acs transport sends email through Azure Communication Services' own REST API (emails:send), authenticated with an Entra ID (Microsoft's identity platform) client-credentials OAuth2 grant. See SMTP for the alternative path into the same service — Azure Communication Services also offers an SMTP relay, reachable through the SMTP transport's oauth2 authentication mode.

Profile fields

Field Type Required Default Notes
endpoint string yes your resource's endpoint, e.g. https://my-resource.communication.azure.com; a trailing slash is stripped automatically
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
from string yes the sender address, which must be a verified sender on the Azure Communication Services resource
timeout_seconds integer no 30 (capped at 120)

The token is requested with the Azure Communication Services scope for sending email, from the same token cache shared by every Entra-authenticated transport (m365, and the SMTP transport's oauth2 mode); it's keyed on (tenant_id, client_id, scope), so it is only ever reused by another profile requesting that exact combination. 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 unlike the Microsoft 365 transport, both are sent together when both are supplied — see below
attachments no array of {filename, content_type, content_base64}

Unlike the m365 transport, which carries only a single body and picks HTML when both are supplied, the acs transport populates the request's plainText field from body_text and its html field from body_html, sending both when both are present.

What success means

A 202 Accepted response is treated as a successful send, and the operation id parsed from the response body ({"id": "...", "status": "Running"}) becomes the provider reference recorded against the notification. As with Microsoft 365's Graph API, this means Azure Communication Services has accepted the send request for asynchronous processing — it is not proof of delivery. The Processor does not poll for the operation's eventual outcome; if you need to know what happened after acceptance, use the recorded operation id to look the send up in Azure yourself.

Failure classification

A 429 response (throttling) is transient and goes through the normal retry chain, as are 5xx responses and outright network failures. Every other 4xx response — a malformed message, an unverified sender domain, a permission Azure Communication Services has revoked — is a permanent failure, resolved immediately with no retry.


Continue to Sending Email through Gmail.