本文介绍了Silex SwiftMailer 在执行时不建立 SMTP 连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am making a console application which uses the SwiftMail extension to send. Due to our policy, I have two virtual machines, one which serves as a SMTP relay and the other which is the application server. Sending mail manually through telnet to the relay works fine. When using SwiftMail, it's broken.

返回标头,send()

getHeaders()->toString()

Message-ID: <[email protected]>
Date: Wed, 24 Oct 2012 14:50:31 -0400
Subject: [YourSite] Feedback
From: [email protected]
To: [email protected]
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

如果我回显 send(),我得到 1.

If I echo the send(), i get 1.

boot.php

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

app.php

 $message = \Swift_Message::newInstance( )
        ->setSubject('[YourSite] Feedback')
        ->setFrom(array('[email protected]'))
        ->setTo(array('[email protected]'))
        ->setBody("Message!");


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

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

When i run a TCP dump on the app server and run the script, there are no SMTP connection made, and there are no errors thrown.

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

Anyone encounter this before? I don't want to use sendmail or mail, but SMTP due to our application requirements.

推荐答案

这是因为 SwiftmailerServiceProvider 默认使用 Swift_MemorySpool,并且只在 上刷新内核.终止.让我退后一步解释这其中的每一部分.

This is because the SwiftmailerServiceProvider uses a Swift_MemorySpool by default, and only flushes that on kernel.terminate. Let me take a step back and explain each part of this.

  • SwiftmailerServiceProvider 负责注册 Swiftmailer 服务和默认配置.默认情况下,传输 (swiftmailer.spooltransport) 是 Swift_SpoolTransportswiftmailer.spoolSwift_MemorySpool.

  • The SwiftmailerServiceProvider is responsible for registering the Swiftmailer services and default configuration. By default the transport (swiftmailer.spooltransport) is Swift_SpoolTransport and the swiftmailer.spool is Swift_MemorySpool.

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

Swiftmailer supports different ways of sending the mails. These are called transports. The spool transport acts as a queue. You can either store this queue in a file or in memory. Spool transports have a flushQueue method which allows flushing the queued mails to a real transport, which should deliver them.

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

The Symfony2 HttpKernel which Silex uses emits a number of events during the lifecycle of every request. The last one that it emits is the kernel.terminate event. This event is triggered after the HTTP response body has been sent. This allows you to do heavy tasks after rendering the page, so that it no longer appears as loading to the user.

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

The SwiftmailerServiceProvider subscribes to the kernel.terminate event in order to flush the memory spool after the page has been rendered. It flushes it to swiftmailer.transport service, which is a Swift_Transport_EsmtpTransport that does the actual sending via SMTP.

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

So let's get to the actual problem. You are in a CLI context, so none of those HttpKernel events will be fired. And since the kernel.terminate event is not fired, your spool is not being flushed. And thus your emails are not getting sent.

对此有两个很好的解决方案:

There's two good solutions for this:

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

  • A) Flush the spool manually. Just do what the provider does in its listener. Add this at the end of your CLI command:

if ($app['mailer.initialized']) {
    $app['swiftmailer.spooltransport']->getSpool()->flushQueue($app['swiftmailer.transport']);
}

  • B) 重新配置 mailer 服务以直接使用 ESMTP 传输,而无需通过假脱机:

  • B) Re-configure the mailer service to use the ESMTP transport directly without going through the spool:

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

  • 两种解决方案都可以.祝你好运!

    Either solution should do. Good luck!

    这篇关于Silex SwiftMailer 在执行时不建立 SMTP 连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    09-16 06:28