尝试通过 XOAUTH2 使用 smtp.gmail.com 进行身份验证

问题描述 投票:0回答:1

我正在使用 PHPMailer 通过 XOAUTH2 与 smtp.gmail.com 进行身份验证,以便发送电子邮件。但是,我收到身份验证错误且响应不充分:

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.

使用 XOAUTH2 时,我发送用户名和访问令牌,而不是密码。那么为什么这些消息显示有效的用户名和密码凭据。用户名和访问令牌是正确的,因此这些响应确实没有帮助。

我们能否从 Gmail 获取一些更好的消息或一些有用的信息来了解为什么此验证失败?

我正在使用的代码部分:

$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"
        );
    }
}
php phpmailer gmail-api actions-on-google smtp-auth
1个回答
0
投票

这是我使用 PHP 进行 SMTP XOauth2 的示例。

它要求您拥有在启用了 Gmail 的 Google 云控制台上创建的已安装应用程序的客户端 ID 和客户端密钥。

您还需要一个刷新令牌。此代码不会创建初始刷新令牌。 我建议使用 oauth2 Playground 或类似 php 客户端库的东西来创建它。

//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\OAuth;
//Alias the League Google OAuth2 provider class
// composer require league/oauth2-google
use League\OAuth2\Client\Provider\Google;


try{
    $client = getClient();
    print_r($client->getClientId());
    print_r($client->getClientSecret());
    print_r($client->getRefreshToken());

    //Use league/oauth2-client as OAuth2 token provider
    //                Fill in authentication details here
    //                Either the gmail account owner, or the user that gave consent
    $email = EMAIL_FROM;
    $clientId = $client->getClientId();
    $clientSecret = $client->getClientSecret();
    $refreshToken = $client->getRefreshToken();
    $send_to = EMAIL_TO;

    //Create a new PHPMailer instance
    $mail = new PHPMailer();

    //Tell PHPMailer to use SMTP
    $mail->isSMTP();

    //Enable SMTP debugging
    //SMTP::DEBUG_OFF = off (for production use)
    //SMTP::DEBUG_CLIENT = client messages
    //SMTP::DEBUG_SERVER = client and server messages
    $mail->SMTPDebug = SMTP::DEBUG_SERVER;

    //Set the hostname of the mail server
    $mail->Host = 'smtp.gmail.com';

    //Set the SMTP port number:
    // - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
    // - 587 for SMTP+STARTTLS
    $mail->Port = 465;

    //Set the encryption mechanism to use:
    // - SMTPS (implicit TLS on port 465) or
    // - STARTTLS (explicit TLS on port 587)
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;

    //Whether to use SMTP authentication
    $mail->SMTPAuth = true;

    //Set AuthType to use XOAUTH2
    $mail->AuthType = 'XOAUTH2';

    //Obtained by configuring and running get_oauth_token.php
    //after setting up an app in Google Developer Console.

    //Create a new OAuth2 provider instance
    $provider = new Google(
        [
            'clientId' => $clientId,
            'clientSecret' => $clientSecret,
        ]
    );

    //Pass the OAuth provider instance to PHPMailer
    $mail->setOAuth(
        new OAuth(
            [
                'provider' => $provider,
                'clientId' => $clientId,
                'clientSecret' => $clientSecret,
                'refreshToken' => $refreshToken,
                'userName' => $email,
            ]
        )
    );

    //Set who the message is to be sent from
    //For gmail, this generally needs to be the same as the user you logged in as
    $mail->setFrom($email, 'First Last');

    //Set who the message is to be sent to
    $mail->addAddress('[REDACTED]', 'John Doe');

    //Set the subject line
    $mail->Subject = 'PHPMailer GMail XOAUTH2 SMTP test';

    //Read an HTML message body from an external file, convert referenced images to embedded,
    //convert HTML into a basic plain-text alternative body
    $mail->CharSet = PHPMailer::CHARSET_UTF8;
    $mail->msgHTML(file_get_contents('test.html'), __DIR__);

    //Replace the plain text body with one created manually
    $mail->AltBody = 'This is a plain-text message body';

    //Attach an image file
    $mail->addAttachment('images/phpmailer_mini.png');

    //send the message, check for errors
    if (!$mail->send()) {
        echo 'Mailer Error: ' . $mail->ErrorInfo;
    } else {
        echo 'Message sent!';
    }
}
catch(Exception $e) {
    // TODO(developer) - handle error appropriately
    echo 'Message: ' .$e->getMessage();
}
© www.soinside.com 2019 - 2024. All rights reserved.