Update Email Customizer provides an administration interface for customizing Drupal update notification emails while keeping Drupal's existing update notification workflow and mail delivery system.
The module allows administrators to customize the HTML content and presentation of update notification emails for Drupal core, contributed modules, and themes. It includes a default email template, replacement tokens, security update awareness, and test email functionality from both the administration interface and Drush.
Project link
https://www.drupal.org/project/update_email_customizer
Comments
Comment #2
avpadernoThank you for applying!
Before giving links helpful to understand how the review process works, what to expect from a review, and what to do to avoid a review takes more time than needed, I would like to thank all the reviewers for the work they do.
These applications are volunters-driven, which also means it is not possible to predict when an application will be marked fixed and the applicant will get the permission to opt projects into security advisory policy. While we aim to make an application as quick as possible, it is also important for us that more people review the project used for an application. In this way, we make sure applications do not miss some important points that should be instead reported.
Applications are not meant to be complete debugging sessions that eliminate every existing bug, though. I apologize if sometimes applications seem to go into too-detailed reviews.
Please read Review process for security advisory coverage: What to expect for more details and Security advisory coverage application checklist to understand what reviewers look for. Tips for ensuring a smooth review gives some hints for a smoother review.
The important notes are the following.
Keep in mind that once the project is opted into security advisory coverage, only Security Team members may change coverage.
To the reviewers
Please read How to review security advisory coverage applications, Application workflow, What to cover in an application review, and Tools to use for reviews.
The important notes are the following.
For new reviewers, I would also suggest to first read In which way the issue queue for coverage applications is different from other project queues.
Comment #3
vishal.kadamFILE: update_email_customizer.module
For a new module that aims to be compatible with Drupal 10 and Drupal 11, I would rather implement hooks as class methods as described in Support for object oriented hook implementations using autowired services.
It would require increasing the minimum Drupal 10 version supported, but Drupal 10.1 is no longer supported.
Comment #4
mxr10 commentedThanks for the review.
I converted the module hooks to object-oriented hook implementations using autowired services.
I also added legacy hook compatibility for Drupal 10 and updated the minimum supported versions to Drupal 10.3 and Drupal 11.1.
The changes are available in commit:
6cbd44e - Convert hooks to object-oriented implementations
The GitLab CI pipeline passes successfully.
Comment #5
avpaderno@mxr Remember to change status, if you are done with changing the project files.
Comment #6
mxr10 commentedComment #7
pedroromán commentedReviewed 1.0.x at 6cbd44e.
src/Hook/UpdateEmailCustomizerHooks.php
The callbacks put the hook service object itself into the form array. Whenever that form is cached (form cache, AJAX, a rebuild after a validation error) Drupal serializes the array, and this object carries the config factory and the Twig environment, which cannot be serialized. Form callbacks need to be static or procedural; the services can be fetched inside them.
When nothing is saved yet, the textarea is filled with the starter template, and
saveSettingsSubmit()stores whatever the textarea holds. Saving the Update settings form for any other reason (for example the check frequency) silently turns the starter text into a custom template, and from then on the Twig default template is never used. Leave the field empty and show the starter as a#placeholderor in the description instead.The class re-implements
t()instead of usingStringTranslationTrait, and then casts every result with(string)even though the method already returns a string. Use the trait and drop the casts; keeping theTranslatableMarkupobjects is also what the render system expects.update_email_customizer.services.yml
That parameter is for modules that have no procedural hooks. This module keeps the
#[LegacyHook]functions in the .module file for Drupal 10, so the parameter is not needed; the attribute already tells Drupal 11 to skip them.README.md
The paragraph starting with "The module uses object-oriented hook implementations" appears twice. The Maintainers section has no maintainer; add your name and drupal.org profile link. The License section is not needed, drupal.org projects are GPL-2.0-or-later by definition.
Tests
The only test covers
TestEmailSender. The behaviour of the module is inmailAlter(): subject, headers and the token replacement in a custom template. A kernel test invokinghook_mail_alter()with anupdate_status_notifymessage would cover it.AI-Generated: Yes (AI tools helped with this review; I checked each point myself.)
Comment #8
mxr10 commentedThanks for the review.
I addressed the reported issues:
- Changed the form submit callbacks so the hook service object is no longer stored in the form array.
- Changed the starter template behavior so it is displayed as a placeholder when no custom template is saved, preventing it from being saved unintentionally.
- Replaced the custom translation helper with StringTranslationTrait and removed the unnecessary string casts.
- Removed the unnecessary skip_procedural_hook_scan parameter.
- Cleaned up the README, removed the duplicated paragraph and unnecessary License section, and added the maintainer information.
- Added a Kernel test covering mailAlter(), including the subject, headers, and token replacement with a custom template.
I also verified the module manually on Drupal 10.6.13:
- Configuration can be saved successfully.
- Custom templates are saved and restored correctly.
- The starter template is used when no custom template is configured.
- Test emails work from both the administration interface and Drush.
Tests:
- Kernel test: 1 test, 10 assertions - passed.
- Unit tests: 3 tests, 8 assertions - passed.
- GitLab CI pipeline #961521 passes successfully.
Changes are available in commit 498b5e3f.
Thanks again for the feedback.
Comment #9
pedroromán commentedTwo corrections to my review in #7.
update_email_customizer.services.yml: please ignore the point about
update_email_customizer.skip_procedural_hook_scan. Setting it is correct for a module whose remaining procedural functions are#[LegacyHook]bridges; core does the same in modules that keep a .module file.src/Hook/UpdateEmailCustomizerHooks.php: the form is not cached after a plain validation error, as I wrote. The serialization problem with
[$this, 'method']callbacks applies when the form is cached (AJAX or a rebuild), which is why static callbacks are still the safer choice.AI-Generated: Yes (AI tools helped with this review and with this correction.)
Comment #10
mxr10 commentedThanks for the clarification.
I restored `update_email_customizer.skip_procedural_hook_scan: true` as the remaining procedural hooks are `#[LegacyHook]` bridges.
The static form callbacks remain unchanged.
The change is available in commit 7ac7bb93, and GitLab CI pipeline #966154 passes successfully.
Thanks again for the review.