Mail Composer: Sending multilingual HTML emails with Drupal

04 Febr. 2026
Druplicon with email

A new solution to Drupal's messy mailing approach

Drupal core's mail module has been a mess for a long time and has seemingly not kept up with the modernization of the rest of the stack. Using the hook system to send emails feels archaic; therefore, a while ago, we started developing a module that:

  • Allows for defining emails in code via a clean and powerful (chaining) object-oriented interface
  • Supports sending HTML emails without any fuss
  • Optionally allows for defining (HTML) emails as Twig templates
  • Allows for translating said emails by simply adding more Twig templates in different languages (multilingual capabilities)
  • Integrates with Drupal's default framework for email manipulation, which handles the transporting and formatting of outgoing emails
  • Can be used as the backend for bespoke UI-driven mailing solutions

We have been using and improving Mail Composer and would love for that work to be reused and further built upon.

Let's talk code

Just sending an inline email

... is as simple as:

/** @var \Drupal\mail_composer\Manager $manager */
$manager = \Drupal::service('mail_composer.manager');

$manager
->compose()
->setFrom('foobar@foo.bar')
->setTo('foo@bar.bar')
->setSubject('Test subject')
->setBody(['This is the body of the email.'])
->send();

Neat, isn't it?

Multilingual HTML emails

In order to send HTML emails, install Mail System and the replacement for the now-unsupported Swift Mailer: Symfony Mailer Lite. The only thing left to do is set Symfony Mailer Lite as the default formatter and sender in /admin/config/system/mailsystem:

Mail System configuration page

That's all that is necessary to send valid HTML emails.

Now let's dive into defining emails in code.

1. Define an Email

Drupal\my_module\TestEmail

namespace Drupal\my_module;

use Drupal\mail_composer\Email;

class TestEmail extends Email {

 /**
  * @inheritDoc
  */
 public function getSubject(): string {
   return $this->t('My test email');
 }

 /**
  * @inheritDoc
  */
 public function getFrom(): string {
   return 'foobar@foo.bar';
 }

}

Bear in mind, TestEmail::getSubject() and TestEmail::getFrom() are optional; you can set or override these values later during runtime when using the manager.

2. Define email content as Twig templates

my_module/templates/emails/test-email.html.twig

<p>This is the body of the <strong>email</strong> with variable {{ my_variable_1 }} and
{{ my_variable_2 }}.</p>

3. Translate the email into (e.g.) German

To translate the email content, just create another twig template with the correct country code in its name. The translation is picked up automatically when sending the email.

my_module/templates/emails/test-email.de.html.twig

<p>Das ist der Textkörper der <strong>E-Mail</strong> mit der Variablen {{ my_variable_1 }} und
{{ my_variable_2 }}.</p>

Defining email content as Twig templates is also optional (though preferred). You could alternatively set this content when using the manager via Manager::setBody() like an animal.

4. Send the email

/** @var \Drupal\mail_composer\Manager $manager */
$manager = \Drupal::service('mail_composer.manager');

$variables = ['my_variable_1' => 'foo', 'my_variable_2' => 'bar'];
$email = new \Drupal\my_module\TestEmail($variables);
$manager->compose($email)->setTo('foo@bar.bar')->send();

Try it and let me know what you think

If you are interested in seeing more examples, check out the module's documentation.

This module has been in production on two of our large-scale sites and has been working very well. Please download and use it, and let me know what you think below (or create requests in the module's queue): Mail Composer.

Neuen Kommentar hinzufügen

Der Inhalt dieses Feldes wird nicht öffentlich zugänglich angezeigt.

Restricted HTML

  • Erlaubte HTML-Tags: <a href hreflang target> <em> <strong> <cite> <blockquote cite> <pre> <ul type> <ol start type> <li> <dl> <dt> <dd> <h4 id> <h5 id> <h6 id>
  • Zeilenumbrüche und Absätze werden automatisch erzeugt.
  • Website- und E-Mail-Adressen werden automatisch in Links umgewandelt.

Angebot innerhalb von 24 Stunden

Wether a huge commerce system, or a small business website, we will quote the project within 24h of you pressing the following button: Get quote