PHPMailer Google Oauth2 发送邮件问题

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

我正在使用 php 7.4 和 php 库

{
   "require": {
       "league/oauth2-google": "4.0.0",
       "phpmailer/phpmailer": "6.1.4"
   }
}

这是我的PHP代码

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\OAuth;
use League\OAuth2\Client\Provider\Google;

date_default_timezone_set('Etc/UTC');

require '/home/automa15/vendor/autoload.php';

session_start();

$email = 'xxx';
$clientId = 'xxx.googleusercontent.com';
$clientSecret = 'xxx';
$redirectUri = 'xxx/oauth2callback.php';
$tokenPath = 'xxx/token.json';

$provider = new Google([
    'clientId' => $clientId,
    'clientSecret' => $clientSecret,
    'redirectUri' => $redirectUri,
    'scopes' => ['https://www.googleapis.com/auth/gmail.send']
]);

function saveTokenToFile($tokenPath, $token) {
    if (!file_put_contents($tokenPath, json_encode($token->jsonSerialize()))) {
        exit('Failed to save the access token');
    }
    echo 'Access token saved successfully<br>';
}

function getTokenFromFile($tokenPath) {
    if (file_exists($tokenPath)) {
        $tokenData = json_decode(file_get_contents($tokenPath), true);
        if (isset($tokenData['access_token']) && isset($tokenData['refresh_token'])) {
            return new \League\OAuth2\Client\Token\AccessToken($tokenData);
        }
    }
    return null;
}

$token = getTokenFromFile($tokenPath);

if (!$token) {
    if (!isset($_GET['code'])) {
        $authUrl = $provider->getAuthorizationUrl([
            'access_type' => 'offline',
            'prompt' => 'consent',
        ]);
        $_SESSION['oauth2state'] = $provider->getState();
        echo '<script>window.location.replace("' . $authUrl . '");</script>';
        exit;
    } elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
        unset($_SESSION['oauth2state']);
        exit('Invalid state');
    } else {
        // Try to get an access token using the authorization code
        try {
            $token = $provider->getAccessToken('authorization_code', [
                'code' => $_GET['code']
            ]);
            if ($token->getRefreshToken()) {
                saveTokenToFile($tokenPath, $token);
                echo 'Token obtained and saved<br>';
            } else {
                exit('Failed to obtain refresh token');
            }
            echo '<script>window.location.replace("' . $_SERVER['PHP_SELF'] . '");</script>';
            exit;
        } catch (Exception $e) {
            exit('Failed to get access token: ' . $e->getMessage());
        }
    }
} else {
    // Refresh the token if it has expired
    if ($token->hasExpired()) {
        try {
            $token = $provider->getAccessToken('refresh_token', [
                'refresh_token' => $token->getRefreshToken()
            ]);
            saveTokenToFile($tokenPath, $token);
            echo 'Token refreshed successfully<br>';
        } catch (Exception $e) {
            exit('Failed to refresh access token: ' . $e->getMessage());
        }
    }
}

if (!$token->getRefreshToken()) {
    exit('No refresh token found in the access token');
}

$mail = new PHPMailer(true);
$mail->isSMTP();
 $mail->SMTPDebug = 4;
    $mail->isSMTP();
    $mail->Host = 'smtp.gmail.com';
    $mail->SMTPAuth = true;
    $mail->SMTPSecure = 'tls';
    $mail->Port = 587;
    $mail->AuthType = 'XOAUTH2';

$t = $token->getRefreshToken();

$mail->setOAuth(new OAuth([
    'provider' => $provider,
    'clientId' => $clientId,
    'clientSecret' => $clientSecret,
    'refreshToken' => $t,
    'userName' => $email,
]));

$mail->setFrom($email, 'Soul of Tanzania');
$mail->addAddress('xxx', 'John Doe');
$mail->Subject = 'PHPMailer GMail XOAUTH2 SMTP test';
$mail->CharSet = PHPMailer::CHARSET_UTF8;
$mail->msgHTML("aaa");
$mail->AltBody = 'This is a plain-text message body';

    if (!$mail->send()) {
        echo 'Mailer Error: ' . $mail->ErrorInfo;
    } else {
        echo 'Message sent!';
    }

?>

这是 oauth2callback.php 的代码

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

use League\OAuth2\Client\Provider\Google;
require '/home/automa15/vendor/autoload.php';

session_start();

$email = 'xxx';
$clientId = 'xxx.googleusercontent.com';
$clientSecret = 'xxx';
$redirectUri = 'xxx/oauth2callback.php';
$tokenPath = 'xxx/token.json';

