Getting "Authentication unsuccessful" error when sending email via SMTP using XOAUTH2

Pitawat-MKV 10 Reputation points
2024-01-19T04:40:26.8933333+00:00

I'm writing a simple Python code to send emails on Outlook 365. I'm following this (option 1) and this documentations.

I downloaded this code sample and can obtain access token from Entra ID but got stuck with "Authentication unsuccessful" error when trying to authenticate to Outlook. The code needs to send emails only, no reading.

Here's my code (again, I'm modifying the code from the link above):

import sys  # For simplicity, we'll read config file from 1st CLI param sys.argv[1]
import json
import logging
import smtplib
import requests
import msal
import base64

def encodebase64(access_token):
    userName = "sender@example.com"
    accessToken = access_token
    string = "user=" + userName + "^Aauth=Bearer " + accessToken + "^A^A"
    base64_bytes = base64.b64encode(string.encode())
	return base64_bytes

config = json.load(open(sys.argv[1]))
app = msal.ConfidentialClientApplication(
    config["client_id"], authority=config["authority"],
    client_credential=config["secret"],
	)
result = None
result = app.acquire_token_silent(config["scope"], account=None)

if not result:
    logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
    result = app.acquire_token_for_client(scopes=config["scope"])

if "access_token" in result:
    xoauthstr = encodebase64(result['access_token'])

    smtp_conn = smtplib.SMTP('smtp.office365.com', 587)
    smtp_conn.set_debuglevel(True)
    smtp_conn.ehlo()
    smtp_conn.starttls()
    smtp_conn.ehlo()
    smtp_conn.docmd('AUTH', 'XOAUTH2 ' + xoauthstr.decode())

	msg = header + '\n this is test msg from me \n\n'
	smtp_conn.sendmail('sender@example.com', 'recipient@example.com', msg)
	print("Mail sent!")

When running the code, I use the command python .\sendemail.py .\parameters.json where my parameters.json looks like this:

{  
  "authority": "https://login.microsoftonline.com/<tenant ID>",
  "client_id": "myappid in GUID format from Azure AD",
  "scope": [ "https://outlook.office365.com/.default" ],
  "secret": "client secret"
}

The registered app in Entra ID has these permissions User's image

The access token obtained during code execution contains this field, and the aud field is https://outlook.office365.com User's image

In Exchange admin center, I have already unchecked "Turn off SMTP AUTH protocol for your organization" User's image

And in Microsoft 365 admin center, I have also turned on "Authenticated SMTP" for this mailbox. User's image

This is the output when executing the code User's image

Can anyone point out where I have done wrong? Thanks.

Outlook | Windows | Classic Outlook for Windows | For business
Microsoft 365 and Office | Install, redeem, activate | For business | Windows
0 comments No comments
{count} votes

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.