wieni / wmmailable
A modern, plugin-based API for sending mails in Drupal 8.
Installs: 16 299
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 5
Forks: 1
Open Issues: 6
Type:drupal-module
pkg:composer/wieni/wmmailable
Requires
- php: >=7.1.0
- drupal/core: ^9.3 || ^10.0 || ^11.0
- drupal/mailsystem: ^4.0
- tijsverkoyen/css-to-inline-styles: ^2.2
Requires (Dev)
- ergebnis/composer-normalize: ^2.0
- wieni/wmcodestyle: ^1.3
Suggests
- hampe/inky: to use the Foundation for Emails renderer
This package is auto-updated.
Last update: 2025-10-03 13:02:39 UTC
README
A modern, plugin-based API for sending mails in Drupal 8. Inspired by Laravel
Why?
- No 'modern' way to handle mails in Drupal 8: messing with
hook_mailandhook_themedoes not really fit in the Wieni Drupal flow with wmmodel, wmcontroller, etc. - No clean, object-oriented API, e.g. to add CC / BCC-adresses you have to manually add headers
- Not intuitive, logic is scattered across multiple files, tends to get messy
Installation
This package requires PHP 7.1 and Drupal 8 or higher. It can be installed using Composer:
composer require wieni/wmmailable
How does it work?
Building mails
- Mails are annotated plugins
- Each class represents one mail
- Dependency injection is possible by implementing the
ContainerFactoryPluginInterface(tutorial)
<?php namespace Drupal\wmcustom\Mail; /** * @Mailable( * id = "contact_form_submission", * template = "mail.contact-submission" * ) */ class ContactFormSubmission extends MailableBase { public function build(array $parameters): MailableInterface; }
- It is possible to take over other module's mails at the time of sending. To do this, change the
idandmoduleproperties. The original mail parameters will be passed to thebuildmethod. Example:
<?php namespace Drupal\wmcustom\Mail; /** * @Mailable( * id = "register_no_approval_required", * module = "user", * template = "mail.account-confirmation" * ) */ class AccountConfirmationMail extends MailableBase { public function build(array $parameters): MailableInterface { $parameters['oneTimeLoginUrl'] = user_pass_reset_url($parameters['account']); {...} } }
Theming mails
-
Mail templates should be stored in a theme. This theme can be set in the
themevalue of thewmmailable.settingsconfig, with the default theme as a fallback. -
The location of the template within the theme is also configurable:
- the default location is in the
mailsubfolder, with the id with dashes instead of underscores as template name. - a custom location can be set in the annotation, in the form of a path relative to the theme, with filename but without extension. Dots can be used as directory seperator.
- the default location is in the
-
The mail formatter determines how mails are rendered. Thanks to the mailsystem module, we can change the mail formatter separately from the mail sender. This module provides 3 formatters. The formatters as listed here are incremental: they all contain the features listed in the previous formatters.
- Mailable - Plain: the most basic mail formatter. Depending on the
passed
Content-Typeheader, this formatter will output HTML or plain text mails. - Mailable - With inline styles: allows you to attach
asset libraries to mails by
passing them to
MailableInterface::addLibraryor an array of asset libraries toMailableInterface::setLibraries. - Mailable - Foundation for Emails: allows you to compose mails using
the Inky templating language.
To use this formatter, you need to have the
thampe/inkypackage installed.
- Mailable - Plain: the most basic mail formatter. Depending on the
passed
Sending mails
- Mails are sent through the
Mailerservice - Two standard
Mailerimplementations are provided:mailable.mailer.directandmailable.mailer.queued - The active implementation can be changed in the
mailable.settings.ymlconfig
<?php namespace Drupal\wmcustom\Form; use Drupal\wmmailable\Mailer\MailerInterface; class ContactForm extends FormBase { /** @var MailerInterface */ protected $mailer; public function __construct( MailerInterface $mailer ) { $this->mailer = $mailer; } public function submitForm(array &$form, FormStateInterface $formState) { $mail = $this->mailer->create('contact_form_submission') ->setRecepients(['Wieni <info@wieni.be>', 'dieter@wieni.be']) ->addBcc('sophie@wieni.be') ->setParameters( compact('domain', 'firstName', 'lastName', 'email', 'question') ); $this->mailer->send($mail); } public static function create(ContainerInterface $container) { return new static( $container->get('mailable.mailer') ); } }
Logging sent mails
- When enabled, this wil log all outgoing mails - also those that aren't composed through this module.
- To enable, configure the mailsystem module to use Mailable - Logger as the mail sender.
- To view logged mails, go to
/admin/reports/sent-mailsor follow the menu link at Reports > Sent mails.
Hooks and events
- Two hooks are provided,
hook_mailable_alterandhook_mailable_{module}_{key}_alter. These hooks are called after thesendmethod is called on the mailable, but before the mail is sent.
<?php function wmcustom_mailable_alter(MailableInterface $mail) { $mail->setHeader('X-SES-SOURCE-ARN', '<...>'); }
- Two events are provided, equivalent to the hooks:
<?php use Drupal\wmmailable\Event\MailableAlterEvent; use Drupal\wmmailable\WmmailableEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class MailableAlterSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { $events[WmmailableEvents::MAILABLE_ALTER][] = 'onMailAlter'; return $events; } public function onMailAlter(MailableAlterEvent $event) { $mailable = $event->getMailable(); $mailable->setSubject("Here's a better subject."); } }
Changelog
All notable changes to this project will be documented in the CHANGELOG file.
Security
If you discover any security-related issues, please email security@wieni.be instead of using the issue tracker.
License
Distributed under the MIT License. See the LICENSE file for more information.