Skip to main content

Transactional email (Microsoft Graph)

Django's EMAIL_BACKEND is EMAW.backends.graph_email.GraphEmailBackend: it authenticates with MSAL (client credentials) and sends through the Microsoft Graph API as a Microsoft 365 mailbox. There is no SMTP anywhere.

CodeEMAW/backends/graph_email.py
EnvMS_TENANT_ID, MS_CLIENT_ID, MS_CLIENT_SECRET, MS_SENDER_UPN (the mailbox, DEFAULT_FROM_EMAIL falls back to support@emaw-app.com), CONTACT_FORM_RECIPIENTS, STORE_ORDER_NOTIFY_RECIPIENTS, EVENTS_NOTIFY_RECIPIENTS, DONATIONS_NOTIFY_RECIPIENTS
Testmanage.py test_graph_email

What goes through it​

EmailSent from
Sign-up verification code, resend, change-email codeEMAW/views/auth.py
Password reset codeEMAW/views/auth.py
Website contact formrest/contact/ → CONTACT_FORM_RECIPIENTS
Store order confirmation, shipped notice, staff order notificationstore/tasks.py
Event registration confirmation (buyer and guests), leader emails, overbooked staff alertevents/tasks.py
Donation receipt, staff notification, failed-payment and cancelled-recurring noticesdonations/tasks.py
Deposco problem notificationsdeposco/tasks.py

Marketing campaigns do not use Graph; see Marketing email (ACS).

Entra app registration​

A single app registration in the everymanawarrior.com tenant with the application permission Mail.Send, restricted (by an Exchange application access policy) to the sender mailbox. The client secret expires; when verification emails stop arriving, check its expiry first. Rotate by creating a new secret in Entra and updating MS_CLIENT_SECRET in both environments' .env.

Test settings​

EMAW_BACKEND.settings.test swaps in the locmem email backend, so tests assert on django.core.mail.outbox.