I want to theme the outgoing mail from the contact module, because the standard output looks horrible. Where can I do this? It's the one starting with admin (http://example.com/user/1) sent a message using the contact form at http://example.com/contact.

  • You need email plugin that can handle html. – user21641 Mar 3 '16 at 10:38
  • Can you give me a link to a working module for Drupal 8? – Fropper Mar 3 '16 at 13:41
  • I write mostly my own code so I don't have that good overview of modules anymore, sorry. Check out that mime mail mentioned in the response below if it has d8 version. – user21641 Mar 3 '16 at 16:53

I was able to get Berdir's answer working in Drupal 8.1.0. But I had to do a number of things to get it going.

  1. Install mailsystem, swiftmailer, contact_storage, and contact (core) modules
  2. Setup a custom contact form, configure it and add fields as needed.
  3. Configure swiftmailer message settings (/admin/config/swiftmailer/messages) to use HTML.
  4. Configure swiftmailer transport settings (/admin/config/swiftmailer/transport) to preferred transport type
  5. Configure mailsystem default mail system settings to use swiftmailer for both formatter and sender plugins. I assume you could also configure per module in the later section if you like, however I did not try it.
  6. Under /admin/structure/display-modes/view add a new view mode for Contact message, setting it's namespace to mail. This is the view mode that will be used when sending the email (somewhere this is hardcoded from what I can tell).
  7. If you want a pretty display of the Contact message nodes on the site then you will also want to create a full view mode and configure that too.
  8. Configure your view modes under the custom contact form you created. The Display Suite module really allowed for customizing the markup with it's field templates made available in display suite extras.

Note, I also have Berdir's MessageViewBuilder override in a custom module but I am unsure it is any longer necessary. I have not attempted to remove it yet.

  • How should I name my twig template, so that it will be used for the outgoing mail? I added a display mode view named mail, so I guess it should be swiftmailer--contact--mail.html.twig. But unfortunately it's not beeing used. – Philipp Michael Aug 16 '16 at 15:17
  • Could you please clarify how to use a custom mail template with contact message fields (not just output {{ body }})? Your answer helped me alot but this seems to be a missing step to get it done (at least for me). – Philipp Michael Aug 16 '16 at 16:09
  • @PhilippMichael I wouldn't know as I didn't use them. I did all markup changes using the view mode and display suite, it works nicely. For any custom elements you need included on the view mode you can implement a pseudo field in a custom module, but that is beyond the scope of this answer. – nicholas.alipaz Aug 16 '16 at 20:18
  • Currently I'm not using Dispay Suite but I will have a look. Thanks. But I managed to use a custom template by applying a theme in hook_contact_message_view(). But now my body html is handled as plain text (might be another issue). Templating the outgoing contact email is so hard and frustrating -.- – Philipp Michael Aug 17 '16 at 7:48
  • 1
    @PhilippMichael yes see Berdir's message about #2223967, I did use that workaround. – nicholas.alipaz Aug 18 '16 at 18:41

I'd recommend Swiftmailer to send HTML mails in 8.x.

But for contact forms, a number of core issues/limitations currently prevent that from working nicely. See https://www.drupal.org/node/2666160 (patch needed, or use of D8 core 8.1.0+) and https://www.drupal.org/node/2223967 (workaround needed/possibly by replacing the contact message view builder and setting the content type of contact mails to HTML), something like this:

 * Implements hook_entity_type_alter().
 * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
