I’m converting an existing PHPMailer app with Basic (userid and password) Authentication to use OAUTH2. Setup was easy but the app fails on authentication.
2020-05-23 15:14:59 Connection: opening to smtp.office365.com:587, timeout=300, options=array()
2020-05-23 15:14:59 Connection: opened
2020-05-23 15:14:59 SMTP INBOUND: "220 LO2P265CA0358.outlook.office365.com Microsoft ESMTP MAIL Service ready at Sat, 23 May 2020 15:14:58 +0000"
2020-05-23 15:14:59 SERVER -> CLIENT: 220 LO2P265CA0358.outlook.office365.com Microsoft ESMTP MAIL Service ready at Sat, 23 May 2020 15:14:58 +0000
2020-05-23 15:14:59 CLIENT -> SERVER: EHLO [my domain name]
2020-05-23 15:14:59 SMTP INBOUND: "250-LO2P265CA0358.outlook.office365.com Hello [91.208.99.2]"
2020-05-23 15:14:59 SMTP INBOUND: "250-SIZE 157286400"
2020-05-23 15:14:59 SMTP INBOUND: "250-PIPELINING"
2020-05-23 15:14:59 SMTP INBOUND: "250-DSN"
2020-05-23 15:14:59 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2020-05-23 15:14:59 SMTP INBOUND: "250-STARTTLS"
2020-05-23 15:14:59 SMTP INBOUND: "250-8BITMIME"
2020-05-23 15:14:59 SMTP INBOUND: "250-BINARYMIME"
2020-05-23 15:14:59 SMTP INBOUND: "250-CHUNKING"
2020-05-23 15:14:59 SMTP INBOUND: "250 SMTPUTF8"
2020-05-23 15:14:59 SERVER -> CLIENT: 250-LO2P265CA0358.outlook.office365.com Hello [91.208.99.2]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-STARTTLS250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2020-05-23 15:14:59 CLIENT -> SERVER: STARTTLS
2020-05-23 15:14:59 SMTP INBOUND: "220 2.0.0 SMTP server ready"
2020-05-23 15:14:59 SERVER -> CLIENT: 220 2.0.0 SMTP server ready
2020-05-23 15:14:59 CLIENT -> SERVER: EHLO [my domain name]
2020-05-23 15:14:59 SMTP INBOUND: "250-LO2P265CA0358.outlook.office365.com Hello [91.208.99.2]"
2020-05-23 15:14:59 SMTP INBOUND: "250-SIZE 157286400"
2020-05-23 15:14:59 SMTP INBOUND: "250-PIPELINING"
2020-05-23 15:14:59 SMTP INBOUND: "250-DSN"
2020-05-23 15:14:59 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2020-05-23 15:14:59 SMTP INBOUND: "250-AUTH LOGIN XOAUTH2"
2020-05-23 15:14:59 SMTP INBOUND: "250-8BITMIME"
2020-05-23 15:14:59 SMTP INBOUND: "250-BINARYMIME"
2020-05-23 15:14:59 SMTP INBOUND: "250-CHUNKING"
2020-05-23 15:14:59 SMTP INBOUND: "250 SMTPUTF8"
2020-05-23 15:14:59 SERVER -> CLIENT: 250-LO2P265CA0358.outlook.office365.com Hello [91.208.99.2]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-AUTH LOGIN XOAUTH2250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2020-05-23 15:14:59 Auth method requested: XOAUTH2
2020-05-23 15:14:59 Auth methods available on the server: LOGIN,XOAUTH2
2020-05-23 15:14:59 CLIENT -> SERVER: AUTH XOAUTH2 [long string of chars ending in == - base 64 encoded?]
2020-05-23 15:15:04 SMTP INBOUND: "535 5.7.3 Authentication unsuccessful [LO2P265CA0358.GBRP265.PROD.OUTLOOK.COM]"
2020-05-23 15:15:04 SERVER -> CLIENT: 535 5.7.3 Authentication unsuccessful [LO2P265CA0358.GBRP265.PROD.OUTLOOK.COM]
2020-05-23 15:15:04 SMTP ERROR: AUTH command failed: 535 5.7.3 Authentication unsuccessful [LO2P265CA0358.GBRP265.PROD.OUTLOOK.COM]
SMTP Error: Could not authenticate.
2020-05-23 15:15:04 CLIENT -> SERVER: QUIT
My composer.json is just:
"require": {
"phpmailer/phpmailer": "~6.1",
"stevenmaguire/oauth2-microsoft": "2.2.0"
which then also drags in the League oauth2-client and others.
To avoid the issue of OAUTH2 only working for free consumer accounts and not O365 (see Issue 3 - stevenmaguire/oauth2-microsoft on github - and I have replicated the issue to confirm it), I have edited /src/Provider/Microsoft.php as follows:
protected $urlAuthorize = 'https://login.microsoftonline.com/common/oauth2/authorize';
protected $urlAccessToken = 'https://login.microsoftonline.com/common/oauth2/token';
(This uses the Graph V1 endpoint. Note that the latest Graph endpoint V2 is accessed via ... oauth2/v2.0/token and ...oauth2/v2.0/authorize and that either of these uses different Scope parameters that are incompatible with the old 'wl' Windows Live ones)
My relevant PHPMailer code is:
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.office365.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->AuthType = 'XOAUTH2'; // omit this to send using basic authentication
$username = [my email address - as Azure AD signin];
$clientId = [from Azure AD - redacted];
$clientSecret = ‘[from Azure AD - redacted];
$refreshToken = [long char string – from running get_auth_token];
$provider = new Microsoft (
[
'clientId' => $clientId ,
'clientSecret' => $clientSecret
]
);
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'refreshToken' => $refreshToken’,
'userName' =>$username
]
)
);
//$mail->Username = blah; // SMTP username – not needed for OAUTH2
//$mail->Password = blah; // SMTP password – not needed for OAUTH2
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587;
$mail->SMTPDebug = SMTP::DEBUG_LOWLEVEL;
My get_oauth_token.php contains:
$clientId = [my client ID];
$clientSecret = [my client secret]';
$redirectUri = [the full URI of get_oauth_token.php];
I have created an app in MSFT Azure AD of type ‘Web app’, taken the client ID and client secret from there, and added API permissions for SMTP.Send, Mail.Send, offline_access, and openid
If I can find where in the code the Azure AD authentication codes and messages (vide https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes#lookup-current-error-code-information) are returned, I'll be a step forward! I have tried the AD Monitor for sign-ins, but these particular unsuccessful attempts are not logged - nor the successful getting of the refresh token.