uc_order_mail() splits the mail body of html mails up in multiple elements and this leads to some strange rendering behaviours (like escaped html). I think the bug comes from that hook_mail needs the body as an array. But one element in that array is what we need to output valid HTML.

See patch.

htmlmail.patch645 bytesbjaxelsen


bjaxelsen created an issue. See original summary.

TR’s picture

Status: Needs review » Postponed (maintainer needs more info)

So I finally got around to looking at this ... I guess I don't exactly understand why there's a problem, so the proposed fix seems magical.

explode(), which we currently use, returns an array. So we currently *are* assigning an array to the 'body' element of the e-mail, just like the documentation says we should. Also, it says 'body' is by default an empty array, so we're not overwriting anything in there already.

As far as I can tell, your patch just puts everything including the embedded line separators into one array element, instead of what we currently do which is to split the body at \n separators then put these separate lines into separate array elements of the body and let drupal_mail() handle the separators. That's what the documentation says we should do. See https://api.drupal.org/api/drupal/core%21core.api.php/function/hook_mail...

The core contact.module (contact_mail() implements hook_mail()) is similar to uc_order_mail() in that it adds multiple lines to the body instead of putting everything on one line.

However, it wouldn't surprise me a bit to learn the documentation is outdated or wrong ... But I can't find a change notice that describes anything that affected what should go into the body.

bjaxelsen’s picture

Just to clarify:

The problem I ran into was:
Because each newline (not each HTML elements) triggers a new subelement in the mail body, the HTML of each body element is no more correct HTML due to open tags and HTML gets escaped. This is a problem we need to solve.

If we look at contact_mail we have this code:

$message['body'][] = t('Hello @recipient-name,', $variables, $options);
$message['body'][] = t("@sender-name (@sender-url) has sent you a message via your contact form at @site-name.", $variables, $options);
$message['body'][] = t("If you don't want to receive such emails, you can change your settings at @recipient-edit-url.", $variables, $options);
$build = entity_view($contact_message, 'mail');
$message['body'][] = \Drupal::service('renderer')->renderPlain($build);

As you can see, the HTML part (the last element) is contained in a single subelement. So we don't get broken HTML here.

And in the API documentation, in hook_mail:

$message['body'][] = MailFormatHelper::htmlToText($body);

This is also an array, but the HTML is contained in a single array value. This is what I want to do.

So the problem is not that we need to put everything is one subelement, but it is that when we have a HTML structure (like a table element with rows and columns), we cannot split it up for every newline without breaking the HTML structure and causing problems.