function yourmodule_entity_type_alter(array &$entity_types) {

 * Implements hook_mail_alter().
function yourmodule_mail_alter(&$message) {
  if ($message['module'] == 'contact' && isset($message['params']['contact_message'])) {
    // Enforce that we are sending mails as HTML.
    $message['headers']['Content-Type'] = 'text/html';

namespace Drupal\yourmodule;

use Drupal\contact\MessageViewBuilder;
use Drupal\Core\Entity\EntityInterface;

 * Customized contact message view that does not do HTML to plain conversion.
class ContactMessageViewBuilder extends MessageViewBuilder {

   * {@inheritdoc}
  public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
    $build = parent::view($entity, $view_mode, $langcode);
    // Remove the post render callback that converts the HTML to plain text.
    return $build;

For theming the outgoing contact mail you can get a node and its body. After that you can set it as mail body. Use hook_mail_alter(). This requires the Swift Mailer module.

use Drupal\Core\Render\Markup;

function hook_mail_alter(&$message) {

  if ($message['id'] == 'contact_page_mail') {

    $contact_message = $message['params']['contact_message'];

    //load the node that has html body 
    $node   = \Drupal\node\Entity\Node::load(155);
    $record = $node->body->value;

    //replace the params as per you requirement
    $record = str_replace("@name", $contact_message->get('field_name')->getValue()[0]['value'], $record);

    $message['body'][1] = $record;
    $message['body'][1] = Markup::create($message['body'][1]);
  • Thanks a lot! I needed to fix mailing for $message['id'] == 'contact_page_autoreply' since the auto-reply didn't seem to be sent in HTML at all. – leymannx Jan 16 '17 at 21:15

Sounds like you need the Mime Mail module first. It will allow your website to send HTML emails, and give you a way to change the template.

  • 1
    It seems the Mime Mail module isn't working with Drupal 8 yet. I get an error when trying to access the modules settings FastCGI sent in stderr: "PHP message: Recoverable fatal error: Argument 2 passed to Drupal\mimemail\Form\AdminForm::__construct() must be an instance of Drupal\mailsystem\MailsystemManager, instance of Drupal\webprofiler\Mail\MailManagerWrapper given, called in /var/www/drupal/modules/mimemail/src/Form/AdminForm.php on line 60 and defined in /var/www/drupal/modules/mimemail/src/Form/AdminForm.php on line 44 – Fropper Mar 3 '16 at 9:07

Just want to add to @nicholas.alipaz answer.
If you followed until point #8 and used dispaly-suit module.
Go to admin/structure/contact/manage/YOURCONTACTFORM/display/mail

scroll down to: 'Layout for YOURCONTACTFORM in mail'.
Under 'Select a layout' choose 'one column layout' you should be presented by tempalte suggestions.
Choose one of them. I chose ds-1col--contact-message.html.twig
I copied modules/contrib/ds/templates/ds-1col.html.twig in my theme's tempalte folder, renamed it ds-1col--contact-message.html.twig and editted it to my likings.
It's a bit simple email temaplate but it worked nicely for my simple contact form.


Drupal 8 with mailsystem, swiftmailer will not use the swiftmailer.html.twig for your outgoing contact mails. Resulting mail message is not easy to reade (nor theme )

You can get rid of the default message and send a brand new one via \Drupal::service('plugin.manager.mail')

This will let you send HTML formatted email as per your swiftmailer.html.twig

@TODO: give HTML to the actual message

Sample code

 * implements hook_mail_alter()
function YOUR_MODULE_mail_alter(&$message) {

  if (!empty($message['id']) ) {

    switch ($message['id']) {
      case 'contact_user_mail':

      // thanks to https://www.zyxware.com/articles/5504/drupal-8-how-to-send-a-mail-programmatically-in-drupal-8
      $options = Array();
      send_a_brand_new_mail($message, $options);

      // Instead of forwarding to dustbinm, how to destroy default contact message?
      $message['to'] = "somewhere@dustbin";

 * Implements hook_mail().
function YOUR_MODULE_mail($key, &$message, $params) {
  $options = array('langcode' => $message['langcode']);
  switch ($key) {
    case 'YOUR_KEY':
      $messaggio = $message['params']['contact_message']->get('message')->getValue(0);

      //re-use from contact.module
      $contact_message = $params['contact_message'];

      /** @var $sender \Drupal\user\UserInterface */
      $sender = $params['sender'];
      $language = \Drupal::languageManager()->getLanguage($message['langcode']);

      $variables = [
        '@site-name' => \Drupal::config('system.site')->get('name'),
        '@subject' => $contact_message->getSubject(),
        '@form-url' => Url::fromRoute('<current>', [], ['absolute' => TRUE, 'language' => $language])->toString(),
        '@sender-name' => $sender->getDisplayName(),

      $variables += [
        '@recipient-name' => $params['recipient']->getDisplayName(),
        '@recipient-edit-url' => $params['recipient']->toUrl('edit-form', ['absolute' => TRUE, 'language' => $language])->toString(),

      if ($sender->isAuthenticated()) {
        $variables['@sender-url'] = $sender->toUrl('canonical', ['absolute' => TRUE, 'language' => $language])->toString();
      else {
        $variables['@sender-url'] = $params['sender']->getEmail();
      $options = ['langcode' => $language->getId()];
      $message['subject'] .= $message['params']['title'] ;
      $message['body'][] = t('Hello @recipient-name,', $variables, $options) . "\r\n\r\n";
      $message['body'][] = t("@sender-name (@sender-url) sent a message using the contact form at @form-url.", $variables, $options);

      // you can at least add some blank rows here
      $message['body'][] = "\r\n\r\n";
      $message['body'][] = ">>>\r\n\r\n";
      $message['body'][] = Html::escape($messaggio[0]['value']);
      $message['body'][] = "<<<"."\r\n\r\n";

function send_a_brand_new_mail($message, $options) {

  $mailManager = \Drupal::service('plugin.manager.mail');
  $module = 'YOUR_MODULE';
  $key = 'YOUR_KEY'; // Replace with Your key
  $to = \Drupal::currentUser()->getEmail();

  $params = $message['params'];
  $params['message'] = $params['contact_message'];
  $params['title']   = $message['subject'];
  $langcode = \Drupal::currentUser()->getPreferredLangcode();
  $send = true;
  $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
  if ($result['result'] != true) {
    $message = t('There was a problem sending your email notification to @email.', array('@email' => $to));
    drupal_set_message($message, 'error');

  $message = t('Your message was emailed to @email ', array('@email' => $to));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.