Problem/Motivation
Part of #1803948: [META] Adopt the symfony mailer component, proposes a way on how to integrate the upcoming email subsystem with the entity subsystem.
The observation which informed the design:
Transactional email is often bound to an entity. E.g., the password reset email is tied to a user entity, the contact email is tied to a contact message entity, and the commerce order receipt email is tied to an order entity.
Entity displays (and view modes) are used by site builders and developers to configure and tweak how content is presented when rendered in a browser, entity forms (and form modes) are used to customize forms.
What if entity "mail modes" would become the canonical way to configure how email is rendered in the recipients inbox?
Steps to reproduce
Proposed resolution
The proposed approach:
The call site (i.e., where an entity is being prepared to be sent as an email) ideally shouldn't be doing much more than specifying the "mail mode", the locale and the destination.
The entity base class provides a couple of existing methods which have similar responsibilities. E.g., EntityBase::toUrl($rel = NULL, array $options = []): Url returns a link generated from patterns defined on the entity type.
Similarly, this PR proposes EntityEmailTrait::toEmail(string $key, ?string $langcode): Email for entities which support being rendered into an email message.
With this API, the call site is quite convenient (made up example):
$email = $entity->toEmail('subscription_start_notification', $subscriberLangcode);
$this->mailer->send($email->from($siteEmail)->to($subscriber));
The entity subsystem provides a way to register/alter entity handlers. This mechanism can be leveraged to provide and swap out the implementation used to actually populate a message from entity values. The current PR illustrates this on the example of the User and the contact Message entities.
diff --git a/core/modules/contact/src/Entity/Message.php b/core/modules/contact/src/Entity/Message.php
index 16eae76660c..a8c90a8e47a 100644
--- a/core/modules/contact/src/Entity/Message.php
+++ b/core/modules/contact/src/Entity/Message.php
@@ -32,6 +36,13 @@
'storage' => ContentEntityNullStorage::class,
'view_builder' => MessageViewBuilder::class,
'form' => ['default' => MessageForm::class],
+ 'email' => [
+ 'page_mail' => PageMessageBuilder::class,
+ 'page_copy' => PageMessageBuilder::class,
+ 'page_autoreply' => ReplyMessageBuilder::class,
+ 'user_mail' => PersonalMessageBuilder::class,
+ 'user_copy' => PersonalMessageBuilder::class,
+ ],
],
admin_permission: 'administer contact forms',
bundle_entity_type: 'contact_form',
The message builders registered in this PR are derived from their respective hook_mail implementations. However, in the future this architecture leaves the possibility to introduce some generic EntityMessageBuilder class configurable through the administrative interface in a similar way as EntityViewBuilder is for markup targeting the browser.
How to manually test the PR:
- Enable and configure the Experimental Symfony Mailer Module.
- Enable the experimental mailer API for user and contact module via container parameters (e.g. via development.services.yml:
parameters: user.use_experimental_mailer: true contact.use_experimental_mailer: true
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
Issue fork drupal-3529014
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
znerol commentedComment #4
znerol commentedComment #5
znerol commentedThis hasn't sparked any interest and is not being worked on at the moment.
Comment #6
dwwPostponed means it's blocked on something. This isn't blocked, only awaiting interest and available time. I'm interested, but not available. 😂
Comment #7
berdirI think it is pretty much postponed, in the way that it's maybe step 7 or something on #3534136: Requirements and strategy for Core Mailer. It shouldn't be what we focus on, not now, so postponed to me is a good state. It's not blocked on a specific issue, but we're not yet at this level of abstraction in the new mail API. Lets build it from the bottom up and then we'll see if provides an additional benefit.