How do I print line breaks and HTML in a watchdog message?
However, this gives me a value for Message that doesn't have any line breaks and ignores my HTML &lt;br&gt; and \n


As well it should :)

You've wrapped the HTML message in a &lt;pre&gt; tag, whose job is simply to preserve everything within as literal text, so that the browser won't interpret it as HTML. To fix, just remove the &lt;pre&gt; tags. If there's a possibility the email content could have been user-submitted, run it through filter_xss() first with an appropriate list of permitted tags, to avoid pain when you view the log message.

At the same time, \n isn't an escape char in HTML, so that's treated literally and rendered as text. It's an escape char in PHP, but it won't affect the outcome here as browsers collapse multiple whitespace chars into a single space anyway.

You could use PHP's nl2br to convert \n to &lt;br&gt; automatically if the message content was dynamic, but since you're using a literal string, you might as well just be explicit and use &lt;br&gt; instead of \n when you want a line break.

This is a basic working example:

$message = [
  'subject' =&gt; 'test subject',
  'body' =&gt; ['&lt;div class="test"&gt;some content&lt;br /&gt;On a new line&lt;/div&gt;'],
];

$allowed_tags = array('div', 'a', 'table', 'br', 'etc...');
$output = '!subject &lt;br /&gt;The following email was not sent: &lt;br /&gt;Subject:&lt;br /&gt;!subject&lt;br /&gt;Body:&lt;br /&gt;!body';
$args = array('!subject' =&gt; filter_xss($message['subject'], $allowed_tags), '!body' =&gt; filter_xss($message['body'][0], $allowed_tags));
watchdog('MYMODULE', $output, $args, WATCHDOG_ALERT);


It's worth noting that the list view of the watchdog messages strips out HTML, so without the spaces after the first !subject and not sent:, some of the message will run together and make it harder to read at a glance.