Ведение журнала swiftmailer send () в symfony2

Я использую swiftmailer для отправки писем из моего проекта symfony2.2. Есть ли способ зарегистрировать глобальную информацию по электронной почте и отправить результаты?

Было бы здорово, если метод sendmail send () запускает событие somę, но я не вижу его.

    Обслуживание:

    class MessageFileLogger implements Swift_Events_SendListener { private $filename; public function __construct($filename) { $this->filename = $filename; } public function getMessages() { return $this->read(); } public function clear() { $this->write(array()); } public function beforeSendPerformed(Swift_Events_SendEvent $evt) { $messages = $this->read(); $messages[] = clone $evt->getMessage(); $this->write($messages); } public function sendPerformed(Swift_Events_SendEvent $evt) { } private function read() { if (!file_exists($this->filename)) { return array(); } return (array) unserialize(file_get_contents($this->filename)); } private function write(array $messages) { file_put_contents($this->filename, serialize($messages)); } } 

    Config:

     services: umpirsky.mailer.message_file_logger: class: MessageFileLogger arguments: - %kernel.logs_dir%/mailer.log tags: - { name: swiftmailer.plugin } 

    На этот вопрос уже был дан ответ. Это решение лучше для Symfony 3 в сочетании с Monolog. Он основан на уппирском ответе. Но без накладных расходов пользовательского регистратора файлов.

    Примечание. Журналы будут помещены в ./var/logs / …

    AppBundle \ Util \ MailerLoggerUtil.php

     <?php namespace AppBundle\Util; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Swift_Events_SendEvent; use Swift_Events_SendListener; class MailerLoggerUtil implements Swift_Events_SendListener { protected $logger; /** * MailerLoggerUtil constructor. * * @param LoggerInterface $logger */ public function __construct(LoggerInterface $logger) { $this->logger = $logger; } /** * @param Swift_Events_SendEvent $evt */ public function beforeSendPerformed(Swift_Events_SendEvent $evt) { // ... } /** * @param Swift_Events_SendEvent $evt */ public function sendPerformed(Swift_Events_SendEvent $evt) { $level = $this->getLogLevel($evt); $message = $evt->getMessage(); $this->logger->log( $level, $message->getSubject().' - '.$message->getId(), [ 'result' => $evt->getResult(), 'subject' => $message->getSubject(), 'to' => $message->getTo(), 'cc' => $message->getCc(), 'bcc' => $message->getBcc(), ] ); } /** * @param Swift_Events_SendEvent $evt * * @return string */ private function getLogLevel(Swift_Events_SendEvent $evt): string { switch ($evt->getResult()) { // Sending has yet to occur case Swift_Events_SendEvent::RESULT_PENDING: return LogLevel::DEBUG; // Email is spooled, ready to be sent case Swift_Events_SendEvent::RESULT_SPOOLED: return LogLevel::DEBUG; // Sending failed default: case Swift_Events_SendEvent::RESULT_FAILED: return LogLevel::CRITICAL; // Sending worked, but there were some failures case Swift_Events_SendEvent::RESULT_TENTATIVE: return LogLevel::ERROR; // Sending was successful case Swift_Events_SendEvent::RESULT_SUCCESS: return LogLevel::INFO; } } } 

    services.yml

     AppBundle\Util\MailerLoggerUtil: arguments: ["@logger"] tags: - { name: monolog.logger, channel: mailer } - { name: "swiftmailer.default.plugin" } 

    Если вы хотите, чтобы журналы почтовых отправлений находились в другом канале, добавьте следующее:

    config.yml (необязательно)

     monolog: handlers: mailer: level: debug type: stream path: '%kernel.logs_dir%/mailer.%kernel.environment%.log' channels: [mailer] 

    Я сделал это так:

    1. Моя сервисная конфигурация

     # /src/Tiriana/MyBundle/Resources/config/services.yml parameters: swiftmailer.class: Tiriana\MyBundle\Util\MailerWrapper 

    2. Служба почтовой службы

    Он расширяет Swift_Mailer , потому что он передается в разные классы, ожидая, что почтовая программа будет экземпляром Swift_Mailer . И он создает экземпляр Swift_Mailer как поле, потому что … $transport является private в \Swith_Mailer ( ссылка ). Код был бы намного лучше, если бы $transport был protected

     // /src/Tiriana/MyBundle/Util/MailerWrapper.php namespace Tiriana\MyBundle\Util; use Monolog\Logger; use Monolog\Handler\StreamHandler; class MailerWrapper extends \Swift_Mailer { private $_logger; /** @var \Swift_Mailer */ private $_mailer; public function send(\Swift_Mime_Message $message, &$failedRecipients = null) { $this->_log('BEFORE SEND'); // <-- add your logic here $ret = $this->_mailer->send($message, $failedRecipients); $this->_log('AFTER SEND'); // <-- add your logic here return $ret; } /** @return Logger */ public function getLogger() { return $this->_logger; } protected function _log($msg) { $this->getLogger()->debug(__CLASS__ . ": " . $msg); } public function __construct(\Swift_Transport $transport, Logger $logger) { /* we need _mailer because _transport is private (not protected) in Swift_Mailer, unfortunately... */ $this->_mailer = parent::newInstance($transport); $this->_logger = $logger; } public static function newInstance(\Swift_Transport $transport) { return new self($transport); } public function getTransport() { return $this->_mailer->getTransport(); } public function registerPlugin(Swift_Events_EventListener $plugin) { $this->getTransport()->registerPlugin($plugin); } } 

    3. Строитель пакетов

     // /src/Tiriana/MyBundle/TirianaMyBundle.php namespace Tiriana\MyBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Tiriana\MyBundle\DependencyInjection\Compiler\OverrideServiceSwiftMailer; class TirianaMyBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new OverrideServiceSwiftMailer()); // <-- ADD THIS LINE } } 

    4. И класс OverrideServiceSwiftMailer

     // /src/Tiriana/MyBundle/DependencyInjection/Compiler/OverrideServiceSwiftMailer.php namespace Tiriana\MyBundle\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; class OverrideServiceSwiftMailer implements CompilerPassInterface { public function process(ContainerBuilder $container) { /* @var $definition \Symfony\Component\DependencyInjection\DefinitionDecorator */ $definition = $container->findDefinition('mailer'); $definition->addArgument(new Reference('logger')); /* add more dependencies if you need - ie event_dispatcher */ } } 

    Вы можете обернуть SwiftMailer своим собственным классом почтовой программы. Подобно,

     class MyMailer { /** * @var \Swift_Mailer */ private $mailer; /** * Mail the specified mailable using swift mailer. * * @param SwiftMessage $swiftMessage */ public function mail(\SwiftMessage $swiftMessage) { // PRESEND ACTIONS $sent = $this->mailer->send($swiftMessage); // POST SEND ACTIONS } } 

    Добавление следующего в раздел «службы» вашей конфигурации приведет к печати взаимодействия с транспортом в stdout (что может быть полезно, если вы отлаживаете с помощью команд консоли, например «swiftmailer: email: send» или «swiftmailer: spool: Отправить'):

     services: # (...) swiftmailer.plugins.loggerplugin: class: 'Swift_Plugins_LoggerPlugin' arguments: ['@swiftmailer.plugins.loggerplugin.logger'] tags: [{ name: 'swiftmailer.default.plugin' }] swiftmailer.plugins.loggerplugin.logger: class: 'Swift_Plugins_Loggers_EchoLogger' arguments: [false] 

    Пример вывода с использованием транспорта SMTP в localhost:

     $ app/console swiftmailer:email:send --subject="Test" --body="Yo! :)" --from="user@example.com" --to="user@example.com" ++ Starting Swift_Transport_EsmtpTransport << 220 example.com ESMTP Exim 4.86 Thu, 07 Jan 2016 13:57:43 +0000 >> EHLO [127.0.0.1] << 250-example.com Hello localhost [127.0.0.1] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING 250-AUTH PLAIN LOGIN 250-STARTTLS 250 HELP ++ Swift_Transport_EsmtpTransport started >> MAIL FROM: <user@example.com> << 250 OK >> RCPT TO: <user@example.com> << 451 Temporary local problem - please try later !! Expected response code 250/251/252 but got code "451", with message "451 Temporary local problem - please try later" >> RSET << 250 Reset OK Sent 0 emails ++ Stopping Swift_Transport_EsmtpTransport >> QUIT << 221 example.com closing connection ++ Swift_Transport_EsmtpTransport stopped