Swift Mailer 递送状态
Posted
技术标签:
【中文标题】Swift Mailer 递送状态【英文标题】:Swift Mailer Delivery Status 【发布时间】:2011-08-11 17:19:52 【问题描述】:有谁知道 SwiftMailer 发送函数是否返回传递状态?我希望能够知道电子邮件已送达或未送达。这可能吗?
谢谢
【问题讨论】:
swiftmailer.org/docs/failures-byreference 上面的链接已经失效了,所以这里是新的更新链接:swiftmailer.org/docs/sending.html#getting-failures-by-reference 【参考方案1】:SwiftMailer 支持至少三层检查,将报告几种类型的传递失败。
1) 始终检查 SwiftMailer 的 send() 或 batchSend() 命令的返回码是否有非零结果。来自the documentation:
//Send the message
$numSent = $mailer->send($message);
printf("Sent %d messages\n", $numSent);
/* Note that often that only the boolean equivalent of the
return value is of concern (zero indicates FALSE)
if ($mailer->send($message))
echo "Sent\n";
else
echo "Failed\n";
2) 使用failures-by-reference feature 了解特定地址是否被拒绝或无法完成:
//Pass a variable name to the send() method
if (!$mailer->send($message, $failures))
echo "Failures:";
print_r($failures);
/*
Failures:
Array (
0 => receiver@bad-domain.org,
1 => other-receiver@bad-domain.org
)
*/
3) 在某些情况下,您可能还需要enable return receipts,这会确认电子邮件阅读器显示了该消息。它们通常被用户或其电子邮件应用程序禁用或忽略,但如果您收到收据,则具有高度确认性。另请注意,这可能会在发送后很多天发生,因此它不是像上面两个那样的实时同步测试。
$message->setReadReceiptTo('your@address.tld');
但是,由于 SMTP 传递涉及到如此多的变量和系统层,因此通常不可能绝对确定邮件是否已传递。您能做的最好的事情是确保您使用上面的前两项检查。如果您将自己的服务器用于 SMTP 服务,那么您还需要像 Marc B 提到的那样监视您的日志和队列。
另一个例子强调需要熟悉您使用的任何底层电子邮件系统。我刚刚开始使用 John Hobbs 为 Amazon Web Services SES 编写的 Swift_AWSTransport。 SES 能够为通过它发送的每条消息返回带有诊断信息的 XML 响应。尽管 SwiftMailer 本身并不了解如何使用该 XML 响应,但我发现它对于解决交付问题非常宝贵。我提到它是因为我发现在某些情况下,上面的检查 #1 和 #2 对 SwiftMailer 来说似乎是成功的,但 SES 不喜欢我的邮件格式。因此,我正在考虑解析该 XML 作为附加检查。
【讨论】:
这个答案确实帮助我快速解决了与发件人地址不符合我服务器上的设置值相关的问题。感谢您以合乎逻辑的方式进行彻底的回答。【参考方案2】:相当老的帖子,但从 Swiftmailer 4+ 开始,除了从 send
方法调用中获取 result
状态。如果您想调试您的邮件程序并查看传输过程中发生的情况,您可以使用 Logger 插件,甚至创建自己的插件。
https://swiftmailer.symfony.com/docs/plugins.html
$mailer = \Swift_Mailer::newInstance(
\Swift_SmtpTransport::newInstance('tls://smtp.gmail.com', 465)
);
$logger = new \Swift_Plugins_Loggers_ArrayLogger;
//$logger = new \Swift_Plugins_Loggers_EchoLogger; //echo messages in real-time
$mailer->registerPlugin(new \Swift_Plugins_LoggerPlugin($logger));
foreach ($recipients as $recipient)
//...
$mailer->send(/*...*/);
echo $logger->dump(); //not needed if using EchoLogger plugin
将为每个send
调用输出传输消息,看起来像
++ Starting Swift_SmtpTransport
<< 220 smtp.gmail.com ESMTP x12sm4143221vkc.19 - gsmtp
>> EHLO server.example.com
<< 250-smtp.gmail.com at your service, [192.168.1.1] 250-SIZE 35882577 250-8BITMIME 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-CHUNKING 250 SMTPUTF8
>> AUTH LOGIN
<< 334 AbcDefGhIjKlMnop
>> AbcDefGhIjKlMnop==
<< 334 AbcDefGhIjKlMnop
>> AbcDefGhIjKlMnop==
<< 235 2.7.0 Accepted
++ Swift_SmtpTransport started
>> MAIL FROM:
<< 250 2.1.0 OK x12sm4143221vkc.19 - gsmtp
>> RCPT TO:<recipient@example.com>
<< 250 2.1.5 OK x12sm4143221vkc.19 - gsmtp
>> DATA
<< 354 Go ahead x12sm4143221vkc.19 - gsmtp
>> .
<< 250 2.0.0 OK 1468948643 x12sm4143221vkc.19 - gsmtp
【讨论】:
【参考方案3】:Swiftmailer 与邮件的实际投递无关。它只是将事情交给您指定的任何 SMTP 服务器,而正是该服务器负责交付。您需要检查 SMTP 服务器的日志以了解邮件发生了什么。它可能会因为服务器被淹没而卡在传出队列中。它可能会卡在队列中,因为接收端无法访问或正在使用灰名单等...一旦 SMTP 服务器确认邮件已排队,Swiftmailer 的工作就会结束。
【讨论】:
如果我发送的消息没有排队,swiftmailer 会通知我吗?还是无法访问 smtp 服务器?它会返回错误字符串吗? 它仍然没有说明为什么它失败了。它不能到达服务器吗?授权被拒绝了吗?是否需要 SSL/TLS 但未使用?等等……以上是关于Swift Mailer 递送状态的主要内容,如果未能解决你的问题,请参考以下文章
尝试使用 swift mailer、gmail smtp、php 发送邮件
Symfony 4.4 - Swift Mailer 安装失败
使用 Swift Mailer、GMail 和 PHP 发送电子邮件,权限被拒绝错误
使用Mailgun服务提供商在Google Cloud上使用Swift Mailer发送电子邮件
通过 Microsoft 365 SMTP 发送电子邮件时如何使用自定义显示名称? (以 PHP Swift Mailer 为例)