I am trying to log emails to watchdog for testing in my local dev environment.

function MYMODULE_mail_alter(&$message) {
  // First: Prevent the mail from being sent.
  $message['send'] = FALSE;

  // Next: Log the mail so it can be debugged if necessary
  $logemail = $message['subject'] .'\nThe following email was not sent: \n<pre>Subject:<br>' . $message['subject'] . '<br>Body:<br>'  . $message['body'][0] . '</pre>';
  watchdog('MYMODULE', '@logemail', array('@logemail' => $logemail), WATCHDOG_ALERT);

However, this gives me a value for Message that doesn't have any line breaks and ignores my HTML <br> and \n:

Patrick K, new members for the week of April 23\nThe following email was not sent: \n<pre>Subject:<br>Patrick K, new members for the week of April 23<br>Body:<br><p>Dear Patrick K,</p> <p>We haven't seen you in awhile. Hundreds of people have joined since you last logged in.</p> <p><a href="">Log in now and say hello to our newest members!</a></p></pre>

How can I get the line breaks and HTML to be rendered in the watchdog message?

3 Answers 3


However, this gives me a value for Message that doesn't have any line breaks and ignores my HTML <br> and \n

As well it should :)

You've wrapped the HTML message in a <pre> 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 <pre> 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 <br> automatically if the message content was dynamic, but since you're using a literal string, you might as well just be explicit and use <br> instead of \n when you want a line break.

This is a basic working example:

$message = [
  'subject' => 'test subject',
  'body' => ['<div class="test">some content<br />On a new line</div>'],

$allowed_tags = array('div', 'a', 'table', 'br', 'etc...');
$output = '!subject <br />The following email was not sent: <br />Subject:<br />!subject<br />Body:<br />!body';
$args = array('!subject' => filter_xss($message['subject'], $allowed_tags), '!body' => 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.


Can you try with the below.

watchdog("my_module", '<pre>' . print_r( $my_array_or_object, true) . '</pre>');
  • 1
    Watchdog docs say: "Keep $message translatable by not concatenating dynamic values into it! Variables in the message should be added by using placeholder strings alongside the variables argument to declare the value of the placeholders." The correct way of doing this would be: watchdog('my_module', '<pre>!my-array-or-object</pre>', array('!my-array-or-object' => print_r($my_array_or_object, true)));
    – KingAndy
    Commented Feb 20, 2018 at 16:43

I can't believe no one mentioned this before, but \n will be interpreted by PHP as char \ and char n when the string is delimited by single quotes. You need to use double quotes.

$logemail = $message['subject'] . "\nThe following email was not sent...";

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.