Why the old tutorials stopped working
The classic recipe, smtplib against smtp.office365.com with a username and password, died when Microsoft switched 365 tenants off basic authentication. The replacement is OAuth 2.0 token flows against Microsoft Graph or SMTP with modern auth: app registrations, client secrets, tenant IDs, token refresh.
That is a lot of Azure ceremony to send a notification.
Scope ceremony also fails in ways that look like bad credentials. George, our CEO, debugged exactly this in our own provider integration: a connection test probed an endpoint that needs SendGrid's Sender Authentication scope, so a valid least-privilege Mail-Send key returned 403 and was reported invalid. The fix was probing an endpoint any valid key can read. When an OAuth or API-key setup rejects a key you know is right, check what the probe endpoint demands before you rotate anything.
Let your code stop caring about Microsoft's auth
The email API path removes the moving part: your Python authenticates to one stable endpoint with a bearer token, and the platform's infrastructure handles delivery to Outlook, Gmail, and everyone else.
requests.post( "https://api.nitrosend.com/v1/my/messages", headers={"Authorization": "Bearer $NITROSEND_API_KEY"}, json={"from": "[email protected]", "to": "[email protected]", "subject": "Your report", "html": "<p>Attached below.</p>"}, )
The bearer token is a server-side API key. It lives in the environment where the script runs, never in anything you distribute.
That platform infrastructure is strict by design. On our forwarding relay, TCP 2525 is firewall-restricted to our API host, TLS and exact SMTP authentication are mandatory, and every single-recipient route and MX snapshot is HMAC-signed, with unsigned or replayed requests rejected. Microsoft's filters reward exactly that discipline.
Reaching Outlook inboxes then becomes a deliverability question, SPF, DKIM, DMARC on your domain, which the platform configures for you.
And it's worth respecting the scale of the gatekeepers. Apple, Alphabet, and Microsoft now control 77 percent of the world's inbox market between them. You don't out-clever three trillion-dollar filters. You authenticate properly and send mail people want.
Outlook's own rules are concrete: past 5,000 emails a day, Microsoft requires SPF, DKIM, and DMARC aligned, with a DMARC policy of p=quarantine or stronger. Switching providers also buys you a short adjustment window while Outlook and Gmail get used to your mail arriving from a new place, so judge deliverability after the warm-up, not on day one. One more count worth knowing: for all of Outlook's enterprise presence, Microsoft 365 mailboxes are only around 5 percent of where senders' audiences actually live. Gmail dominates. Weight your testing accordingly.
Full parameters and responses live in the REST API docs and the API reference.
Go deeper
Gmail version of the same trap: Python via Gmail. The full language guide: send email with Python. Outlook applies its own filtering, so SPF, DKIM and DMARC authentication matters here, and inbox placement is how you tell whether it worked.