Description
Description
In some cases, you may need to get SentMessage
information after send.
As the docs say SentMessage
generates by TransportInterface
and NOT available through the Mailer by itself.
The reason for this is understandable - Mailer
can't just return SentMessage
as it can work async (through the Messenger)
I've seen related issues and rejected PR's (breaking BC), but still believe that Symfony should provide better DX in this case.
Example
In my case, I needed to get the Mailgun mail id to track it after sending it.
I ended up with this workaround - not brilliant as DX.
Later I faced another solution - to use directly TransportInformation
, but again, it's not what you expecting from Mailer.
Proposal
As a developer, I expect to deal with Mailer
as the main Facade component, not Transport
, therefore I think this PR makes sense for the next major version where we can break BC and make return type ?SentMessage
for sync sending.
As for now, we can make a new Event called MessageSentEvent that will provide SentMessage for minor version updates, and still useful for async mode.
<?php
namespace use Symfony\Component\Mailer\Event;
use Symfony\Component\Mailer\SentMessage;
class MessageSentEvent
{
private $sentMessage;
public function __construct(SentMessage $sentMessage)
{
$this->sentMessage = $sentMessage;
}
public function getSentMessage(): SentMessage
{
return $this->sentMessage;
}
}
And dispatch this Event after transport sends a message:
- In Mailer::send method for sync mode:
...
if (null === $this->bus) {
$sentMessage=$this->transport->send($message, $envelope);
$event = new MessageSentEvent($sentMessage);
$this->dispatcher->dispatch($event);
return;
}
...
- In MessageHandler::invoke for async mode:
...
$sentMessage=$this->transport->send($message->getMessage(), $message->getEnvelope());
$event = new MessageSentEvent($sentMessage);
$this->dispatcher->dispatch($event);
return $sentMessage;
...
After that, it becomes easy to subscribe to this event and process SentMessage information.