【问题标题】:Symfony: Logging all Mails created by MailerSymfony:记录 Mailer 创建的所有邮件
【发布时间】:2020-02-06 14:54:26
【问题描述】:

出于各种原因,我希望/需要记录通过我在 Symfony 5 上运行的网站发送的所有电子邮件。

到目前为止,我所拥有的是一个订阅者,它在创建 MessageEvent 类时创建了一个 EmailLogEntry 类型的实体(至少这是我从 (MessageEvent::class) 中理解的——如果我错了,请纠正我)。我还使用此订阅者使用默认系统地址填写缺少的电子邮件地址。

现在,发送电子邮件后,我想调整我的实体并致电$email->setSent(true);,但我不知道如何订阅尝试发送电子邮件的事件。为了代码的可重用性,我不想在服务中这样做(是的,它是多个,因为有多个生成邮件的源)我实际上调用$this->mailer->send($email);

我现在的问题是:

  • 谁能告诉我如何订阅 Mailers send 事件?
  • 一般而言,我如何确定可以订阅哪些事件?文档中列出了内核事件,但触发的所有其他事件呢?

顺便说一句,我现在的订阅者代码:

class SendMailSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                MessageEvent::class => [
                    ['onMessage', 255],
                    ['logMessage', 0],
                ],
            ];
        }

        public function logMessage(MessageEvent $event) {
            $email = new EmailLogEntry();
            [...]
        }
    }

谢谢。

【问题讨论】:

  • stackoverflow.com/questions/18033210/… 中的想法非常类似于您的用例。你应该能够适应它。你也应该避免一次问太多问题。对于事件,请查看bin/console debug:event* 命令
  • 不幸的是,该链接适用于 SwiftMailer,而我正在使用 Symfony 的原生新 Mailer。 SwiftMailer 有更多选项可以帮助我解决我的问题...
  • 这正是我说“适应它”的原因,因为尽管 Symfony Mailer 与 SwiftMailer 并不完全相同,但我相信它大体上是相同的,因为您可以使用装饰模式来包装它。特别是如果您总是使用 MailerInterface 而不是 Mailer 类型提示。实现起来也很宽容,因为Mailer只有一个功能来装饰(发送)。此外,装饰是正确的方法。供参考见github.com/symfony/mailer/blob/master/Mailer.php(如有必要,可以阅读装饰)
  • MessageEvent 的使用条款是否正确?这可能是它不起作用的原因。
  • @Jakumi:好的,我得看看装饰图案的问题——这是我第一次听说。这是我的第一个基于 Symfony 的项目,到目前为止,我正在通过教程或类似问题进行学习。关于使用条款:不,我没有。我找到了关于use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Event\MessageEvents; 的信息,但这就是我通过阅读Mailer 代码文件所能找到的全部内容。 EventListener 文件夹中的所有类也订阅MessageEvent::class 并使用MessageEvent

标签: symfony mailer subscriber


【解决方案1】:

我的问题的答案是:目前不能订阅Mailer的send()事件。

作为一种解决方法,这是我现在的代码: 这是我的 Mailer 服务的摘录。

// send email and log the whole message
private function logSendEmail($email) {
    $log = new EmailLog();

    // sender
    $log->setSender(($email->getFrom()[0]->getName() ?:"")." <".$email->getFrom()[0]->getAddress().">");

    // get recipient list
    foreach($email->getTo() AS $to) {
        $recipient[] = "To: ".$to->getName()." <".$to->getAddress().">";
    }
    foreach($email->getCc() AS $cc) {
        $recipient[] = "CC: ".$cc->getName()." <".$cc->getAddress().">";
    }
    foreach($email->getBcc() AS $bcc) {
        $recipient[] = "Bcc: ".$bcc->getName()." <".$bcc->getAddress().">";
    }
    $log->setRecipient(implode(";",$recipient));

    // other message data
    $log->setSubject($email->getSubject());
    $log->setMessage(serialize($email->__serialize()));
    $log->setMessageTime(new \DateTime("now"));
    $log->setSent(0); // set Sent to 0 since mail has not been sent yet

    // try to send email
    try {
        $this->mailer->send($email);
        $log->setSent(1);   // set sent to 1 if mail was sent successfully
    }

//      catch(Exception $e) {
//          to be determined
//      }

    // and finally persist entity to database
    finally {
        $this->em->persist($log);
        $this->em->flush();
    }
}

EmailLog 是我创建的一个实体。当我分别保存发件人、收件人和主题时,有一点悬念。但是,为了遵守消费者数据保护,我计划在 30 天后自动清除消息字段,同时保留其他字段 6 个月。

到目前为止,我也没有使用订阅者,主要是因为网站访问者可以请求消息副本,而我也对记录它不感兴趣。另外,由于我想生成可重用的代码,我可能在某些时候会遇到邮件可能包含个人消息的问题,我当然不想记录这些邮件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    相关资源
    最近更新 更多