Подтвердить что ты не робот

Silex SwiftMailer не выполняет подключение SMTP после выполнения

Я делаю консольное приложение, использующее расширение SwiftMail для отправки. Из-за нашей политики у меня есть две виртуальные машины, одна из которых служит ретранслятором SMTP, а другая - сервером приложений. Отправка почты вручную через telnet на реле работает нормально. При использовании SwiftMail он сломан.

Заголовки возвращаются и нет записей, возвращаемых в переменной $failure для 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.

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 на сервере приложений и запускаю script, никакого SMTP-соединения не производится, и ошибок не возникает.

Кто-нибудь сталкивался с этим раньше? Я не хочу использовать sendmail или почту, но SMTP из-за требований наших приложений.

4b9b3361

Ответ 1

Это связано с тем, что по умолчанию 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, чтобы очистить буфер памяти после того, как страница была отображена. Он сбрасывает его в службу 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']);
    });
    

Любое решение должно быть выполнено. Удачи!