Skip to content

Commit

Permalink
feature #47191 [Mailer] Add a way to inject Stamps when sending an em…
Browse files Browse the repository at this point in the history
…ail via Messenger (fabpot)

This PR was merged into the 6.2 branch.

Discussion
----------

[Mailer] Add a way to inject Stamps when sending an email via Messenger

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | no
| New feature?  | yes <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | n/a <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT
| Doc PR        |

In #47190, we add a way to add a specific stamp to the message sent to the Messenger bus.
I think we should make this possibility more generic.

Commits
-------

77381fa [Mailer] Add a way to inject Stamps when sending an email via Messenger
  • Loading branch information
fabpot committed Aug 5, 2022
2 parents 1f27ed7 + 77381fa commit aea5200
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/Symfony/Component/Mailer/Event/MessageEvent.php
Expand Up @@ -20,7 +20,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
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[] */
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
13 changes: 11 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,25 @@ 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 +75,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 aea5200

Please sign in to comment.