Custom software, scripts, monitoring, backup jobs

Pick a route

  1. Microsoft Graph sendMail with OAuth (best fit if you can change the code). POST https://graph.microsoft.com/v1.0/users/{id|userPrincipalName}/sendMail, Mail.Send (delegated or application). Returns 202 Accepted: "doesn't indicate that the request processing has completed." Saves to Sent Items unless saveToSentItems is false. [V: https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0]
  2. SMTP with XOAUTH2 (if the app can speak it). Microsoft documents both user flows (authorization code, device code) and the client-credentials flow for SMTP. [V: https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth]
  3. HVE if every recipient is internal [V: HVE page].
  4. SMTP relay connector if the app runs on-prem with a static IP and cannot do OAuth; not for third-party-hosted apps [V: device-setup page].
  5. Third-party sending service if hosted elsewhere and sending to customers.

Client-credentials SMTP, as Microsoft documents it [V]

  1. Register an app in Microsoft Entra. API permissions > APIs my organization uses > "Office 365 Exchange Online" > Application permissions > SMTP.SendAsApp. Grant admin consent.
  2. In Exchange Online PowerShell: New-ServicePrincipal -AppId <APP_ID> -ObjectId <ENTERPRISE_APP_OBJECT_ID>. Microsoft stresses the Object ID must be the one from the Enterprise application, not the App registration; wrong ID causes authentication failure.
  3. Allow the app to use a mailbox: Add-MailboxPermission -Identity "john.smith@contoso.com" -User <SERVICE_PRINCIPAL_ID> -AccessRights FullAccess. Note what this grants: FullAccess to that mailbox. Use a dedicated mailbox.
  4. Token request scope must be https://outlook.office365.com/.default. Use the token with SASL XOAUTH2: AUTH XOAUTH2 base64("user=" + user + "^Aauth=Bearer " + token + "^A^A").
  5. If sending as a different address, grant Send As (Add-RecipientPermission).
  6. Make sure SMTP AUTH is enabled for that mailbox (mailbox setting overrides the org setting) [V: Enable or disable SMTP AUTH page].

Hardening note [G]

Application permissions such as Graph Mail.Send can be broader than one mailbox unless you restrict them. Microsoft mentions Application Access Policies (legacy) and "Role Based Access Control for Applications in Exchange Online" as the enforcement mechanisms in its HVE OAuth page [V that the sentence exists: https://learn.microsoft.com/en-us/exchange/mail-flow-best-practices/oauth-high-volume-mails-m365]; we did not read those pages. Restrict before production.

Don't