Problem/Motivation
Part of stage 2 of
🌱
[META] Adopt the symfony mailer component
Needs review
.
Create a new service that performs some additional Drupal-specific processing when sending an email. This mostly means copying various parts of the old mail system into the new one:
- Core MailManager
- Contrib mailsystem module
- Mailer plugins, such as Contrib Drupal Symfony Mailer Lite (DSM-L)
- plus potentially taking some new ideas from Contrib Drupal Symfony Mailer (DSM)
Proposed resolution
Class Mailer
that implements MailerInterface
. Functions of the mailer are:
- Set some defaults (currently in MailManager)
- Invoke events/callbacks (currently in MailManager)
- Switch render context to avoid pollution (currently in MailManager)
- Convert relative URLs to absolute (currently in MailManager)
- Ensure that subject is plain text (currently in MailManager)
- Switch theme (currently in mailsystem)
- Switch language (currently done in Commerce module, and would save more than half the code in
user_mail()
)
- Switch account (currently done in Simplenews module, ensures security and personalisation)
- Render templates (currently done in DSM-L), which is a 2-stage process, first part module specific (done in simplenews, commerce) second part a generic wrapper which is generated separately for HTML and plain
- Convert to plain-text (currently done in DSM-L) - Symfony will do it, but in quite a different way from Drupal
- Inline CSS (currently done in DSM-L)
- Attachment access checking (some done in DSM-L)
- Act as a factory for Email objects (currently in DSM), which helps with dependency injection and allows Contrib code to override the Email class
The Email building pipeline proceeds in the following sequence:
- Init phase: set language, theme, user account only
- Switching: render context (to avoid leaking into current request), language, theme, user account (for access control and correct rendering of entities)
- Build phase: allow modules to build the unrendered email
- Rendering: render twig, replace tokens
- Post-render phase: allow modules to process the rendered email
- Send email
- Post-send phase: allow modules to react to the sent email
The implementation can be divided between various classes, each one is independently replaceable for customisation.
- Mailer class
- Email class
- Processor classes for specific function such as inline CSS
Remaining tasks
User interface changes
Introduced terminology
API changes
Possible interface for Mailer service:
/**
* Creates a new email.
*
* @param string $tag
* Tag used to identify the type or source of this email.
* @see \Drupal\symfony_mailer\EmailInterface::getTag()
*
* @return \Drupal\symfony_mailer\EmailInterface
* The new email.
*/
public function newEmail(string $tag): EmailInterface;
/**
* Sends an email.
*
* @param \Drupal\symfony_mailer\InternalEmailInterface $email
* The email to send.
*
* @return bool
* Whether successful.
*/
public function send(InternalEmailInterface $email): bool;
Example usage of the interface, taken from Contrib DSM module implementation of emails for the Core user module.
/**
* {@inheritdoc}
*/
public function notify(string $op, UserInterface $user): bool {
if ($op == 'register_pending_approval') {
$this->newEmail("{$op}_admin")->setEntityParam($user)->send();
}
return $this->newEmail($op)
->setEntityParam($user)
->setTo($user)
->send();
}
Data model changes
Release notes snippet