$provider = new Google([
    'clientId' => $clientId,
    'clientSecret' => $clientSecret,
    'redirectUri' => $redirectUri,
    'scopes' => ['https://www.googleapis.com/auth/gmail.send'],
    'accessType' => 'offline',
    'prompt' => 'consent',
]);

if (!isset($_GET['code'])) {

    $authorizationUrl = $provider->getAuthorizationUrl([
        'access_type' => 'offline',
        'prompt' => 'consent',
    ]);

    $_SESSION['oauth2state'] = $provider->getState();

    $_SESSION['oauth2pkceCode'] = $provider->getPkceCode();

    header('Location: ' . $authorizationUrl);
    exit;

} elseif (empty($_GET['state']) || empty($_SESSION['oauth2state']) || $_GET['state'] !== $_SESSION['oauth2state']) {

    if (isset($_SESSION['oauth2state'])) {
        unset($_SESSION['oauth2state']);
    }

    exit('Invalid state');

} else {

    try {
    
        // Try to get an access token using the authorization code grant.
        $accessToken = $provider->getAccessToken(
            'authorization_code',
            [
                'code' => $_GET['code']
            ]
        );

        echo 'Access Token: ' . $accessToken->getToken() . "<br>";
        echo 'Refresh Token: ' . $accessToken->getRefreshToken() . "<br>";
        echo 'Expired in: ' . $accessToken->getExpires() . "<br>";
        echo 'Already expired? ' . ($accessToken->hasExpired() ? 'expired' : 'not expired') . "<br>";

        $tokenPath = 'xxx/token.json';
        $tokenData = [
            'access_token' => $accessToken->getToken(),
            'refresh_token' => $accessToken->getRefreshToken(),
            'expires' => $accessToken->getExpires(),
            'resource_owner_id' => $accessToken->getResourceOwnerId(),
        ];
        if (!file_put_contents($tokenPath, json_encode($tokenData))) {
            exit('Failed to save the access token');
        }
        echo 'Tokens obtained and saved to token.json';

    } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {

        // Failed to get the access token or user details.
        exit($e->getMessage());

    }

}
?>

我已经完成了所有不太安全的应用程序,如果我切换到用户和密码,但在 Oauth2 中发出问题,代码就可以正常工作,这就是我收到的错误,任何人都可以帮忙,这正在成为一种折磨。

