如何处理 transient/intermittent PHPMailer SMTP 连接错误
How to handle transient/intermittent PHPMailer SMTP connect errors
我搜索了 Whosebug 和 PHPMailer 问题,但没有成功。有很多永久性 PHPMailer SMTP 连接错误,但 none 我可以在瞬态或间歇性错误中看到。
我正在使用 PHPMailer (6.2) 和 PHP 8.0 从我的远程 Web 服务器向 smtp.office365.com(Microsoft Exchange Online 服务)发送电子邮件。大多数时候它工作正常。
间歇性地,我怀疑是由于网络级别或 SMTP 服务器级别的拥塞,我看到以下消息:
SMTP 错误:无法连接到服务器:连接被拒绝 (111)
SMTP 错误:无法连接到服务器:连接超时
然后:SMTP connect() 失败。
由于与 SMTP 服务器的初始连接远离托管 PHPMailer 脚本的 Web 服务器,这意味着我不能依赖 SMTP 服务器处理电子邮件排队和重试。
我已经输入了一些重试 $email-> 发送命令的基本代码,但到目前为止,当 SMTP 连接失败时,它从未成功通过。
我正在寻求有关如何处理(在 PHPMailer 中)这些暂时性错误的建议?
非常感谢。
我的服务器 PHP 脚本(提取):
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require ($_SERVER['DOCUMENT_ROOT'] . '/vendor/phpmailer/phpmailer/src/Exception.php');
require ($_SERVER['DOCUMENT_ROOT'] . '/vendor/phpmailer/phpmailer/src/PHPMailer.php');
require ($_SERVER['DOCUMENT_ROOT'] . '/vendor/phpmailer/phpmailer/src/SMTP.php');
// Load Composer's autoloader
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';
$email = new PHPMailer(true);//True means Throw errors
try {
//Server settings
$email->SMTPDebug = SMTP::DEBUG_CONNECTION;
$debug = '';
$email->Debugoutput = function($str, $level) {
$GLOBALS['debug'] .= "$level: $str\n";
};
$email->isSMTP(); // Set mailer to use SMTP
$email->CharSet = 'UTF-8'; //not important
$email->Host = 'smtp.office365.com'; // Specify main and backup SMTP servers
$email->SMTPAuth = true; // Enable SMTP authentication
$email->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$email->Port = 587; // TCP port to connect to
//Authentication
$email->Username = ‘Myusername’; // SMTP username
$email->Password = 'mypassword'; // SMTP password - must be App Password from Microsoftt
//Recipients
$email->SetFrom(‘MySenderemail’);
$email->addReplyto(‘Myreplytoemail’, 'No-Reply');
$email->addAddress( ‘MyTargetemailaddress’);
// Content
$email->isHTML(true);
$email->Subject = $mailsubject;
$email->Body = $messagebody;
$email->AltBody = 'This email can only be viewed in HTML. Please contact the SSN IT Coordinator.';
//Send the email
$email->send();
elog($ModuleName . '|' . $authentic . ': ' . 'Mail Sent Successfully ' . ' ' . $mailsubject);
echo($ModuleName . '|' . $authentic . ': ' . 'Mail Sent Successfully ' . ' ' . $mailsubject);
return true;
} catch (Exception $e) {
error_log($email->ErrorInfo);
error_log($debug);
if (strpos($email->ErrorInfo, 'SMTP connect() failed') !== false) {
// Retry sending the email in case it was a transient error
error_log ($ModuleName . '|' . $authentic . ': ' . 'First attempt at email failed, retrying: ' . $email->ErrorInfo . ' ' . $mailsubject);
try {$email->send();} catch (exception $e){
//Failed second time so send error
http_response_code(500);
if (!headers_sent()) {header('HTTP/1.1 500 Internal Server Error');}
elog($ModuleName . '|' . $authentic . ': ' . 'Retry Mail not sent ' . $mailsubject . $authentic . $e->getMessage());
die($ModuleName . '|' . $authentic . ': ' . 'Retry Mail not sent ' . $mailsubject . $authentic . $e->getMessage());
}
} else {
//Some error other than SMTP Connect failed so return it.
http_response_code(500);
if (!headers_sent()) {header('HTTP/1.1 500 Internal Server Error');}
error_log ($ModuleName . '|' . $authentic . ': ' . 'Mail NOT SENT ' . $mailsubject . $authentic . $e->getMessage());
die($ModuleName . '|' . $authentic . ': ' . 'Mail NOT SENT ' . $mailsubject . $authentic . $e->getMessage());
}
}
您的连接困难似乎有时间因素,因此立即重试不太可能比第一次成功。我推荐的方法也是 PHPMailer 文档推荐的方法:安装本地邮件服务器并通过它进行中继。它将管理排队、重试、指数退避和退回,您的发送脚本将 运行 快得多。这比尝试在 PHP 中编写邮件服务器要有效和可靠得多,这正是您正在尝试做的。
旁注:由于您使用的是 Composer,因此可以删除 PHPMailer 类 的 require
行; composer 的自动加载器会自动为你加载 类。
我搜索了 Whosebug 和 PHPMailer 问题,但没有成功。有很多永久性 PHPMailer SMTP 连接错误,但 none 我可以在瞬态或间歇性错误中看到。
我正在使用 PHPMailer (6.2) 和 PHP 8.0 从我的远程 Web 服务器向 smtp.office365.com(Microsoft Exchange Online 服务)发送电子邮件。大多数时候它工作正常。
间歇性地,我怀疑是由于网络级别或 SMTP 服务器级别的拥塞,我看到以下消息:
SMTP 错误:无法连接到服务器:连接被拒绝 (111)
SMTP 错误:无法连接到服务器:连接超时
然后:SMTP connect() 失败。
由于与 SMTP 服务器的初始连接远离托管 PHPMailer 脚本的 Web 服务器,这意味着我不能依赖 SMTP 服务器处理电子邮件排队和重试。
我已经输入了一些重试 $email-> 发送命令的基本代码,但到目前为止,当 SMTP 连接失败时,它从未成功通过。
我正在寻求有关如何处理(在 PHPMailer 中)这些暂时性错误的建议?
非常感谢。
我的服务器 PHP 脚本(提取):
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require ($_SERVER['DOCUMENT_ROOT'] . '/vendor/phpmailer/phpmailer/src/Exception.php');
require ($_SERVER['DOCUMENT_ROOT'] . '/vendor/phpmailer/phpmailer/src/PHPMailer.php');
require ($_SERVER['DOCUMENT_ROOT'] . '/vendor/phpmailer/phpmailer/src/SMTP.php');
// Load Composer's autoloader
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';
$email = new PHPMailer(true);//True means Throw errors
try {
//Server settings
$email->SMTPDebug = SMTP::DEBUG_CONNECTION;
$debug = '';
$email->Debugoutput = function($str, $level) {
$GLOBALS['debug'] .= "$level: $str\n";
};
$email->isSMTP(); // Set mailer to use SMTP
$email->CharSet = 'UTF-8'; //not important
$email->Host = 'smtp.office365.com'; // Specify main and backup SMTP servers
$email->SMTPAuth = true; // Enable SMTP authentication
$email->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$email->Port = 587; // TCP port to connect to
//Authentication
$email->Username = ‘Myusername’; // SMTP username
$email->Password = 'mypassword'; // SMTP password - must be App Password from Microsoftt
//Recipients
$email->SetFrom(‘MySenderemail’);
$email->addReplyto(‘Myreplytoemail’, 'No-Reply');
$email->addAddress( ‘MyTargetemailaddress’);
// Content
$email->isHTML(true);
$email->Subject = $mailsubject;
$email->Body = $messagebody;
$email->AltBody = 'This email can only be viewed in HTML. Please contact the SSN IT Coordinator.';
//Send the email
$email->send();
elog($ModuleName . '|' . $authentic . ': ' . 'Mail Sent Successfully ' . ' ' . $mailsubject);
echo($ModuleName . '|' . $authentic . ': ' . 'Mail Sent Successfully ' . ' ' . $mailsubject);
return true;
} catch (Exception $e) {
error_log($email->ErrorInfo);
error_log($debug);
if (strpos($email->ErrorInfo, 'SMTP connect() failed') !== false) {
// Retry sending the email in case it was a transient error
error_log ($ModuleName . '|' . $authentic . ': ' . 'First attempt at email failed, retrying: ' . $email->ErrorInfo . ' ' . $mailsubject);
try {$email->send();} catch (exception $e){
//Failed second time so send error
http_response_code(500);
if (!headers_sent()) {header('HTTP/1.1 500 Internal Server Error');}
elog($ModuleName . '|' . $authentic . ': ' . 'Retry Mail not sent ' . $mailsubject . $authentic . $e->getMessage());
die($ModuleName . '|' . $authentic . ': ' . 'Retry Mail not sent ' . $mailsubject . $authentic . $e->getMessage());
}
} else {
//Some error other than SMTP Connect failed so return it.
http_response_code(500);
if (!headers_sent()) {header('HTTP/1.1 500 Internal Server Error');}
error_log ($ModuleName . '|' . $authentic . ': ' . 'Mail NOT SENT ' . $mailsubject . $authentic . $e->getMessage());
die($ModuleName . '|' . $authentic . ': ' . 'Mail NOT SENT ' . $mailsubject . $authentic . $e->getMessage());
}
}
您的连接困难似乎有时间因素,因此立即重试不太可能比第一次成功。我推荐的方法也是 PHPMailer 文档推荐的方法:安装本地邮件服务器并通过它进行中继。它将管理排队、重试、指数退避和退回,您的发送脚本将 运行 快得多。这比尝试在 PHP 中编写邮件服务器要有效和可靠得多,这正是您正在尝试做的。
旁注:由于您使用的是 Composer,因此可以删除 PHPMailer 类 的 require
行; composer 的自动加载器会自动为你加载 类。