The goal of this meeting was to discuss the proposal in (#3539651-34: Introduce email plugins / branch 3539651-email-yaml-plugin-zengenuity ).
Multilanguage
Drupal string translation leverages PHP 8 \Stringable semantics. Translatable strings are evaluated lazily, they remain objects as long as they are not casted to a string. This can happen as late as when a message is finally rendered. But it potentially happens earlier, e.g. if a translatable object is passed to a method argument with explicit string typehint.
The current prototype provides methods to set the subject and the body on the call site. However, those methods accept a string and not a \Stringable argument. That means that translatable objects might be evaluated before third-party code has a chance to change the message language.
People on the call agreed that specifying the subject / body at the call site is not a priority. This functionality is to be removed from the prototype.
Alternatively, subject and body could also be defined at the call site using closures.
Params and Templates
The YAML definition provides a way to specify one template (#theme) for the HTML body part and another one for the text part. Those templates are free-form, i.e., all key-value pairs from the params array are passed as variables to the template.
As a result, each message type must provide its own template with the expected params. It was suggested that those values could also be passed to a #params key. Like this it would be possible to provide a default template with a defined variable structure.
Existing contrib modules provide a wrapper template which is used as the skeleton for all messages (much like html.html.twig). This has been useful in practice.
Plugin Definition
It has been questioned whether a plugin definition in YAML is the best approach. This is a recurring subject in this group. The YAML approach is best if it is unnecessary for most users to specify and implement a custom class.
It has been pointed out that there is a precedent in core for hybrid plugin definitions (layouts can be defined in YAML and also using PHP attributes).
Another idea would be to swap out the default class according to the properties in the definition. E.g, if the definition specifies an entity_type and/or a view_mode, then the class key is set to some EntityEmail plugin. Another generic plugin could handle cases where subject and body are defined in config.
Architecture and Hooks
EmailManager in the current iteration provides separate build() and send() methods. This is for cases where the built Symfony Email object needs to be modified at the call site before it is sent. As a consequence, the send() method accepts an optional $symfony_email parameter. Nobody on the call likes that. The separation of build() and send() is to be reconsidered.
One use case of a separate build() method could be to render a preview of an email which is about to be sent out (e.g., in a customer support backend). However, this use case could also be implemented by directly rendering a template.
The hooks email_post_render and email_pre_send are called at nearly the same place. It's unsure if both are needed, but it isn’t a problem to deprecate and remove any of them later.
Hook email_pre_send provides a mechanism to cancel email sending. A similar mechanism is already available in the Symfony Mailer transport layer. The MessageEvent provides an equivalent mechanism. The DX might be better if Drupal developers wouldn’t need to mix hook implementations and event subscribers.
It was discussed whether the rendering logic could be moved from the plugin manager to the plugin. This would pose some risk as a plugin implementation could (accidentally) override the base plugin in a way which prevents hook invocation. This could lead to hard to detect defects (e.g., email redirection could fail only for a specific type of email).
What’s next:
- Next planning meeting takes place January 7th 2026 at 4PM UTC+1.
Comments
Comment #2
znerol commentedComment #4
znerol commented