如何在 Symfony 5 中同时发送同步与异步邮件

本教程详细介绍了如何在 symfony 5 应用中灵活地同时实现同步和异步邮件发送。通过创建自定义信使消息和处理程序,并精确配置信使路由,开发者可以区分处理不同场景下的邮件发送需求。文章内容涵盖了消息类、处理程序、信使配置在服务中调度邮件的完整实现,旨在提供一个结构清晰、易于理解的解决方案,避免了默认配置以及导致所有邮件都被异步处理的问题。
在现代 Web 应用中,邮件发送是常见的需求,而邮件根据重要性和时效性,可能需要同步发送(即时响应)或异步发送(后台处理,不阻止用户请求)。Symfony 框架通过其 Mailer 和 Messenger 组件提供了强大的邮件处理能力。 Messenger 配置可能导致所有通过 MailerInterface::send() 发送的邮件都被路由到异步队列。本教程将指导您如何配置 Symfony 5 应用,以实现对邮件发送模式的精细控制。理解 Symfony Mailer 与 Messenger 的行为
当 Symfony 的 Messenger 与组件 Mailer 组件集成时,MailerInterface::send() 方法实际上会创建 Symfony\Component\Mailer\Messenger\SendEmailMessage 类型的消息,并将其调度到 Messenger 消息转发。如果在 Framework.messenger.routing 配置中的消息类型路由到异步传输,那么所有通过一个 MailerInterface::send()发送的邮件都将自动处理。
为了实现同步和异步邮件的共存,我们需要避免将 Symfony\Component\Mailer\Messenger\SendEmailMessage相反,我们要实现异步邮件创建一个自定义的消息类型和处理程序,并只将这个自定义消息类型路由到异步传输。实现异步邮件发送
要实现异步邮件发送,我们需要定义一个自定义的消息类来承载邮件数据,一个消息处理程序来实际发送邮件,并相应配置Messenger。1. 创建异步邮件消息类
首先,创建一个PHP类来封装邮件所需的所有数据,例如主题、内容、日常等。该类将作为Messenger消息在早餐中传输。
// src/Message/EmailAsync.phpnamespace App\Message;class EmailAsync{ private string $subject; private string $bodyHtmlTemplate; private ?string $bodyTextTemplate; private string $recipient; private array $context; private string $senderEmail; // 假设发件人是固定的或通过配置获取 public function __construct( string $subject, string $bodyHtmlTemplate, ?string $bodyTextTemplate, string $recipient, array $context = [], string $senderEmail = 'noreply@example.com' // 示例发件人 ) { $this-gt;subject = $subject; $this-gt;bodyHtmlTemplate = $bodyHtmlTemplate; $this-gt;bodyTextTemplate = $bodyTextTemplate; $this-gt;recipient = $recipient; $this-gt;context = $context; $this-gt;senderEmail = $senderEmail; } public function getSubject(): string { return $this-gt;subject; } public function getBodyHtmlTemplate(): string { return $this-gt;bodyHtmlTemplate; } public function getBodyTextTemplate(): ?string { return $this-gt;bodyTextTemplate; } public function getRecipient(): string { return $this-gt;recipient; } public function getContext(): array { return $this-gt;context; } public function getSenderEmail(): string { return $this-gt;senderEmail; }}登录后复制2. 创建异步邮件处理程序
接下来,创建一个消息处理程序来处理EmailAsync消息。
当 Messenger 收到一个 EmailAsync 消息时,会调用这个处理程序,由处理程序构建 TemplatedEmail 并使用 MailerInterface 发送。// src/MessageHandler/EmailAsyncHandler.phpnamespace App\MessageHandler;use App\Message\EmailAsync;use Symfony\Component\Mime\Address;use Symfony\Bridge\Twig\Mime\TemplatedEmail;use Symfony\Component\Mailer\MailerInterface;使用 Symfony\Component\Messenger\Handler\MessageHandlerInterface;类 EmailAsyncHandler 实现 MessageHandlerInterface{ protected MailerInterface $mailer; public function __construct(MailerInterface $mailer) { $this-gt;mailer = $mailer; } public function __invoke(EmailAsync $emailAsync): void { $emailToSend = (new TemplatedEmail()) -gt;from(new地址($emailAsync-gt;getSenderEmail())) -gt;to(新地址($emailAsync-gt;getRecipient())) -gt;主题($emailAsync-gt;getSubject()) -gt;htmlTemplate($emailAsync-gt;getBodyHtmlTemplate()) -gt;textTemplate($emailAsync-gt;getBodyTextTemplate()) -gt;context($emailAsync-gt;getContext()); $this-gt;mailer-gt;send($emailToSend); }}登录后复制3. 配置 Messenger 路由
在 config/packages/messenger.yaml 或 config/packages/prod/messenger.yaml 中配置 Messenger,将 App\Message\EmailAsync 消息路由到异步传输。请确保您已经配置了一个异步传输(例如使用 MESSENGER_TRANSPORT_DSN 环境指标)。
# config/packages/messenger.yamlframework: messenger: # 配置异步传输,例如使用 RabbitMQ, Redis, 或 Doctrine Transports: async: 'env(MESSENGER_TRANSPORT_DSN)'routing: # 将自定义的 EmailAsync 消息路由到异步传输 'App\Message\EmailAsync': async # 解决 Symfony\Component\Mailer\Messenger\SendEmailMessage 没有被路由到# 如果你需要一个完全同步的 MailerInterface::send(),请不要在此处添加 SendEmailMessage 的路由。登录后复制
重要提示:确认 Symfony\Component\Mailer\Messenger\SendEmailMessage 没有被路由到 async。如果你的 Messenger 配置中没有关于 Symfony\Component\Mailer\Messenger\SendEmailMessage的路由入境,那么通过 MailerInterface::send()发送的邮件将默认以同步方式处理,这就是我们实现同步邮件所需要的。小云雀
剪映出品的AI视频和图片创作助手1949查看详情4.在服务中调度异步邮件可以
现在,您在服务中注入MessageBusInterface并调度EmailAsync消息来发送异步邮件。
// src/Service/MailManagerAsync.phpnamespace App\Service;use App\Message\EmailAsync;use Symfony\Component\Messenger\MessageBusInterface;class MailManagerAsync{ protected MessageBusInterface $bus; private string $defaultSenderEmail; // 可以通过构造函数注入或配置获取 public function __construct(MessageBusInterface $bus, string $defaultSenderEmail = 'noreply@example.com') { $this-gt;bus = $bus; $this-gt;defaultSenderEmail = $defaultSenderEmail; } public function sendAsyncMessage( string $subject, string $htmlTemplate, ?string $textTemplate, string $to, array $context = [] ): void { $emailAsync = new EmailAsync( $subject, $htmlTemplate, $textTemplate, $to, $context, $this-gt;defaultSenderEmail ); $this-gt;bus-gt;dispatch($emailAsync); }}登录后复制
现在,当您调用MailManagerAsync::sendAsyncMessage()时,邮件将封装成EmailAsync消息并发送到Messenger链路,然后由异步传输处理。实现同步邮件发送
对于同步邮件发送,您可以继续使用Symfony提供的MailerInterface服务,直接调用其send()方法。由于我们没有将 Symfony\Component\Mailer\Messenger\SendEmailMessage 路由到异步传输,因此这些邮件将立即发送,不会进入消息队列。
// src/Service/MailManagerSync.phpnamespace App\Service;use Symfony\Component\Mime\Address;use Symfony\Bridge\Twig\Mime\TemplatedEmail;use Symfony\Component\Mailer\MailerInterface;class MailManagerSync{ protected MailerInterface $mailer; private string $defaultSenderEmail; // 可以通过构造函数注入或配置获取 public function __construct(MailerInterface $mailer, string $defaultSenderEmail = 'noreply@example.com') { $this-gt;mailer = $mailer; $this-gt;defaultSenderEmail = $defaultSenderEmail; } public function sendSyncMessage( string $subject, string $htmlTemplate, ?string $textTemplate, string $to, array $context = [] ): void { $email = (new TemplatedEmail()) -gt;from(new Address($this-gt;defaultSenderEmail)) -gt;to(new Address($to)) -gt;subject($subject) -gt;htmlTemplate($htmlTemplate) -gt;textTemplate($textTemplate) -gt;context($context); $this-gt;mailer-gt;send($email); }}登录后复制
当您调用MailManagerSync::sendSyncMessage()时,邮件将立即发送,而不会经过Messenger队列。总结与注意事项
通过上述步骤,您已经在 Symfony 5 应用中成功实现了同步和异步邮件的异步发送:异步邮件:通过自定义 EmailAsync 消息和 EmailAsyncHandler 处理程序,指定其路由到 Messenger 的异步传输。在服务中,您需要注入 MessageBusInterface 来调度这些消息。同步邮件:直接使用 MailerInterface 服务发送 TemplatedEmail。由于Symfony\Component\Mailer\Messenger\SendEmailMessage 没有被路由到异步传输,这些邮件将直接发送。
注意事项:Messenger传输配置:确保您的异步传输已正确配置并能够正常工作(例如,RabbitMQ服务器正在运行,或者Doctrine传输的数据库连接正常)。错误处理:对于异步邮件,处理程序中的错误不会立即反馈给用户。您需要为Messenger配置失败策略(如重试、死信队列)来处理邮件发送失败的情况。发件人地址:示例代码中发件人地址是硬编码的,实际应用中应通过配置文件或环境变量注入。模板路径: htmlTemplate 和 textTemplate 应指向实际的 Twig 模板文件路径。代码可维护性:将同步和异步邮件发送逻辑封装在不同的服务中,有助于提高代码的易用性和可维护性。
遵循教程本的方法,您将能够更灵活地管理 Symfony应用中的邮件发送流程,根据业务需求选择最合适的发送模式。
以上就是如何在Symfony 5中同时发送同步与异步邮件的详细内容,更多请关注乐哥常识网其他相关文章! 相关标签: php redis html 编码 app ai 路由环境变量配置文件 red php symfony Rabbitmq 并发负载数据库大家都在看: php怎么配置备份备用数据_php配置临时阵列方法与备份技巧 php怎么找备份中的顶部_PHP备份中拓扑的位置 php随机输出备份数字_php备份随机元件技巧【教程】 php根据值获取键名操作_php备份值替换对应键名方法【解析】 php获取数据库中索引步骤_php获取数据库中索引方法详解【教程】
