Symfony:记录 Mailer 创建的所有邮件

Symfony: Logging all Mails created by Mailer

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

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

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

我现在的问题是:

顺便说一句,我目前的订阅者代码:

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

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

谢谢。

我的问题的答案是:目前您无法订阅 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 个月。

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