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.
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>"}, )
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.