So as the title explains, when sending an HTML email with drupal_mail(), email comes with no HTML tags.

    $module = 'module';
    $key = 'contact_message';
    $language = language_default();
    $params = array();
    $email = '[email protected]';
    $from = variable_get('site_mail', '[email protected]');
    $send = TRUE;
    $message = drupal_mail($module, $key, $email, $language, $params, $from, $send);
    $message['headers']['Content-Type'] = 'text/html; charset=UTF-8';
    $message['subject'] = 'Test';
    $message['body'] = array();
    $message['body'][] = '<a href="#">Testing anchor in mail</a>';
    $system = drupal_mail_system($module, $key);
    $message = $system->format($message);
    $message['result'] = $system->mail($message);

And when recieving the email, and viewing the source:

Message-Id: <[email protected]>
X-Authentication-Warning: testserver : www-data set sender to [email protected] using -f
To: [email protected]
Subject: Test
X-PHP-Originating-Script: 1000:system.mail.inc
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
Sender: [email protected]
From: [email protected]

Testing anchor in mail [1]

[1] #

So you can see that any HTML tags were stripped. And it doesn't matter what HTML tags I put in body.

I thought it might be related to Text Fomats, but I have "Filtered HTML" and "Full HTML" active filters with any permissions.

The thing confused me were the Ubercart invoices. At first they were sent with HTML, and then at some point it stopped. They were received plain text. After digging a bit @develkar answer, I've found this in one of ubercart updates:

 * Installs HTML Mail System for Ubercart.
function uc_store_update_7004() {
  // Set mail handler for all Ubercart modules
      variable_get('mail_system', array('default-system' => 'DefaultMailSystem')),
        'uc_cart'  => 'UbercartMailSystem',
        'uc_order' => 'UbercartMailSystem',
        'uc_file'  => 'UbercartMailSystem',
        'uc_roles' => 'UbercartMailSystem',
        'uc_stock' => 'UbercartMailSystem',
        'uc_store' => 'UbercartMailSystem',

I guess that at some point, one of installed modules (I suspect SMTP module) overridden this variable, and that's why emails were coming plain text. After running this update manually again, Ubercat invoices are HTML again.

For the rest of emails, I'll have to install some modules as suggested in other answers.


4 Answers 4


drupal_mail(), by default sends a mail as plain text.

If you print out the array $message['headers'], you will get something like:

    'MIME-Version' => '1.0',
    'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
    'Content-Transfer-Encoding' => '8Bit',
    'X-Mailer' => 'Drupal',

As you can see, the Content-Type in the mail header is text/plain; charset=UTF-8; format=flowed; delsp=yes. You can try by modifying this header in hook_mail_alter(), you could use one of the modules which allows you to send the mail as HTML, like HTML Mail, or Mime Mail.


Following the comments by @Ayesh and @alechko and after looking into the APIs, I found out that the headers are not the only reason for sending the mail as plain text. Because drupal_mail() internally makes a call to drupal_mail_system(), which returns an object that implements the MailSystemInterface interface. The format() method implemented by drupal_mail_system() is responsible for stripping out the HTML from the emails. So, even if the headers of the mail show the formats to be HTML, the mails would be sent as plain text only. So, I guess one could not send an HTML mail using drupal_mail(). You should look for some other alternative (module) mentioned above.

  • Even though you set the ctype, Drupal strips all HTML tags in the preparation step (can't remember method name).
    – AKS
    Commented May 9, 2013 at 7:46
  • If you'd look in my output of received mail, you'd see that: Content-Type: text/html; charset=UTF-8
    – alechko
    Commented May 9, 2013 at 7:55
  • @AyeshK You are right. I have made the edit, the function responsible for stripping HTML is drupal_mail_sytem().
    – AjitS
    Commented May 9, 2013 at 8:11
  • @alechko Please see for the edit.
    – AjitS
    Commented May 9, 2013 at 8:11
  • Thanks @develkar :) . Actually the header change does the trick in D6, and I recently had to create a custom mail class to handle HTML emails. Still using drupal_mail, and overriding the rendering methods only.
    – AKS
    Commented May 9, 2013 at 8:19

In hook_mail also,you can define the headers as text/html,then you will get mail as an html format,as for example:

$message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';

Give a try with HTML Mail module installed and configured.

Lets you theme your messages the same way you theme the rest of your website.

  • I tried and it worked, but I was looking for native solution, because in the past, same installation was sending HTML emails, and after some point I've noticed that the emails came stripped. I had no "Helper modules" in the past.
    – alechko
    Commented May 9, 2013 at 7:52

It doesn't matter what the header Content-Type is, Drupal's default mail system converts html to plain text. See DefaultMailSystem::format() in mail.inc

public function format(array $message) {
// Join the body array into one string.
$message['body'] = implode("\n\n", $message['body']);
// Convert any HTML to plain-text.
$message['body'] = drupal_html_to_text($message['body']);
// Wrap the mail body for sending.
$message['body'] = drupal_wrap_mail($message['body']);
return $message;


To send allow html in the message body you will need to:

  1. create a custom mail system class that implements MailSystemInterface that has a format method that does not convert html to plain text
  2. Include that new class in your modules.info file
  3. Let Drupal know you want to use your custom mail system class

    variable_set('mail_system', array('default-system' => 'ExampleMailSystem'));

  4. Set the Content-Type header from "text/plain" to "html/plain"

    $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';

This documentation on d.o. does a good job of describing the solution and providing an example.


  • This looks doable. Would it be possible to switch the mail_system just on particular occassions, like in a webform submission handler for only some webforms ?
    – commonpike
    Commented Dec 28, 2017 at 19:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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