I'm using PHPMailer to authenticate via XOAUTH2 with smtp.gmail.com in order to send an email. However, I'm getting an authentication error with an inadequate response:
2023-11-17 06:32:29 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [2402:b280:a1f:ba65:ce96:e5ff:feee:f13e]250-SIZE 35882577250-8BITMIME250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2023-11-17 06:32:29 CLIENT -> SERVER: AUTH XOAUTH2 dXNlcj1tdXJyYXlAZm9jdXMtY29tcHV0aW5nLmNvbS5hdQFhdXRoPUJlYXJlciB5YTI5LmEwQWZCX2J5QXAxU2twbzdJSXBGTVJLWVNPYlZqWXZMaVBCZkVXLUUweEtwOUVmUTNHTWhnV3d5UDUwM09VdGY2NVZkeW0xcHNsd05lR0JLZElwNUI4eFFISjJZdC00U1o5amQxWGtIUjBVZ0tMN29wZWt5NlJzZFFfcHRVSmU4RGU2X0dYbS1xN2lmcVFzV1VIRTI2ZHl5OUhKNWxudE1NQ2kybkhpd2FDZlEzeFY2Q1hLcmpMU0VXbnRKUEEwMTczAQE=
2023-11-17 06:32:30 SERVER -> CLIENT: 334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczov9vZ2xlLmNvbS8ifQ==
2023-11-17 06:32:30 SMTP ERROR: AUTH command failed: 334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvovL21haWwuZ29vZ2xlLmNvbS8ifQ==
SMTP Error: Could not authenticate.
2023-11-17 06:32:30 CLIENT -> SERVER: QUIT
2023-11-17 06:32:30 SERVER -> CLIENT: 535-5.7.8 Username and Password not accepted. Learn more at535 5.7.8 https://support.google.com/mail/?p=BadCredentials k6-20020a17090a404600b00277371fd346sm2482723pjg.30 - gsmtp
2023-11-17 06:32:30 SMTP ERROR: QUIT command failed: 535-5.7.8 Username and Password not accepted. Learn more at535 5.7.8 https://support.google.com/mail/?p=BadCredentials k6-20020a17090a404600b00277371fd346sm2482723pjg.30 - gsmtp
SMTP Error: Could not authenticate.
When using XOAUTH2 I'm sending a username and an access token, not a password. So why are these messages indicating in valid username and password credentials. The username and access token are correct, so these responses are really unhelpful.
Can we please get some better messages or some helpful information from Gmail about why this isn't authenticating?
Section of the code I am using:
$mailer = new PHPMailer(true);
$mailer->SMTPDebug = SMTP::DEBUG_SERVER;
$mailer->isSMTP();
$mailer->Host = ini_get("SMTP");
$mailer->Port = ini_get("smtp_port");
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mailer->SMTPAuth = true;
$mailer->Username = null;
$mailer->Password = null;
$mailer->AuthType = $smtp["authtype"]; // "XOAUTH2"
$oauth = new MyOAuthTokenProvider();
$oauth->setEmail($smtp["username"]);
$oauth->setAccessToken($smtp["accessToken"]);
$mailer->setOAuth($oauth);
$mailer->SMTPKeepAlive = true;
$mailer->From = $headers["From"];
$mailer->addReplyTo($headers["From"]);
$mailer->addAddress($recipient);
$mailer->isHTML(true);
$mailer->Subject = $headers["Subject"];
$mailer->Body = $body;
$mailer->send();
class MyOAuthTokenProvider implements OAuthTokenProvider {
protected $email;
protected $accessToken;
public function setEmail($value) {
$this->email = $value;
}
public function setAccessToken($value) {
$this->accessToken = $value;
}
/**
* @see \PHPMailer\PHPMailer\OAuth::getOauth64()
*/
public function getOauth64(): string
{
return base64_encode(
'user=' .
$this->email .
"\001auth=Bearer " .
$this->accessToken .
"\001\001"
);
}
}
EDIT: Linda was really helpful sharing her code, however this only works where the security scope allows access to all your Gmail mailboxes and for sending email. The limited scopes simply don't work, none of them. This is a major issue for us as it breaches the ISO27001 standard we are wanting to meet, which requires that access to data should only be required for the functions necessary.
This now remains an issue firmly with Google/Gmail that they need to fix their security scopes.
This is my sample for SMTP XOauth2 with PHP.
It requires that you have a client id and client secret for an installed app created on Google cloud console with gmail enabled.
You also need a refresh token. This code doesn't create the initial refresh token. I recommend using either oauth2 playground or something like the php client library to create that.
debug