我使用 phpmailer 透過 smtp.google.com 伺服器發送郵件,但現在它無法正常工作,因為他們說使用 OAuth2.0 設定。
我參考了一些範例並使用使用 PhpMailer 和 Gmail XOAUTH2 發送電子郵件建立了一個範例頁面來測試它,但它不起作用。誰能指出程式碼中出了什麼問題嗎?
這是我的 html 頁面
<?php namespace Phppot; require_once ("lib/MailService.php"); $mailService = new MailService(); if (! empty($_POST['send'])) { $response = $mailService->sendContactMail($_POST); } ?> <html> <head> <title>Contact Us Form</title> <link rel="stylesheet" type="text/css" href="assets/css/style.css" /> </head> <body> <div class="form-container"> <form name="frmContact" id="" frmContact"" method="post" action="" enctype="multipart/form-data" onsubmit="return validateContactForm()"> <div class="input-row"> <label style="padding-top: 20px;">Name</label> <span id="userName-info" class="info"></span><br /> <input type="text" class="input-field" name="userName" id="userName" /> </div> <div class="input-row"> <label>Email</label> <span id="userEmail-info" class="info"></span><br /> <input type="text" class="input-field" name="userEmail" id="userEmail" /> </div> <div class="input-row"> <label>Subject</label> <span id="subject-info" class="info"></span><br /> <input type="text" class="input-field" name="subject" id="subject" /> </div> <div class="input-row"> <label>Message</label> <span id="userMessage-info" class="info"></span><br /> <textarea name="content" id="content" class="input-field" cols="60" rows="6"></textarea> </div> <div> <input type="submit" name="send" class="btn-submit" value="Send" /> <div id="statusMessage"> <?php if (! empty($response)) { ?> <p class='<?php echo $response['type']; ?>Message'><?php echo $response['text']; ?></p> <?php } ?> </div> </div> </form> </div> <script type="text/javascript" src="assets/js/validation.js"></script> </body> </html>
這是 get_oauth_token.php
<?php /** * PHPMailer - PHP email creation and transport class. * PHP Version 5.5 * @package PHPMailer * @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> * @author Jim Jagielski (jimjag) <jimjag@gmail.com> * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> * @author Brent R. Matzelle (original founder) * @copyright 2012 - 2020 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @note This program is distributed in the hope that it will be useful - WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. */ /** * Get an OAuth2 token from an OAuth2 provider. * * Install this script on your server so that it's accessible * as [https/http]://<yourdomain>/<folder>/get_oauth_token.php * e.g.: http://localhost/phpmailer/get_oauth_token.php * * Ensure dependencies are installed with 'composer install' * * Set up an app in your Google/Yahoo/Microsoft account * * Set the script address as the app's redirect URL * If no refresh token is obtained when running this file, * revoke access to your app and run the script again. */ namespace PHPMailer\PHPMailer; /** * Aliases for League Provider Classes * Make sure you have added these to your composer.json and run `composer install` * Plenty to choose from here: * @see http://oauth2-client.thephpleague.com/providers/thirdparty/ */ //@see https://github.com/thephpleague/oauth2-google use League\OAuth2\Client\Provider\Google; //@see https://packagist.org/packages/hayageek/oauth2-yahoo use Hayageek\OAuth2\Client\Provider\Yahoo; //@see https://github.com/stevenmaguire/oauth2-microsoft use Stevenmaguire\OAuth2\Client\Provider\Microsoft; if (!isset($_GET['code']) && !isset($_GET['provider'])) { ?> <html> <body>Select Provider:<br> <a href='?provider=Google'>Google</a><br> <a href='?provider=Yahoo'>Yahoo</a><br> <a href='?provider=Microsoft'>Microsoft/Outlook/Hotmail/Live/Office365</a><br> </body> </html> <?php exit; } require 'vendor/autoload.php'; session_start(); $providerName = ''; if (array_key_exists('provider', $_GET)) { $providerName = $_GET['provider']; $_SESSION['provider'] = $providerName; } elseif (array_key_exists('provider', $_SESSION)) { $providerName = $_SESSION['provider']; } if (!in_array($providerName, ['Google', 'Microsoft', 'Yahoo'])) { exit('Only Google, Microsoft and Yahoo OAuth2 providers are currently supported in this script.'); } //These details are obtained by setting up an app in the Google developer console, //or whichever provider you're using. $clientId = 'random.apps.googleusercontent.com'; $clientSecret = 'random_key'; //If this automatic URL doesn't work, set it yourself manually to the URL of this script $redirectUri = (isset($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; //$redirectUri = 'http://localhost/PHPMailer/redirect'; $params = [ 'clientId' => $clientId, 'clientSecret' => $clientSecret, 'redirectUri' => $redirectUri, 'accessType' => 'offline' ]; $options = []; $provider = null; switch ($providerName) { case 'Google': $provider = new Google($params); $options = [ 'scope' => [ 'https://mail.google.com/' ] ]; break; case 'Yahoo': $provider = new Yahoo($params); break; case 'Microsoft': $provider = new Microsoft($params); $options = [ 'scope' => [ 'wl.imap', 'wl.offline_access' ] ]; break; } if (null === $provider) { exit('Provider missing'); } if (!isset($_GET['code'])) { //If we don't have an authorization code then get one $authUrl = $provider->getAuthorizationUrl($options); $_SESSION['oauth2state'] = $provider->getState(); header('Location: ' . $authUrl); exit; //Check given state against previously stored one to mitigate CSRF attack } elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) { unset($_SESSION['oauth2state']); unset($_SESSION['provider']); exit('Invalid state'); } else { unset($_SESSION['provider']); //Try to get an access token (using the authorization code grant) $token = $provider->getAccessToken( 'authorization_code', [ 'code' => $_GET['code'] ] ); //Use this to interact with an API on the users behalf //Use this to get a new access token if the old one expires echo 'Refresh Token: ', $token->getRefreshToken(); }
提交表單時,顯示錯誤
致命錯誤:未捕獲錯誤:在lib/MailService.php:31 中找不到類別「Phppot\SMTP」堆疊追蹤:#0 index.php(7): Phppot\MailService->sendContactMail(Array) #1 {main}拋出在lib/MailService.php 第31 行
已編輯
這是我的 MailService.php 檔案
<?php namespace Phppot; use Phppot\Config; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; class MailService { function sendContactMail($postValues) { $name = $postValues["userName"]; $email = $postValues["userEmail"]; $subject = $postValues["subject"]; $content = $postValues["content"]; require_once __DIR__ . '/Config.php'; $recipientArray = explode(",", Config::RECIPIENT_EMAIL); require_once __DIR__ . '/../vendor/autoload.php'; $mail = new PHPMailer(true); // Comment the following lines of code till $mail->Port to send // mail using phpmail instead of 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_OFF; //Set the hostname of the mail server $mail->Host = Config::SMTP_HOST; //Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission $mail->Port = Config::SMTP_PORT; //Set the encryption mechanism to use - STARTTLS or SMTPS $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; //Whether to use SMTP authentication $mail->SMTPAuth = true; //Set AuthType to use XOAUTH2 $mail->AuthType = 'XOAUTH2'; //Fill in authentication details here //Either the gmail account owner, or the user that gave consent $oauthUserEmail = Config::OAUTH_USER_EMAIL; $clientId = Config::OAUTH_CLIENT_ID; $clientSecret = Config::OAUTH_SECRET_KEY; //Obtained by configuring and running get_oauth_token.php //after setting up an app in Google Developer Console. $refreshToken = Config::REFRESH_TOKEN; //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' => $oauthUserEmail, ] ) ); // Recipients $mail->setFrom(Config::SENDER_EMAIL, $name); $mail->addReplyTo($email, $name); $mail->addAddress(Config::RECIPIENT_EMAIL, Config::RECIPIENT_EMAIL); $mail->Subject = $subject; $mail->CharSet = PHPMailer::CHARSET_UTF8; $mail->msgHTML($mailBody); //Replace the plain text body with one created manually $mail->AltBody = 'This is a plain-text message body'; if (!$mail->send()) { $output = json_encode(array('type'=>'error', 'text' => '<b>'.$from.'</b> is invalid.')); $output = json_encode(array('type'=>'error', 'text' => 'Server error. Please mail vincy@phppot.com')); } else { $output = json_encode(array('type'=>'message', 'text' => 'Thank you, I will get back to you shortly.')); } return $output; } }
您遇到命名空間問題。你正在這樣做:
然後使用這個:
因為您尚未將PHPMailer 套件中的SMTP 類別名稱匯入到您的命名空間中,所以它將尋找名為
Phppot\SMTP
的類,該類別不存在,因此會出現錯誤訊息。您可以透過新增以下內容來解決此問題:這將使它使用 PHPMailer 中正確的 SMTP 類別。
請注意,這裡可能有另一個問題。您已經
use Phppot\Config;
,但您已經在Phppot
命名空間中,因此將查找名為Phppot\Phppot\Config,可能不存在。如果該類別已位於您聲明的命名空間中,則不需要為其使用
use
語句。