HTML mail - how to properly format message I am trying to implement html mail notifications using htmlmail module. I am not certain if message should be formatted as array in $message["body][] before the template or passed as a string in $message['body'].

The reason I am asking is that I first expected the email to be sent in as a string but then saw the HTMLMAILSystem::format function that flattens the body array:

  public function format(array $message) {
    $eol = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
    // @todo Remove this when issue #209672 gets resolved.
    $default_from = variable_get('site_mail', ini_get('sendmail_from'));
    if ( !empty($message['headers']['From'])
      &amp;&amp; $message['headers']['From'] == $default_from
      &amp;&amp; valid_email_address($default_from)
    ) {
      $message['headers']['From'] = '"'
      . str_replace('"', '', variable_get('site_name', 'Drupal'))
      . '" &lt;' . $default_from . '&gt;';
    }
    // Collapse the message body array.
    if (module_exists('mailmime')) {
      $body = $this-&gt;formatMailMIME($message);
      $plain = $message['MailMIME']-&gt;getTXTBody();
    }
    else {
      if (is_array($message['body'])) {
        $message['body'] = implode("&lt;br /&gt;$eol&lt;br /&gt;$eol", $message['body']);
      }
      $body = theme('htmlmail', $message);
      if ($message['body'] &amp;&amp; !$body) {
        watchdog(
          'htmlmail',
          'The %theme function did not return any text.  Please check your template file for errors.',
          array('%theme' =&gt; "theme('htmlmail', \$message)"),
          WATCHDOG_WARNING
        );
        $body = $message['body'];
      }


So if I understood correctly, message must be preformatted with correct html in $message["body"][] , but I am not 100% sure there are lots of code-bits involved for email sendouts. I also need to validate if this will allow me to send mail as plaintext?
In Drupal 7, it's the implementation of MailSystemInterface::format() that formats the message body and changes it to a string; before that, $message['body'] is supposed to be an array.
In Drupal 6, drupal_mail() receives an array for $message['body'], and changes it in a string.

// drupal_mail() in Drupal 6

// Build the e-mail (get subject and body, allow additional headers) by
  // invoking hook_mail() on this module. We cannot use module_invoke() as
  // we need to have $message by reference in hook_mail().
  if (function_exists($function = $module . '_mail')) {
    $function($key, $message, $params);
  }

  // Invoke hook_mail_alter() to allow all modules to alter the resulting e-mail.
  drupal_alter('mail', $message);

  // Concatenate and wrap the e-mail body.
  $message['body'] = is_array($message['body']) ? drupal_wrap_mail(implode("\n\n", $message['body'])) : drupal_wrap_mail($message['body']);


Compare the code you are showing with the code used by the Drupal 7 implementation (DefaultMailSystem::format()).

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;
}


Drupal requiring $message['body'] to be an array of strings is made clear in hook_mail_alter(), which describes it as follows:


'body': An array of strings containing the message text. The message body is created by concatenating the individual array strings into a single text string using "\n\n" as a separator.


Since hook_mail_alter() is invoked right before the format() method, that method is supposed to get an array, not a string.

 // drupal_mail() in Drupal 7

 // Bundle up the variables into a structured array for altering.
  $message = array(
    'id' =&gt; $module . '_' . $key,
    'module' =&gt; $module,
    'key' =&gt; $key,
    'to' =&gt; $to,
    'from' =&gt; isset($from) ? $from : $default_from,
    'language' =&gt; $language,
    'params' =&gt; $params,
    'send' =&gt; TRUE,
    'subject' =&gt; '',
    'body' =&gt; array(),
  );

  //  …

  // Build the e-mail (get subject and body, allow additional headers) by
  // invoking hook_mail() on this module. We cannot use module_invoke() as
  // we need to have $message by reference in hook_mail().
  if (function_exists($function = $module . '_mail')) {
    $function($key, $message, $params);
  }

  // Invoke hook_mail_alter() to allow all modules to alter the resulting e-mail.
  drupal_alter('mail', $message);

  // Retrieve the responsible implementation for this message.
  $system = drupal_mail_system($module, $key);

  // Format the message body.
  $message = $system-&gt;format($message);


The only reason I could see to check if $message['body'] is a string is to protect the code against modules not correctly updated in the passage from Drupal 5 to Drupal 6. In fact, Drupal 5 passed a string for body, as evident in the example for hook_mail_alter() shown in the documentation.

function hook_mail_alter(&amp;$mailkey, &amp;$to, &amp;$subject, &amp;$body, &amp;$from, &amp;$headers) {
  $body .= "\n\n--\nMail sent out from " . variable_get('sitename', t('Drupal'));
}