Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Mailer] Simplify getting SentMessage information after send #42108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hushker opened this issue Jul 14, 2021 · 8 comments · Fixed by #47080
Closed

[Mailer] Simplify getting SentMessage information after send #42108

hushker opened this issue Jul 14, 2021 · 8 comments · Fixed by #47080
Labels
DX DX = Developer eXperience (anything that improves the experience of using Symfony) Mailer

Comments

@hushker
Copy link

hushker commented Jul 14, 2021

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:

  1. 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;
        }
...
  1. 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.

@javiereguiluz javiereguiluz added the DX DX = Developer eXperience (anything that improves the experience of using Symfony) label Jul 16, 2021
@carsonbot
Copy link

Thank you for this issue.
There has not been a lot of activity here for a while. Has this been resolved?

@stof
Copy link
Member

stof commented Jan 17, 2022

where we can break BC and make return type ?SentMessage for sync sending.

This would then make it likely that some code will be written that would break if you turn on async sending. And from a performance point of view, you likely want to turn on async sending. So that looks like a bad idea to me.
So this would still get a negative vote from me.

@carsonbot carsonbot removed the Stalled label Jan 17, 2022
@ro0NL
Copy link
Contributor

ro0NL commented Jan 17, 2022

same boat :)

what if we split the API? either by method, or thru argument.

@Lozik
Copy link
Contributor

Lozik commented May 8, 2022

I'd like to +1 this proposal. How exactly it's implemented – whether the Mailer interface returns the SentMessage object or there is a triggered event – does not matter to me.

The use cases that are important for me:

  • Debugging email problems on production systems
  • Audit trail of sent messages (including message-id returned by the third party provider or SMTP server) -> possibility to save database entry for every sent message
  • all this without disabling the async functionality for performance reasons

For some projects, I still need to use swiftmailer for this reason.

@javiereguiluz
Copy link
Member

@stof sorry if the comparison is not correct ... but in the HttpClient component we return a response object immediately even if the HTTP request is async. We could do the same here: always returns a SentMessage and then:

(1) If technically possible, do the same as HttpClient and implement the methods in a way that for async emails you just need to wait until you receive a response form the server.
(2) If not possible, add some method that developers can check to know if they have access to information or not (e.g. isAsync())

@mkrauser
Copy link
Contributor

I would love to have an Event dispatched after the Message is sent. Of course this Event should contain the SentMessage Object.
This would work with sync and async. Event switching from sync to async should work without changing anything else.

@stof
Copy link
Member

stof commented May 13, 2022

@javiereguiluz the HttpClient does concurrent requests in the same PHP process. But it does not delegate the request sending to a Messenger worker running in a different process.

That's not the same kind of async (there was a talk about async PHP at the Symfony Live Paris 2022, that was showing the various kinds of async in its intro)

@fabpot
Copy link
Member

fabpot commented Jul 27, 2022

Dispatching events is the best/only way to fix this one. See #47080.

@fabpot fabpot closed this as completed Jul 27, 2022
fabpot added a commit that referenced this issue Jul 27, 2022
This PR was merged into the 6.2 branch.

Discussion
----------

[Mailer] Add new events

| 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       | Fix #42108 <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT
| Doc PR        |

Dispatching 2 new events: `SentMessageEvent` and `FailedMessageEvent` when sending an email.
It allows acting on the `SentMessage` or the "initial" message in case of a failure.

Commits
-------

d1138b2 [Mailer] Add new events
javiereguiluz added a commit to symfony/symfony-docs that referenced this issue Feb 3, 2025
…geEvent` (wkania)

This PR was merged into the 6.4 branch.

Discussion
----------

[Mailer] Mention the `SentMessageEvent` and `FailedMessageEvent`

The symfony/symfony#47080 PR was created to solve the problem of [debugging](symfony/symfony#37570) and to get [information](symfony/symfony#42108) about email after it was sent.
The section about [debugging](https://symfony.com/doc/current/mailer.html#debugging-emails) does not mention those events. Added some links for better navigation.

For example what debug returns:

```
< 220 ESMTP SYMFONY.COM
> EHLO [127.0.0.1]
< 250-smtp.symfony.com
< 250-PIPELINING
< 250-SIZE 157286400
< 250-AUTH PLAIN LOGIN PLAIN LOGIN PLAIN LOGIN
< 250-AUTH=PLAIN LOGIN PLAIN LOGIN PLAIN LOGIN
< 250-ENHANCEDSTATUSCODES
< 250-8BITMIME
< 250 SMTPUTF8
> AUTH LOGIN
< 334 VXNlcm5hbWU6
> ZXhhbXBsZUBzeW1mb255LmNvbQ==
< 334 UGFzc3dvcmQ6
> U3ltcGhvbnkg.aXMgQXdlc29tZQ==
< 235 2.7.0 Authentication successful
> MAIL FROM:<[email protected]>
< 250 2.1.0 Ok
> RCPT TO:<[email protected]>
< 250 2.1.5 Ok
> DATA
< 354 End data with <CR><LF>.<CR><LF>
> .
< 250 OK. ID: a20fb6ebbc54d22b
```

P.S.
I see that the checks now can find repeated words:
```
mailer.rst ✘
 1765: The word "the" is used more times in a row.
   ->  ``FailedMessageEvent`` allows acting on the the initial message in case of a failure and some
```

Commits
-------

8e3c1db [Mailer] Mention the SentMessageEvent and FailedMessageEvent in the debug section
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DX DX = Developer eXperience (anything that improves the experience of using Symfony) Mailer
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants