11

我正在制作一个使用 SwiftMail 扩展发送的控制台应用程序。由于我们的政策,我有两台虚拟机,一台用作 SMTP 中继,另一台用作应用程序服务器。通过 telnet 手动将邮件发送到中继可以正常工作。使用 SwiftMail 时,它已损坏。

$failure返回标头,并且在变量中没有返回条目send()

的回应getHeaders()->toString()

Message-ID: <1351104631.508838778dc03@swift.generated>
Date: Wed, 24 Oct 2012 14:50:31 -0400
Subject: [YourSite] Feedback
From: noreply@localhost.com
To: sixeightzero@localhost.com
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

如果我回应send(),我得到1

引导.php

$app->register(new Silex\Provider\SwiftmailerServiceProvider(), array(
    'swiftmailer.options' => array(
        'host' => 'ip.host.relay',
        'port' => 25,
        'encryption' => null,
        'auth_mode' => null
    ),
));

应用程序.php

 $message = \Swift_Message::newInstance( )
        ->setSubject('[YourSite] Feedback')
        ->setFrom(array('noreply@localhost.com'))
        ->setTo(array('sixeightzero@localhost.com'))
        ->setBody("Message!");


    $app['mailer']->send($message, $failures);

当我在应用服务器上运行 TCP 转储并运行脚本时,没有建立 SMTP 连接,也没有抛出错误。

有人遇到过这种情况吗?由于我们的应用程序要求,我不想使用 sendmail 或邮件,而是使用 SMTP。

4

1 回答 1

41

这是因为默认情况下SwiftmailerServiceProvider使用 a Swift_MemorySpool,并且只刷新 on kernel.terminate。让我退后一步,解释一下每个部分。

  • SwiftmailerServiceProvider负责注册 Swiftmailer 服务和默认配置。默认情况下,transport( swiftmailer.spooltransport) isSwift_SpoolTransportswiftmailer.spoolis Swift_MemorySpool

  • Swiftmailer 支持不同的邮件发送方式。这些被称为传输。假脱机传输充当队列。您可以将此队列存储在文件中或内存中。假脱机传输有一种flushQueue方法允许将排队的邮件刷新到一个真正的传输,它应该传递它们。

  • Silex 使用的 Symfony2 HttpKernel 在每个请求的生命周期中都会发出许多事件。它发出的最后一个是kernel.terminate事件。在发送 HTTP 响应正文后触发此事件。这允许您在呈现页面后执行繁重的任务,以便它不再显示为正在加载给用户。

  • SwiftmailerServiceProvider订阅kernel.terminate事件是为了在页面呈现后刷新内存假脱机。它将它刷新到swiftmailer.transport服务,这是一个Swift_Transport_EsmtpTransport通过 SMTP 进行实际发送的服务。

那么让我们来看看实际的问题。您处于 CLI 上下文中,因此不会触发这些 HttpKernel 事件。并且由于kernel.terminate没有触发事件,因此您的线轴没有被刷新。因此,您的电子邮件没有被发送。

有两个很好的解决方案:

  • A) 手动冲洗阀芯。只需执行提供程序在其侦听器中执行的操作即可。在 CLI 命令的末尾添加:

    if ($app['mailer.initialized']) {
        $app['swiftmailer.spooltransport']->getSpool()->flushQueue($app['swiftmailer.transport']);
    }
    
  • B) 重新配置mailer服务以直接使用 ESMTP 传输而不通过假脱机:

    $app['mailer'] = $app->share(function ($app) {
        return new \Swift_Mailer($app['swiftmailer.transport']);
    });
    

任何一种解决方案都应该这样做。祝你好运!

于 2012-10-25T02:48:21.310 回答