HTML mail without using modules I am trying to use the MailManager class in Drupal 8 to send HTML mail. I got it working, but it isn't parsing the HTML markup. I think something is wrong with the headers of the email.

What I have is a custom module (Custom_forward) that contains a form and that calls Mailmanager::mail() in its submitForm() method, which contains the following code.

        // Email body
        $header = $sender . ' thought you would like to see this page from the website.';
        $personal_message = $form_state-&gt;getValues()['message_body'];
        $entity_url_value = '&lt;a href="' . $entity_url-&gt;toString() . '"&gt;Go to article&lt;/a&gt;';
        $message = $header . '&lt;br&gt;' . $personal_message . '&lt;br&gt;' . $entity_url_value;

        // Email
        $langcode = 'en';
        $mailManager = \Drupal::service('plugin.manager.mail');
        $to = $form_state-&gt;getValues()['recipient'];

        $params['title'] = 'Forward';
        $params['message'] = $message;
        $result = $mailManager-&gt;mail('custom_forward', 'forward', $to, $langcode, $params, NULL, true);

        if ($result['result'] !== true) {
            drupal_set_message(t('There was a problem sending your message and it was not sent.'), 'error');
            \Drupal::logger('mail-log')-&gt;error($message);
        }
        else {
            drupal_set_message(t('Your message has been sent.'));
        }


According to Drupal you also need the hook_mail method in mytheme.theme to be able to send message, you can see this method here:

function custom_forward_mail($key, &amp;$message, $params) {
  $message['body'] = [];
  $message['subject'] = [];
  $message['headers'] = array(
    'content-type' =&gt; 'text/html',
    'charset' =&gt; 'UTF-8',
    'format' =&gt; 'flowed',
    'delsp' =&gt; 'yes',
    'from' =&gt; \Drupal::config('system.site')-&gt;get('mail')
  );

  switch ($key) {
    case 'forward':
      $message['subject'] = $params['title'];
      $message['body'][] = '&lt;html&gt;&lt;body&gt;' . $params['message'] . '&lt;/body&gt;&lt;/html&gt;';
      break;
  }
}


As you can see, I am setting the content type to text/html and that should tell the mail system to parse the content as an HTML, but this is not working for some reasons.

This is a testing email. All the HTML markup is not shown, but also not working.

Bassem thought you would like to see this page from the website. personal message Go to article [1] [1] http://myhost/node/81
Without any module it is not possible to send HTML emails. This is because the default plugin the MailManager class (which is a plugin manager) uses to effectively send emails contains the following code. (See PhpMail.php.)

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'] = MailFormatHelper::htmlToText($message['body']);

    // Wrap the mail body for sending.
    $message['body'] = MailFormatHelper::wrapMail($message['body']);
    return $message;
  }


The comment clearly states: Convert any HTML to plain-text.

If you look at MailFormatHelper::htmlToText(), you will see the code that is converting the HTML markup in plain text, in particular the following that changes any &lt;a&gt; tag as you saw in your test email.

  // Replace inline &lt;a&gt; tags with the text of link and a footnote.
  // 'See &lt;a href="https://www.drupal.org"&gt;the Drupal site&lt;/a&gt;' becomes
  // 'See the Drupal site [1]' with the URL included as a footnote.
  static::htmlToMailUrls(NULL, TRUE);
  $pattern = '@(&lt;a[^&gt;]+?href="([^"]*)"[^&gt;]*?&gt;(.+?)&lt;/a&gt;)@i';
  $string = preg_replace_callback($pattern, 'static::htmlToMailUrls', $string);
  $urls = static::htmlToMailUrls();
  $footnotes = '';
  if (count($urls)) {
    $footnotes .= "\n";
    for ($i = 0, $max = count($urls); $i &lt; $max; $i++) {
      $footnotes .= '[' . ($i + 1) . '] ' . $urls[$i] . "\n";
    }
  }


You need a module that defines a new mail plugin using a different implementation of the format() method and make the MailManager class use it. As said in the documentation for MailManager::getInstance(), the class uses the configuration in system.mail.interface. (The array returned from \Drupal::config('system.mail.interface').) In your example, an array value for custom_forward_formard (e.g. 'custom_forward_forward =&gt; 'custom_forward_mail', where custom_forward_mail is the plugin ID for the class implemented by your module) would do the trick.