2024-05-23 14:23:18 Connection: opening to smtp.gmail.com:587, timeout=300, options=array()
2024-05-23 14:23:18 Connection: opened
2024-05-23 14:23:19 SMTP INBOUND: "220 smtp.gmail.com ESMTP d9443c01a7336-1ef0c036347sm257008095ad.203 - gsmtp"
2024-05-23 14:23:19 SERVER -> CLIENT: 220 smtp.gmail.com ESMTP d9443c01a7336-1ef0c036347sm257008095ad.203 - gsmtp
2024-05-23 14:23:19 CLIENT -> SERVER: EHLO www.souloftanzania.com
2024-05-23 14:23:19 SMTP INBOUND: "250-smtp.gmail.com at your service, [75.119.223.127]"
2024-05-23 14:23:19 SMTP INBOUND: "250-SIZE 35882577"
2024-05-23 14:23:19 SMTP INBOUND: "250-8BITMIME"
2024-05-23 14:23:19 SMTP INBOUND: "250-STARTTLS"
2024-05-23 14:23:19 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2024-05-23 14:23:19 SMTP INBOUND: "250-PIPELINING"
2024-05-23 14:23:19 SMTP INBOUND: "250-CHUNKING"
2024-05-23 14:23:19 SMTP INBOUND: "250 SMTPUTF8"
2024-05-23 14:23:19 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [75.119.223.127]250-SIZE 35882577250-8BITMIME250-STARTTLS250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2024-05-23 14:23:19 CLIENT -> SERVER: STARTTLS
2024-05-23 14:23:19 SMTP INBOUND: "220 2.0.0 Ready to start TLS"
2024-05-23 14:23:19 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2024-05-23 14:23:20 CLIENT -> SERVER: EHLO www.souloftanzania.com
2024-05-23 14:23:20 SMTP INBOUND: "250-smtp.gmail.com at your service, [75.119.223.127]"
2024-05-23 14:23:20 SMTP INBOUND: "250-SIZE 35882577"
2024-05-23 14:23:20 SMTP INBOUND: "250-8BITMIME"
2024-05-23 14:23:20 SMTP INBOUND: "250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
2024-05-23 14:23:20 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2024-05-23 14:23:20 SMTP INBOUND: "250-PIPELINING"
2024-05-23 14:23:20 SMTP INBOUND: "250-CHUNKING"
2024-05-23 14:23:20 SMTP INBOUND: "250 SMTPUTF8"
2024-05-23 14:23:20 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [75.119.223.127]250-SIZE 35882577250-8BITMIME250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2024-05-23 14:23:20 Auth method requested: XOAUTH2
2024-05-23 14:23:20 Auth methods available on the server: LOGIN,PLAIN,XOAUTH2,PLAIN-CLIENTTOKEN,OAUTHBEARER,XOAUTH
2024-05-23 14:23:21 CLIENT -> SERVER: AUTH XOAUTH2 dXNlcj1pbmZvQHNvdWxvZnRhbnphbmlhLmNvbQFhdXRoPUJlYXJlciB5YTI5LmEwQVhvb0NndkdUcXJHNnlwNTlIanZCd0xSaDRzNnpTdDFiWENXZmJTYkl4YUluekJXMFRQcnVkOXpEcEZoYm9RN2VKSGt4UmNSUGFhVDhfSDJQekw0WFJVMENHbjRpT0hPOUplanV5Y25KZFBqUVp0dTk3ZVF5TVdzRVdVRi1lSHBoUHdDTXlnT05zdEwyel9DUzIyZk1Xak9oRE5COERfdlZzM2VhQ2dZS0FlMFNBUThTRlFIR1gyTWk2dTR5Zk14M3pNVENFWTFGclR0aDJ3MDE3MQEB
2024-05-23 14:23:21 SMTP INBOUND: "334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ=="
2024-05-23 14:23:21 SERVER -> CLIENT: 334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
2024-05-23 14:23:21 SMTP ERROR: AUTH command failed: 334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
SMTP Error: Could not authenticate.
2024-05-23 14:23:21 CLIENT -> SERVER: QUIT
2024-05-23 14:23:21 SMTP INBOUND: "535-5.7.8 Username and Password not accepted. For more information, go to"
2024-05-23 14:23:21 SMTP INBOUND: "535 5.7.8 https://support.google.com/mail/?p=BadCredentials d9443c01a7336-1ef0c036347sm257008095ad.203 - gsmtp"
2024-05-23 14:23:21 SERVER -> CLIENT: 535-5.7.8 Username and Password not accepted. For more information, go to535 5.7.8 https://support.google.com/mail/?p=BadCredentials d9443c01a7336-1ef0c036347sm257008095ad.203 - gsmtp
2024-05-23 14:23:21 SMTP ERROR: QUIT command failed: 535-5.7.8 Username and Password not accepted. For more information, go to535 5.7.8 https://support.google.com/mail/?p=BadCredentials d9443c01a7336-1ef0c036347sm257008095ad.203 - gsmtp
2024-05-23 14:23:21 Connection: closed
SMTP Error: Could not authenticate.

Fatal error: Uncaught PHPMailer\PHPMailer\Exception: SMTP Error: Could not authenticate. in /home/automa15/vendor/phpmailer/phpmailer/src/PHPMailer.php:2024 Stack trace: #0 /home/automa15/vendor/phpmailer/phpmailer/src/PHPMailer.php(1844): PHPMailer\PHPMailer\PHPMailer->smtpConnect(Array) #1 /home/automa15/vendor/phpmailer/phpmailer/src/PHPMailer.php(1587): PHPMailer\PHPMailer\PHPMailer->smtpSend('Date: Thu, 23 M...', 'This is a multi...') #2 /home/automa15/vendor/phpmailer/phpmailer/src/PHPMailer.php(1423): PHPMailer\PHPMailer\PHPMailer->postSend() #3 /home/automa15/souloftanzania.com/backoffice/addPayment2.php(138): PHPMailer\PHPMailer\PHPMailer->send() #4 {main} thrown in /home/automa15/vendor/phpmailer/phpmailer/src/PHPMailer.php on line 2024

到目前为止尝试了所有解决方案,但不知道这里缺少或错误的内容

php oauth-2.0 smtp phpmailer php-7.4
1个回答
0
投票

我设法通过添加这样的全范围访问来解决这个问题

而不是这个

$provider = new Google([
    'clientId' => $clientId,
    'clientSecret' => $clientSecret,
    'redirectUri' => $redirectUri,
    'scopes' => ['https://www.googleapis.com/auth/gmail.send']
]);

我正在做这个

$provider = new Google([
        'clientId' => $clientId,
        'clientSecret' => $clientSecret,
        'redirectUri' => $redirectUri,
        'scopes' => ['https://www.googleapis.com/auth/gmail.send', 'https://mail.google.com/']
]);
© www.soinside.com 2019 - 2024. All rights reserved.