【问题标题】:Symfony mailer: Swift_TransportException between message sendingSymfony 邮件程序:消息发送之间的 Swift_TransportException
【发布时间】:2026-02-12 20:10:02
【问题描述】:

在我目前正在工作的当前项目中,我有一个 symfony 任务,它运行一些向数据库插入大量数据并运行至少半小时。 当任务开始时,邮件通知被正确发送,问题是在任务执行时我们无法发送另一封邮件来通知处理结束。

邮件工厂当前配置了假脱机传递策略,但在这种特定情况下,我们希望使用 sendNextImmediately() 方法立即触发通知。

我遇到了异常:

[Swift_TransportException]
预期响应代码 250,但得到代码“451”,消息“451 4.4.2 超时 - 关闭连接。74sm1186065wem.17 "

以及 php 日志文件中的流动错误:

警告:fwrite(): SSL: Broken pipe in /var/www/project/lib/vendor/symfony/lib/vendor/swiftmailer/classes/Swift/Transport/StreamBuffer.php 在第 209 行

有人可以帮忙吗? 有什么方法可以刷新 symfony 邮件程序以建立新连接?

【问题讨论】:

  • 您能否显示您正在使用发送第二条消息的代码。您正在创建一个新的 swiftmailer 实例,对吗?
  • @Tom 每条消息的代码都非常相似: $message = $this->getMailer()->compose(); $message->setFrom(sfConfig::get('app_notifications_from_address'), sfConfig::get('app_notifications_from_address_name')); $message->setTo(sfConfig::get('app_notifications_to_error_support_address')); $message->setBody($html, 'text/html'); $this->getMailer()->sendNextImmediately()->send($message);我错过了什么吗?
  • 好的,看来您已经解决了。这或多或少是我所追求的……要么停止/启动,要么完全创建一个新实例。

标签: symfony1 swiftmailer


【解决方案1】:

做一个 Symfony2 项目,我也遇到了这个失败。我们使用了一个永久运行的 php 脚本,它产生了错误。

我们发现以下代码可以完成这项工作:

private function sendEmailMessage($renderedTemplate, $subject, $toEmail)
    {
        $mailer = $this->getContainer()->get('mailer');
        /* @var $mailer \Swift_Mailer */
        if(!$mailer->getTransport()->isStarted()){
            $mailer->getTransport()->start();
        }
        $sendException = null;
        /* @var $message \Swift_Message */
        $message = \Swift_Message::newInstance()
            ->setSubject($subject)
            ->setFrom($this->getContainer()->getParameter('email_from'))
            ->setTo($toEmail)
            ->setBody($renderedTemplate);


        $mailer->send($message);
        $mailer->getTransport()->stop();
        //throw $sendException;
    }

【讨论】:

  • 很棒的回复@stoefln。但是,这会对性能产生重大影响。如果保持连接,我可以发送1 email/2.4s,而如果我们每次使用您的脚本关闭连接,我可以发送1 email/5.1s。也许一个好主意是设置一个计时器。您是否知道连接超时需要多长时间,例如使用 gmail?
  • @Patt 你是对的。不幸的是,我不知道如何设置计时器:/我们切换到打开连接发送一堆电子邮件并在此之后关闭它。
  • 这是个好主意@stoefln。如果我们知道连接断开之前需要多长时间,那么计时器的想法是可行的,但看起来它取决于提供者。如果我发现任何好的东西,我会提出一个要点(你的回答为我节省了一些时间,非常感谢):)
【解决方案2】:

对于 Symfony1 用户

我的猜测是连接被保持太久(根本没有活动),导致 ssl 连接超时。

目前,可以通过停止 Swift_Transport 实例并在发送第二条消息之前再次显式启动它来解决问题。

代码如下:

$this->getMailer()->getRealtimeTransport()->stop();
$this->getMailer()->getRealtimeTransport()->start();
$this->getMailer()->sendNextImmediately()->send($message);

【讨论】:

    【解决方案3】:

    我遇到了完全相同的问题,上面的解决方案非常有帮助,但是我必须做不同的事情:订购。

    $this->getMailer()->sendNextImmediately()->send($message);
    $this->getMailer()->getRealtimeTransport()->stop();
    

    如果我在发送消息之前尝试停止传输,它对我不起作用(连接超时已经挂起)。此外,您不需要运行 getRealtimeTransport()->start() - 它会自动启动。

    【讨论】: