通过 Symfony Messenger 执行邮件发送

Posted

技术标签:

【中文标题】通过 Symfony Messenger 执行邮件发送【英文标题】:Executing mail sending via Symfony Messenger 【发布时间】:2020-11-22 15:43:16 【问题描述】:

我正在寻找有关我的代码的大帮助。 我尽我所能连接一些 Symfony 功能,我想我要去某个地方..

我正在使用 Symfony 4.2 和 API 平台并尝试添加发送电子邮件消息以异步使用的过程。

我有我的评论实体,它在持久实体上触发它。它触发了我的 __invoke 函数,但是有一个问题。我不太明白下一步该怎么做。

正如文档 here 中所说,首先我需要配置 Data Persister:

<?php

namespace App\DataPersister;

use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
use App\Entity\Comment;

final class EmailNotificationDataPersister implements ContextAwareDataPersisterInterface

private $decorated;
private $mailer;

public function __construct(ContextAwareDataPersisterInterface $decorated, \Swift_Mailer $mailer)

    $this->decorated = $decorated;
    $this->mailer = $mailer;


public function supports($data, array $context = []): bool

    return $this->decorated->supports($data, $context);


public function persist($data, array $context = [])

    $result = $this->decorated->persist($data, $context);

    if (
        $data instanceof Comment && (
            ($context['collection_operation_name'] ?? null) === 'post')
    ) 
        $this->sendWelcomeEmail($data);
    

    return $result;


public function remove($data, array $context = [])

    return $this->decorated->remove($data, $context);


private function sendWelcomeEmail(Comment $comment)

    // Your welcome email logic...
    // $this->mailer->send(...);


我使用的是 Symfony 4.2,所以我安装了 swift mailer 电子邮件客户端。

我还定义了 EmailSubscriber:

<?php

namespace App\EventSubscriber;

use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\Comment;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\Messenger\MessageBusInterface;

final class EmailNotificationSubscriber implements EventSubscriberInterface



private $messageBus;

public function __construct(MessageBusInterface $messageBus)

    $this->messageBus = $messageBus;


public static function getSubscribedEvents()

    return [
        KernelEvents::VIEW => [ 'sendMail', EventPriorities::POST_WRITE],
    ];


public function sendMail(GetResponseForControllerResultEvent $event)

    $comment = $event->getControllerResult();
    $method = $event->getRequest()->getMethod();


    if (!$comment instanceof Comment || Request::METHOD_POST !== $method) 
        return;
    

    $this->messageBus->dispatch(new Comment());


最后我实现了处理程序:

<?php

namespace App\Handler;

use App\Entity\Comment;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

final class EmailNotificationHandler implements MessageHandlerInterface

    public function __invoke(Comment $comment)
    
        // do something with the resource
    

当我在我的 api 平台中触发持久实体时,调用函数中的 var_dump() 被捕获。

我不知道是否有问题以及下一步该怎么做。 我需要使用 Symfony Messenger 异步执行电子邮件发送。

在我的 .env 文件中:

MESSENGER_TRANSPORT_DSN=amqp://127.0.0.1:8000/api/messages

和框架.yaml

messenger:
    transports:
        amqp: "%env(MESSENGER_TRANSPORT_DSN)%"

    routing:
        'App\Entity\Comment': amqp

还有什么方法可以向用户表中发布的任何随机邮件发送电子邮件?我想为此设置邮件配置。

【问题讨论】:

嗨。首先,也显示 messenger 和 sendmail 配置。其次,您可以在 dataPersister 类中使用messageBus-&gt;dispatch,这里不需要订阅者。您还需要使用AsyncMessageInterface 创建一条消息。然后你可以在你的 __invoke 方法中使用mailer-&gt;send($message) 看,查看 Symfony 关于创建和发送电子邮件的文档。您只需要创建新的电子邮件对象并使用邮件发送它。 symfony.com/doc/4.2/email.html 【参考方案1】:

对于异步运行操作,您需要transport。对于本地测试,symfony 服务器和 docker 效果很好。

#config/packages/messenger.yaml
transports:
    async: '%env(RABBITMQ_DSN)%'

docker-compose.yaml 放在项目根目录。

rabbitmq:
    image: rabbitmq:3-management
    ports: [5672, 15672]

在控制台中运行

docker-compose up -d
symfony server:start -d

用于在控制台中运行的消费消息

symfony console messenger:consume async -vv

在生产中,您必须为 RabbitMQ、Amazon SQS 等添加带有真实凭证的 RABBITMQ_DSN(或 MESSENGER_TRANSPORT_DSN),并且可能使用 Supervisor 来消费消息。

【讨论】:

以上是关于通过 Symfony Messenger 执行邮件发送的主要内容,如果未能解决你的问题,请参考以下文章

在 Symfony Messenger 组件中使用独立的发件人

Symfony Messenger / RabbitMQ 中的消费者错误处理

如何关闭 symfony messenger 组件的日志记录

Symfony Messenger 4.3 - 从理论传输中消费消息失败(抛出异常)

Symfony 5 Messenger 不自动配置消息处理程序

如何使用 Behat 测试在多总线场景中调度 Symfony Messenger 事件?