- Issue created by @adamps
The purpose of this issue is to create the best possible framework for use by modules that want to send emails.
1) Modules that send emails typically wish to have a mailer service. These services implement an interface specific to the needs of that module. So UserMailerInterface
resembles _user_mail_notify()
and ContactMailerInterface
is simply a rename of MailHandlerInterface
.
2) The email sending code needs to be split into different parts, allowing other code including events/hooks to run in between. The sequence of steps for sending an email is like this.
hook_mail()
in the old mail API, and the argument still applies.prepare()
sets the langcode
, to
and replyTo
.build()
fills the headers and creates the body as a render array or using a template.postRender()
can act on the rendered body.postSend()
which for example can log the operation.3) As part of
✨
Migration strategy for moving to Symfony Mailer
Active
, modules need to support converting to the old Mail interface. This would be done using a legacyMail()
callback.
4) We would like to collect metadata about the mailer service, including for use by ✨ Create a system for configurable emails in Symfony Mailer Active .
Answering the 4 points above:
1) Modules that send mail should implement a mailer class, with a mailer interface specific to the module. For example UserMailer
implements UserMailerInterface
.
2) Mailer classes should implement EmailProcessorInterface
which has the required callbacks for step 2 above. This interface is also implemented by modules that alter emails.
3) Mailer classes should implement MailerInterface
which extends EmailProcessorInterface
with the extra callback.
4) Create plug-in @Mailer
with classes implementing MailerInterface</code. Create manager <code>MailerManager
implementing MailerManagerInterface
.
So the module Mailer class acts both like a service and like a plug-in. We will need to figure out the details of exactly how this works. Some ideas:
The above is the recommended way for modules to send email. However for some code such as test code, prototyping, or tools, it's too complex to create a class for every different email that's sent. Instead they'd prefer simple inline code like this:
$mailer->create('module.key')->setTo($to)->setBody($body)->send();
We can't do exactly that due to point 2) from the problem/motivation section, but we can do something almost as simple. We create a FallbackMailer
implementing FallbackMailerInterface
. This has a single function send(array $params)
. Sending code will write
$fallback_mailer->send(['to' => $to, $body => $body]);
$fallback_mailer->send(['to' => $to, $build => 'my_build_function']);
The fallback mailer will process each of the parameters in the correct callback. The second case passes a callable that will be called during the build phase.