Skip to content
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

[Messenger][Mailer] Ability to choose the Message class used by Mailer::send #36348

Closed
Seldaek opened this issue Apr 5, 2020 · 13 comments · Fixed by #47190
Closed

[Messenger][Mailer] Ability to choose the Message class used by Mailer::send #36348

Seldaek opened this issue Apr 5, 2020 · 13 comments · Fixed by #47190

Comments

@Seldaek
Copy link
Member

Seldaek commented Apr 5, 2020

Description
To allow routing different emails to different messenger transports (not mailer transport), it would be good if there was a way to choose the message class used, instead of having Mailer::send hardcode it to Symfony\Component\Mailer\Messenger\SendEmailMessage.

P.S: I found the docs a little confusing as I tried setting up Mailer + Messenger together for the first time, and as both use "transport", the Mailer docs say to send to another transport you can use an X-Transport header, so I tried setting that to my messenger transport I wanted to route to, and then got an error that the transport didn't exist. Maybe the docs should be more clear there.

Example

I had to copy the entire Mailer class to do this, as there is no easy way to change the message class used, and as anyway it is final. But anyway I hope it illustrates what I am trying to get to.

<?php

namespace App;

use Symfony\Component\Mailer\Messenger\SendEmailMessage as BaseSendEmailMessage;

class SendEmailMessage extends BaseSendEmailMessage
{
}

class SendUrgentEmailMessage extends BaseSendEmailMessage
{
}

class Mailer implements MailerInterface
{
    public function send(RawMessage $message, Envelope $envelope = null): void
    {
        $this->doSend(SendEmailMessage::class, $message, $envelope);
    }

    public function sendUrgently(RawMessage $message, Envelope $envelope = null): void
    {
        $this->doSend(SendUrgentEmailMessage::class, $message, $envelope);
    }

    private function doSend(string $messageClass, RawMessage $message, Envelope $envelope = null)
    {
        if (null === $this->bus) {
            $this->transport->send($message, $envelope);

            return;
        }

        if (null !== $this->dispatcher) {
            $message = clone $message;
            $envelope = null !== $envelope ? clone $envelope : Envelope::create($message);
            $event = new MessageEvent($message, $envelope, (string) $this->transport, true);
            $this->dispatcher->dispatch($event);
        }

        $this->bus->dispatch(new $messageClass($message, $envelope));
    }
}

Now with this I am able to route urgent emails to a different messenger queue which is processed faster.

@weaverryan
Copy link
Member

I had talked to Jordi about this. Obviously, because the message is wrapped in MessageEvent, routing different emails to different Messenger transports isn't possible. I'm not sure what Mailer can do about that, it feels like the fix will have to be in Messenger itself - #36349.

@Seldaek
Copy link
Member Author

Seldaek commented Apr 5, 2020

Might help if messages had an interface they can implement to tell Messenger where they should be routed? Just thinking out loud here.

@weaverryan
Copy link
Member

I think that would be cool too - but there's no decent way (at the moment) for Mailer to communicate that over to Messenger - all the routing config is just the class => transport config sitting in the user's messenger.yaml file. Unless I'm missing something, we need a hook point over on that side.

the Mailer docs say to send to another transport you can use an X-Transport header, so I tried setting that to my messenger transport I wanted to route to,

Ah, this is referring to the *Mailer * transport - not the Messenger transport. It IS confusing in the docs - this section is right after talking about Messenger transports - it confused me just now too.

@weaverryan
Copy link
Member

Related to #35750

@Seldaek
Copy link
Member Author

Seldaek commented Apr 5, 2020

Yup of course this would have to be supported in Messenger too, I'm just thinking it might allow smarter routing patterns if the code/message could route itself. It's also dangerous though for sure, it's nice to remain in control in messenger.yaml of the whole routing.

javiereguiluz added a commit to symfony/symfony-docs that referenced this issue Apr 6, 2020
This PR was merged into the 4.4 branch.

Discussion
----------

Moving mailer transport section

See symfony/symfony#36348 (comment)

I moved this Mailer "transport" section above Messenger so that, if you're reading the Messenger section, you can't accidentally keep reading and think that the "mailer transports" section is talking about Messenger transports.

Also, I changed the transport name from `important` to `alternative` just to add some further differentiation.

Commits
-------

8700f2e moving mailer transport section
@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?

@Seldaek
Copy link
Member Author

Seldaek commented Feb 19, 2021

Yes. I do still think this would be valuable to be able to send transactional emails ASAP, while background emails could be sent at a slower pace.

It also seems like it highlight a design flaw in the Messenger/Mailer combo somehow given how hard it is to achieve, so it's probably worth investigating what could be done. I unfortunately don't have enough knowledge about Messenger internals to say.

@carsonbot carsonbot removed the Stalled label Feb 19, 2021
@Seldaek Seldaek changed the title [Mailer] Ability to choose the Message class used by Mailer::send [Messenger][Mailer] Ability to choose the Message class used by Mailer::send Feb 19, 2021
@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?

@sstok
Copy link
Contributor

sstok commented Aug 22, 2021

@carsonbot Yes.

@carsonbot carsonbot removed the Stalled label Aug 22, 2021
@jcaillot
Copy link

yes
just bumped into this a few days ago. had to implement @Seldaek trick (thanks)

@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?

@fabpot
Copy link
Member

fabpot commented Aug 4, 2022

Implemented in #47190

@Seldaek
Copy link
Member Author

Seldaek commented Aug 4, 2022

Thanks!

@fabpot fabpot closed this as completed Aug 7, 2022
fabpot added a commit that referenced this issue Aug 7, 2022
…ally (fabpot)

This PR was merged into the 6.2 branch.

Discussion
----------

[Mailer] Add a way to change the Bus transport dynamically

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

This PR relies on #39306. Once merged, this PR will be rebased.
This allows overriding the bus transport "dynamically" via the `X-Bus-Transport` header.

Commits
-------

ffe3600 [Mailer] Add a way to change the Bus transport dynamically
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants