Skip to content

Commit

Permalink
[Mailer] Add a way to inject Stamps when sending an email via Messenger
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Aug 4, 2022
1 parent 6eef692 commit 3f5650a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/Symfony/Component/Mailer/Event/MessageEvent.php
Expand Up @@ -19,8 +19,10 @@
* Allows the transformation of a Message and the Envelope before the email is sent.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final
*/
final class MessageEvent extends Event
class MessageEvent extends Event
{
private RawMessage $message;
private Envelope $envelope;
Expand Down
45 changes: 45 additions & 0 deletions src/Symfony/Component/Mailer/Event/QueuingMessageEvent.php
@@ -0,0 +1,45 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Mailer\Event;

use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Messenger\Stamp\StampInterface;
use Symfony\Component\Mime\RawMessage;

/**
* Allows the transformation of a Message, the Envelope, and the Messenger stamps before the email is sent to the Messenger bus.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
final class QueuingMessageEvent extends MessageEvent
{
/** @var StampInterface[] $stamps */
private array $stamps = [];

public function __construct(RawMessage $message, Envelope $envelope, string $transport)
{
parent::__construct($message, $envelope, $transport, true);
}

public function addStamp(StampInterface $stamp): void
{
$this->stamps[] = $stamp;
}

/**
* @return StampInterface[]
*/
public function getStamps(): array
{
return $this->stamps;
}
}
7 changes: 5 additions & 2 deletions src/Symfony/Component/Mailer/Mailer.php
Expand Up @@ -13,6 +13,7 @@

use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\Event\QueuingMessageEvent;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Messenger\SendEmailMessage;
use Symfony\Component\Mailer\Transport\TransportInterface;
Expand Down Expand Up @@ -44,6 +45,7 @@ public function send(RawMessage $message, Envelope $envelope = null): void
return;
}

$stamps = [];
if (null !== $this->dispatcher) {
// The dispatched event here has `queued` set to `true`; the goal is NOT to render the message, but to let
// listeners do something before a message is sent to the queue.
Expand All @@ -52,12 +54,13 @@ public function send(RawMessage $message, Envelope $envelope = null): void
// Listeners should act depending on the `$queued` argument of the `MessageEvent` instance.
$clonedMessage = clone $message;
$clonedEnvelope = null !== $envelope ? clone $envelope : Envelope::create($clonedMessage);
$event = new MessageEvent($clonedMessage, $clonedEnvelope, (string) $this->transport, true);
$event = new QueuingMessageEvent($clonedMessage, $clonedEnvelope, (string) $this->transport);
$this->dispatcher->dispatch($event);
$stamps = $event->getStamps();
}

try {
$this->bus->dispatch(new SendEmailMessage($message, $envelope));
$this->bus->dispatch(new SendEmailMessage($message, $envelope), $stamps);
} catch (HandlerFailedException $e) {
foreach ($e->getNestedExceptions() as $nested) {
if ($nested instanceof TransportExceptionInterface) {
Expand Down
12 changes: 10 additions & 2 deletions src/Symfony/Component/Mailer/Tests/MailerTest.php
Expand Up @@ -13,13 +13,14 @@

use PHPUnit\Framework\TestCase;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\Event\QueuingMessageEvent;
use Symfony\Component\Mailer\Exception\LogicException;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport\NullTransport;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\StampInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\RawMessage;

Expand All @@ -37,19 +38,24 @@ public function testSendMessageToBus()
{
$bus = new class() implements MessageBusInterface {
public $messages = [];
public $stamps = [];

public function dispatch($message, array $stamps = []): Envelope
{
$this->messages[] = $message;
$this->stamps = $stamps;

return new Envelope($message, $stamps);
}
};

$stamp = $this->createMock(StampInterface::class);

$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->expects($this->once())
->method('dispatch')
->with(self::callback(static function (MessageEvent $event) {
->with(self::callback(static function (QueuingMessageEvent $event) use ($stamp) {
$event->addStamp($stamp);
return 'Time for Symfony Mailer!' === $event->getMessage()->getSubject();
}))
->willReturnArgument(0)
Expand All @@ -68,5 +74,7 @@ public function dispatch($message, array $stamps = []): Envelope

self::assertCount(1, $bus->messages);
self::assertSame($email, $bus->messages[0]->getMessage());
self::assertCount(1, $bus->stamps);
self::assertSame([$stamp], $bus->stamps);
}
}

0 comments on commit 3f5650a

Please sign in to comment.