Я делаю консольное приложение, которое использует расширение 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
.
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('noreply@localhost.com')) ->setTo(array('sixeightzero@localhost.com')) ->setBody("Message!"); $app['mailer']->send($message, $failures);
Когда я запускаю дамп TCP на сервере приложений и запускаю скрипт, соединение с SMTP не производится, и ошибок не возникает.
Кто-нибудь сталкивался с этим раньше? Я не хочу использовать sendmail или почту, но SMTP из-за требований наших приложений.
Это связано с тем, что SwiftmailerServiceProvider
по умолчанию использует Swift_MemorySpool
и только сбрасывает его на kernel.terminate
. Позвольте мне сделать шаг назад и объяснить каждую часть этого.
SwiftmailerServiceProvider
отвечает за регистрацию служб Swiftmailer и конфигурации по умолчанию. По умолчанию транспорт ( swiftmailer.spooltransport
) – Swift_SpoolTransport
а swiftmailer.spool
– Swift_MemorySpool
.
Swiftmailer поддерживает различные способы отправки писем. Они называются транспортом. Транспортировка катушки действует как очередь. Вы можете сохранить эту очередь в файле или в памяти. Транспортировка катушек имеет метод flushQueue
который позволяет сбрасывать почтовые отправления в реальный транспорт, который должен их доставлять.
Symfony2 HttpKernel, который использует Silex, испускает ряд событий в течение жизненного цикла каждого запроса. Последним, который он испускает, является событие kernel.terminate
. Это событие запускается после отправки тела ответа HTTP. Это позволяет выполнять тяжелые задачи после рендеринга страницы, чтобы она больше не отображалась как загрузка пользователю.
SwiftmailerServiceProvider
подписывается на событие kernel.terminate
, чтобы очистить 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']); });
Любое решение должно делать. Удачи!