Mr Treublaan 1-3
1097 DP Amsterdam
The Netherlands

Sending html mails in Drupal 8/9 programmatically

An example Drupal module including Twig template
18 Aug, 2020 Drupal

Home Blog Sending html mails in Dr...

Drupal html mail example

Last month we implemented a user story for our Drupal distro OpenLucius: we needed to send clean html from Drupal 9 modules. This should also be scalable, as in: different modules should be able to mail different content in a consistent template. After some time of coding and trying different modules and options within those modules, we finally got it together in a nice, clean and scalable way.

So I thought more people would like to send nice html mails from Drupal 8/9 programmatically: I extracted the code and produced an isolated example module, even installable.

Copy and run off

I published it here on Github, so you can copy it and run off with it to do whatever you need. At the moment it's not a published Drupal.org project with all kinds of configurable stuff.

Install instructions

Clone this repo and install it like a custom module in Drupal; I haven't set it up with Composer / Packagist. The drupal module has a dependency on Swiftmailer module, which has a dependency on the Mailsystem Drupal module. After you installed it, these three modules should be enabled:

Config instructions

Configure Mailsystem Head to /admin/config/system/mailsystem and copy this config:

Drupal mailsystem
  1. Formatter: choose 'Swiftmailer'
  2. Sender: choose 'Default PHP Mailer', somehow it didn't work when I choose 'Swiftmailer' here. That took a loooong time to figure out.
  3. Choose your active theme (custom or contrib), this is needed so Swiftmailer will detect your clean html Twig override for the emails:

Copy Twig template override

Drupal HTML mail twig override

Copy the file 'swiftmailer--lucius-html-mail.html.twig' to your custom theme's '/templates' folder. This is the clean html email template override which Swiftmailer will use later on and you can tune anyway you like.

Swiftmailer config FYI, all 'Transport settings' in Swiftmailer config can be left to default (see /config/swiftmailer/transport).

Explaining the Drupal code

1. hook_mail() in .module file

First of all, to make use of the Drupal's mailing system: you need to implement hook_mail in the .module file:

Drupal hook mail
  1. Get global site name -and email.
  2. This took a loooooooooooooooooooong time to figure out, but you need to define these headers to make Drupal html mails work.
  3. Additional parameters to fill Twig html email template.

2. Custom Drupal Mail Service 'lucius_html_mail.mail'.

I implemented a custom Drupal Service 'lucius_html_mail.mail', for among other things scalability: this service handles all generic stuff for email sending, while other modules can use this service via Dependency injection and send mails with different parameters: message content in this case.

Drupal mail service
  1. Define our custom Mail Service and inject 2 external Services.
  2. Constructor to facilitate the 2 external Services.
  3. Build the mailing variables, loop through users, get name and email, finally send mails.

3. Drupal Route and Controller to test and send example emails

I defined a route '/send_test_mail'. If you head over to that url in your browser, the code in sendTestMail() will execute.

If all is ok: all users will receive the example mail.

!) So make sure you're testing this in an environment where mails can't go to the outside world, we use local Docker with Mailhog for example. (!

Drupal send test mail
  1. Drupal's Dependency Injection in action: inject our custom Service 'lucius_html_mail.mail'.
  2. Prepare all paramaters for the mail with static example texts. Then send the mails via our Service method 'sendMail()'.
  3. Simple helper function to get all users.

So, if you head over to '/send_test_mail', all users should receive an email that looks like this:

Drupal html mail example

4. Custom Twig override file 'swiftmailer--lucius-html-mail.html.twig'

As mentioned earlier, swiftmailer--lucius-html-mail.html.twig should be copied somewhere to your custom theme's /templates folder. I found this html code in this open source repo. It's even responsive and uses a lot of inline styles, needed to make it compatible to all major email clients.

Drupal clean email template

As you can see, there are Twig variables, mostly I use the values in the $message array. These variables match the parameters we build earlier. Function Lucius_html_mail_mail() (hook_mail) turned our parameters into one $message array, which can be used in the Twig template as shown in above image.

So tune this template anyway you like, or implement a complete new one with other variables. It's all in your hands now, make it the way you want in a clean, responsive and scalable way!

Handy: Twig template file override suggestions

If you turn on Development mode in Drupal, you can see all template suggestions to go even further down/up the road:

Drupal swiftmailer theme suggestions

Wrap up

Ok, that's it for now. Hopefully you're now able to implement nice clean emails for your Drupal 8/9 system. If you need more explanation, or you can't get it to work: please let me know.

Written by Joris Snoek | Aug 18, 2020
Let's Talk

Please tell me all about your project!
Mail , or send a message:

Got some more time?

Related content
09 May, 2023 Drupal

Save time, frustration, and potential content loss.


07 Jun, 2021 Drupal

Programmatically in multiple Views


02 Jun, 2021 Drupal