需要使用 php 邮件程序从 gmail 发送邮件而不启用 "less secure app" 并生成 "app password"
Need to send mail from gmail using php mailer without enabling "less secure app" and generating "app password"
我正在尝试使用 php 邮件程序从我的 gmail 帐户发送邮件。
我知道要使用 php 邮件程序发送邮件,我们需要从我们的 gmail 帐户设置中启用 "less secure app"。
还有一个选项,在不启用 "less secure app" 的情况下,我们可以使用 "APP password",通过启用两步验证从安全性较低的应用程序发送邮件。
但问题是使用 "APP password",我无法从 php 邮件程序发送邮件,收到用户名和密码未被接受的错误消息。
我搜索后发现,我们无法使用 "APP password" 从安全性较低的应用程序发送邮件。从此找到 link https://support.google.com/accounts/answer/185833?hl=en&authuser=5
我正在使用以下 php 邮件程序代码发送邮件:
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
// Load Composer's autoloader
require 'vendor/autoload.php';
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'ssl://smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = username;
$mail->Password = password;
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465;
//Recipients
$mail->setFrom('test@gmail.com', 'Test');
$mail->addAddress('test1@gmail.com', 'Test1'); // Add a recipient
$mail->addAddress('test2@gmail.com'); // Name is optional
$mail->addReplyTo('test@gmail.com', 'Test');
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
使用时"APP password"出现如下错误信息。
2019-09-04 07:24:15 CLIENT -> SERVER: EHLO localhost
2019-09-04 07:24:15 CLIENT -> SERVER: AUTH LOGIN
2019-09-04 07:24:16 CLIENT -> SERVER: <credentials hidden>
2019-09-04 07:24:16 CLIENT -> SERVER: <credentials hidden>
2019-09-04 07:24:16 SMTP ERROR: Password command failed: 535-5.7.8 Username and Password not accepted. Learn more at535 5.7.8 https://support.google.com/mail/?p=BadCredentials z12sm8871955pfj.41 - gsmtp
SMTP Error: Could not authenticate.
2019-09-04 07:24:16 CLIENT -> SERVER: QUIT
SMTP Error: Could not authenticate.
Message could not be sent. Mailer Error: SMTP Error: Could not authenticate.
请提供在不启用 "less secure app" 和使用 gmail "APP password"
的情况下发送邮件的解决方案
我也使用了第三种方式——XOAUTH2认证来发送邮件。以下是我的代码:
<?php
/**
* This example shows how to send via Google's Gmail servers using XOAUTH2 authentication.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\OAuth;
// Alias the League Google OAuth2 provider class
use League\OAuth2\Client\Provider\Google;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
//Load dependencies from composer
//If this causes an error, run 'composer install'
require 'vendor/autoload.php';
$send_to_address = $_GET['email'];
$send_to_name = $_GET['name'];
//Create a new PHPMailer instance
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Set the hostname of the mail server
$mail->Host = 'smtp.gmail.com';
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;
//Set the encryption system to use - ssl (deprecated) or tls
$mail->SMTPSecure = 'tls';
//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
$email = 'gts@goodway.in';
$clientId = '315061611767-fitjjndpsi6uo1j7hn923loaa0dg1ch1.apps.googleusercontent.com';
$clientSecret = '3m-47D5Ojvpnfqp5qxxQ2WLn';
//Obtained by configuring and running get_oauth_token.php
//after setting up an app in Google Developer Console.
$refreshToken = '4/qgEr9g7oYr2jk-q2YZpDbD5GCKK0oMdUHrVwsww9t5tXey5zr4fcjhS4Mk25rLcklEkUl4F20iKKmy-CAMme5r8';
//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, 'Gudbiz');
//Set who the message is to be sent to
$mail->addAddress($send_to_address, $send_to_name);
//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 = 'utf-8';
//$mail->msgHTML(file_get_contents('contentsutf8.html'), __DIR__);
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
//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!";
}
使用上面的代码我得到如下输出:
2019-09-04 11:52:57 SERVER -> CLIENT: 220 smtp.gmail.com ESMTP v8sm7946021pje.6 - gsmtp
2019-09-04 11:52:57 CLIENT -> SERVER: EHLO testapi.howorkforce.com
2019-09-04 11:52:58 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [13.126.85.98]250-SIZE 35882577250-8BITMIME250-STARTTLS250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2019-09-04 11:52:58 CLIENT -> SERVER: STARTTLS
2019-09-04 11:52:58 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2019-09-04 11:52:58 CLIENT -> SERVER: EHLO testapi.howorkforce.com
2019-09-04 11:52:58 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [13.126.85.98]250-SIZE 35882577250-8BITMIME250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
但是邮件没有发送。请为此提出解决方案。
请使用 "SMTP debug 4"
查找附加信息
2019-09-05 11:51:05 Connection: opening to smtp.gmail.com:587, timeout=300, options=array()
2019-09-05 11:51:05 Connection: opened
2019-09-05 11:51:05 SMTP INBOUND: "220 smtp.gmail.com ESMTP l23sm2317472pjy.3 - gsmtp"
2019-09-05 11:51:05 SERVER -> CLIENT: 220 smtp.gmail.com ESMTP l23sm2317472pjy.3 - gsmtp
2019-09-05 11:51:05 CLIENT -> SERVER: EHLO localhost
2019-09-05 11:51:06 SMTP INBOUND: "250-smtp.gmail.com at your service, [103.125.155.132]"
2019-09-05 11:51:06 SMTP INBOUND: "250-SIZE 35882577"
2019-09-05 11:51:06 SMTP INBOUND: "250-8BITMIME"
2019-09-05 11:51:06 SMTP INBOUND: "250-STARTTLS"
2019-09-05 11:51:06 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2019-09-05 11:51:06 SMTP INBOUND: "250-PIPELINING"
2019-09-05 11:51:06 SMTP INBOUND: "250-CHUNKING"
2019-09-05 11:51:06 SMTP INBOUND: "250 SMTPUTF8"
2019-09-05 11:51:06 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [103.125.155.132]250-SIZE 35882577250-8BITMIME250-STARTTLS250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2019-09-05 11:51:06 CLIENT -> SERVER: STARTTLS
2019-09-05 11:51:06 SMTP INBOUND: "220 2.0.0 Ready to start TLS"
2019-09-05 11:51:06 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2019-09-05 11:51:06 CLIENT -> SERVER: EHLO localhost
2019-09-05 11:51:06 SMTP INBOUND: "250-smtp.gmail.com at your service, [103.125.155.132]"
2019-09-05 11:51:06 SMTP INBOUND: "250-SIZE 35882577"
2019-09-05 11:51:06 SMTP INBOUND: "250-8BITMIME"
2019-09-05 11:51:06 SMTP INBOUND: "250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
2019-09-05 11:51:06 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2019-09-05 11:51:06 SMTP INBOUND: "250-PIPELINING"
2019-09-05 11:51:06 SMTP INBOUND: "250-CHUNKING"
2019-09-05 11:51:06 SMTP INBOUND: "250 SMTPUTF8"
2019-09-05 11:51:06 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [103.125.155.132]250-SIZE 35882577250-8BITMIME250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2019-09-05 11:51:06 Auth method requested: XOAUTH2
2019-09-05 11:51:06 Auth methods available on the server: LOGIN,PLAIN,XOAUTH2,PLAIN-CLIENTTOKEN,OAUTHBEARER,XOAUTH
如果您要避免这些事情,剩下的唯一选择是使用 PHPMailer 支持的 XOAUTH2 身份验证。配置起来既困难又复杂,并且可能会发生变化,因此我不会将代码粘贴到此处以使其过时,而是让您参考源代码。将您的代码基于 the gmail OAuth example provided with PHPMailer, and configure it and obtain credentials using the PHPMailer gmail xoauth2 guide in the project wiki.
我得到了解决方案。我使用的刷新令牌就是那个,这让我非常头疼。
我使用的 "refresh token" 无效。一旦我重新生成刷新令牌,一切似乎都很好。邮件发送正确。
我正在尝试使用 php 邮件程序从我的 gmail 帐户发送邮件。
我知道要使用 php 邮件程序发送邮件,我们需要从我们的 gmail 帐户设置中启用 "less secure app"。
还有一个选项,在不启用 "less secure app" 的情况下,我们可以使用 "APP password",通过启用两步验证从安全性较低的应用程序发送邮件。
但问题是使用 "APP password",我无法从 php 邮件程序发送邮件,收到用户名和密码未被接受的错误消息。
我搜索后发现,我们无法使用 "APP password" 从安全性较低的应用程序发送邮件。从此找到 link https://support.google.com/accounts/answer/185833?hl=en&authuser=5
我正在使用以下 php 邮件程序代码发送邮件:
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
// Load Composer's autoloader
require 'vendor/autoload.php';
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'ssl://smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = username;
$mail->Password = password;
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465;
//Recipients
$mail->setFrom('test@gmail.com', 'Test');
$mail->addAddress('test1@gmail.com', 'Test1'); // Add a recipient
$mail->addAddress('test2@gmail.com'); // Name is optional
$mail->addReplyTo('test@gmail.com', 'Test');
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
使用时"APP password"出现如下错误信息。
2019-09-04 07:24:15 CLIENT -> SERVER: EHLO localhost
2019-09-04 07:24:15 CLIENT -> SERVER: AUTH LOGIN
2019-09-04 07:24:16 CLIENT -> SERVER: <credentials hidden>
2019-09-04 07:24:16 CLIENT -> SERVER: <credentials hidden>
2019-09-04 07:24:16 SMTP ERROR: Password command failed: 535-5.7.8 Username and Password not accepted. Learn more at535 5.7.8 https://support.google.com/mail/?p=BadCredentials z12sm8871955pfj.41 - gsmtp
SMTP Error: Could not authenticate.
2019-09-04 07:24:16 CLIENT -> SERVER: QUIT
SMTP Error: Could not authenticate.
Message could not be sent. Mailer Error: SMTP Error: Could not authenticate.
请提供在不启用 "less secure app" 和使用 gmail "APP password"
的情况下发送邮件的解决方案我也使用了第三种方式——XOAUTH2认证来发送邮件。以下是我的代码:
<?php
/**
* This example shows how to send via Google's Gmail servers using XOAUTH2 authentication.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\OAuth;
// Alias the League Google OAuth2 provider class
use League\OAuth2\Client\Provider\Google;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
//Load dependencies from composer
//If this causes an error, run 'composer install'
require 'vendor/autoload.php';
$send_to_address = $_GET['email'];
$send_to_name = $_GET['name'];
//Create a new PHPMailer instance
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Set the hostname of the mail server
$mail->Host = 'smtp.gmail.com';
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;
//Set the encryption system to use - ssl (deprecated) or tls
$mail->SMTPSecure = 'tls';
//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
$email = 'gts@goodway.in';
$clientId = '315061611767-fitjjndpsi6uo1j7hn923loaa0dg1ch1.apps.googleusercontent.com';
$clientSecret = '3m-47D5Ojvpnfqp5qxxQ2WLn';
//Obtained by configuring and running get_oauth_token.php
//after setting up an app in Google Developer Console.
$refreshToken = '4/qgEr9g7oYr2jk-q2YZpDbD5GCKK0oMdUHrVwsww9t5tXey5zr4fcjhS4Mk25rLcklEkUl4F20iKKmy-CAMme5r8';
//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, 'Gudbiz');
//Set who the message is to be sent to
$mail->addAddress($send_to_address, $send_to_name);
//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 = 'utf-8';
//$mail->msgHTML(file_get_contents('contentsutf8.html'), __DIR__);
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
//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!";
}
使用上面的代码我得到如下输出:
2019-09-04 11:52:57 SERVER -> CLIENT: 220 smtp.gmail.com ESMTP v8sm7946021pje.6 - gsmtp
2019-09-04 11:52:57 CLIENT -> SERVER: EHLO testapi.howorkforce.com
2019-09-04 11:52:58 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [13.126.85.98]250-SIZE 35882577250-8BITMIME250-STARTTLS250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2019-09-04 11:52:58 CLIENT -> SERVER: STARTTLS
2019-09-04 11:52:58 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2019-09-04 11:52:58 CLIENT -> SERVER: EHLO testapi.howorkforce.com
2019-09-04 11:52:58 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [13.126.85.98]250-SIZE 35882577250-8BITMIME250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
但是邮件没有发送。请为此提出解决方案。
请使用 "SMTP debug 4"
查找附加信息 2019-09-05 11:51:05 Connection: opening to smtp.gmail.com:587, timeout=300, options=array()
2019-09-05 11:51:05 Connection: opened
2019-09-05 11:51:05 SMTP INBOUND: "220 smtp.gmail.com ESMTP l23sm2317472pjy.3 - gsmtp"
2019-09-05 11:51:05 SERVER -> CLIENT: 220 smtp.gmail.com ESMTP l23sm2317472pjy.3 - gsmtp
2019-09-05 11:51:05 CLIENT -> SERVER: EHLO localhost
2019-09-05 11:51:06 SMTP INBOUND: "250-smtp.gmail.com at your service, [103.125.155.132]"
2019-09-05 11:51:06 SMTP INBOUND: "250-SIZE 35882577"
2019-09-05 11:51:06 SMTP INBOUND: "250-8BITMIME"
2019-09-05 11:51:06 SMTP INBOUND: "250-STARTTLS"
2019-09-05 11:51:06 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2019-09-05 11:51:06 SMTP INBOUND: "250-PIPELINING"
2019-09-05 11:51:06 SMTP INBOUND: "250-CHUNKING"
2019-09-05 11:51:06 SMTP INBOUND: "250 SMTPUTF8"
2019-09-05 11:51:06 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [103.125.155.132]250-SIZE 35882577250-8BITMIME250-STARTTLS250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2019-09-05 11:51:06 CLIENT -> SERVER: STARTTLS
2019-09-05 11:51:06 SMTP INBOUND: "220 2.0.0 Ready to start TLS"
2019-09-05 11:51:06 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2019-09-05 11:51:06 CLIENT -> SERVER: EHLO localhost
2019-09-05 11:51:06 SMTP INBOUND: "250-smtp.gmail.com at your service, [103.125.155.132]"
2019-09-05 11:51:06 SMTP INBOUND: "250-SIZE 35882577"
2019-09-05 11:51:06 SMTP INBOUND: "250-8BITMIME"
2019-09-05 11:51:06 SMTP INBOUND: "250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
2019-09-05 11:51:06 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2019-09-05 11:51:06 SMTP INBOUND: "250-PIPELINING"
2019-09-05 11:51:06 SMTP INBOUND: "250-CHUNKING"
2019-09-05 11:51:06 SMTP INBOUND: "250 SMTPUTF8"
2019-09-05 11:51:06 SERVER -> CLIENT: 250-smtp.gmail.com at your service, [103.125.155.132]250-SIZE 35882577250-8BITMIME250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH250-ENHANCEDSTATUSCODES250-PIPELINING250-CHUNKING250 SMTPUTF8
2019-09-05 11:51:06 Auth method requested: XOAUTH2
2019-09-05 11:51:06 Auth methods available on the server: LOGIN,PLAIN,XOAUTH2,PLAIN-CLIENTTOKEN,OAUTHBEARER,XOAUTH
如果您要避免这些事情,剩下的唯一选择是使用 PHPMailer 支持的 XOAUTH2 身份验证。配置起来既困难又复杂,并且可能会发生变化,因此我不会将代码粘贴到此处以使其过时,而是让您参考源代码。将您的代码基于 the gmail OAuth example provided with PHPMailer, and configure it and obtain credentials using the PHPMailer gmail xoauth2 guide in the project wiki.
我得到了解决方案。我使用的刷新令牌就是那个,这让我非常头疼。
我使用的 "refresh token" 无效。一旦我重新生成刷新令牌,一切似乎都很好。邮件发送正确。