如何在Symfony Mailer发送邮件后获取所使用的传输方式?
如何获取Symfony Mailer中Failover传输实际使用的子传输
当你用Symfony Mailer的Failover传输时,默认的SentMessageEvent里没法直接拿到实际生效的子传输,试试下面这两种方法:
方法1:通过事件监听器获取Failover的最后使用传输
Symfony的FailoverTransport类自带getLastUsedTransport()方法,能直接拿到最后成功发送邮件的子传输。写个事件监听器就能搞定:
先创建监听器类:
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Mailer\Event\SentMessageEvent; use Symfony\Component\Mailer\Transport\FailoverTransport; class MailTransportLogger implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ SentMessageEvent::class => 'logTransport', ]; } public function logTransport(SentMessageEvent $event): void { $transport = $event->getTransport(); if ($transport instanceof FailoverTransport) { $actualTransport = $transport->getLastUsedTransport(); // 这里可以把传输信息存日志或者做其他处理 // 比如拿类名:$actualTransport::class // 如果需要DSN,要是传输实现了DsnAwareInterface,还能调用getDsn() error_log("Failover实际用了: " . $actualTransport::class); } else { // 非Failover传输直接拿信息 error_log("用了传输: " . $transport::class); } } }
然后在services.yaml里注册这个监听器:
services: App\EventSubscriber\MailTransportLogger: tags: - { name: kernel.event_subscriber }
方法2:自定义Failover传输,给消息加标记
要是你想把实际传输信息直接加到邮件头里,可以自定义一个Failover传输的子类:
use Symfony\Component\Mailer\Transport\FailoverTransport; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mime\RawMessage; use Symfony\Component\Mailer\Envelope; class TrackableFailoverTransport extends FailoverTransport { public function send(RawMessage $message, Envelope $envelope = null): SentMessage { $sentMessage = parent::send($message, $envelope); $actualTransport = $this->getLastUsedTransport(); // 给原始消息加个自定义头,后续就能从消息里拿到 $sentMessage->getOriginalMessage()->getHeaders()->addTextHeader('X-Used-Transport', $actualTransport::class); return $sentMessage; } }
之后需要替换Symfony默认的FailoverTransport,这一步需要自定义传输工厂,适合需要在邮件里直接带上传输信息的场景。
注意点
- 只有当传输是
FailoverTransport实例时,才能调用getLastUsedTransport(),所以记得先做类型判断。 - 只要你的Failover DSN是用
failover(...)格式定义的,Symfony就会自动用FailoverTransport,上面的方法都适用。 - 普通传输直接从
SentMessageEvent的getTransport()就能拿到对应对象,获取类名或者DSN都没问题。
内容的提问来源于stack exchange,提问作者OVG
相关产品推荐
相关产品推荐

