How to configure Symfony Mailer to read DSN from database at runtime? #61506
Unanswered
kekkoudesu
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I want site admins to be able to configure the MAILER_DSN at runtime, and change it without needing a system administrator to change the MAILER_DSN environment variable on the server. This involves creating a doctrine entity to write/read the mailer configuration from. I've done considerable research into how to achieve this.
I do have a working method, but it's pretty hacky. I wrote a custom environment variable processor to replace the
mailer.dsn
parameter every time the Mailer fetches it, as environment variables are resolved at runtime:The two environment variable processors are used in the config file:
And this works just great in the dev environment (currently not tested in prod):
This is obviously a pretty dirty hack. I can't see any obvious downsides to it other than it maybe not working in the future if EnvVarProcessors are changed somehow to prevent this. The upside is that it requires very little code and I don't need to understand the interfaces/implementations for Mailer, Notifier, EmailChannel, LoginLinkNotification, etc.
The 'proper' way, I assume, would be to write a service that implements MailerInterface and replaces the current Mailer. So I did that too:
It uses
shared: false
because the object needs to be recreated every time in case the database configuration has changed. This will have a performance impact on every invocation of the Mailer service. You might be able to write some code insend()
to decide whether to recreate the service based on cache to mitigate this.You configure it to override the Mailer service here:
And this...actually works. As long as you invoke the Mailer service directly instead of via Notifier, and hardcode the
sender
(you could just replace the envelope in the DbBackedMailer too if you wanted):But as this doesn't work for my LoginLinkNotification which uses Notifier, I guess I need to replace the Notifier service. I wasn't able to understand the logic very well, and I'm at the point where I really want to move on from this. The EnvVarProcessor is hacky but it was easy to write and understand, plus it's easy to maintain. And it doesn't have a performance impact.
I just wanted to know...am I doing something wrong here?
These methods do not work for the purpose:
mailer.dsn
parameter right before service compilation. This wouldn't work the simple way because, while you can potentially use$container->setParameter
to overridedsn
, you can't inject any services like Doctrine's EntityManager or a Repository because the service container is not ready for use. It would be possible to use Doctrine classes directly without the service container, but this is more prone to error. You would also need some way to clear the cache in the Controller after an admin saves the mailer settings so the service container gets recompiled; probably running thecache:clear
console command directly. So it could be made to work, but I don't think it's a great solution.MailerInterface
class'send()
method does not take the Transport as an argument and instead uses it from the constructor, which configurators can't override.send()
method.Beta Was this translation helpful? Give feedback.
All reactions