在symfony2中记录swiftmailer send()活动

时间:2013-08-03 13:12:03

标签: php symfony logging swiftmailer symfony-2.2

我使用swiftmailer从我的symfony2.2项目发送邮件。有没有办法记录全球所有电子邮件信息并发送结果?

如果邮件程序send()方法有触发somę事件会很好,但我看不到它。

5 个答案:

答案 0 :(得分:15)

这个问题已经回答了,这个解决方案对于Symfony 4与Monolog的结合更好。它基于umpirsky他的答案。但没有自定义文件记录器的开销。

注意:日志将放在./var/logs /...

应用\的Util \ MailLoggerUtil.php

<?php

namespace App\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)
    : void
    {
        // ...
    }

    /**
     * @param Swift_Events_SendEvent $evt
     */
    public function sendPerformed(Swift_Events_SendEvent $evt)
    : void
    {
        $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.yaml

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

如果您希望邮件程序日志位于另一个频道,请添加以下内容:

dev / monolog.yaml(可选)

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

答案 1 :(得分:8)

服务:

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));
    }
}

配置:

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

答案 2 :(得分:5)

我是这样做的:

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 $transportlink)。如果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); } } ...

,则代码会更好
// /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
    }
}

3。捆绑构建器

OverrideServiceSwiftMailer

4。并// /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 - i.e. event_dispatcher */ } }

{{1}}

答案 3 :(得分:2)

将以下内容添加到配置的“services”部分将打印与stdout传输的交互(如果您使用控制台命令进行调试,这可能很有用,例如'swiftmailer:email:send'或'swiftmailer :线轴:发送'):

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

答案 4 :(得分:1)

您可以使用自己的自定义邮件程序类包装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
    }
}