Table of Contents
Better Email Notifications with HTML formatting
This hack was in part inspired by the beautiful page change notifications sent out by other wiki software such as PBWiki, which uses HTML formatting instead of plain-text, and in part inspired by the existing diff rendering system in DokuWiki. I figured if DokuWiki is already capable of generating nicely formatted diff of page changes, I could tap into the system to send out HTML-formatted page notifications.
UPDATEs:
- Instructions updated for DokuWiki 2008-04-11 RC2.
- edited hack for notification on new pages
- tested and working on DokuWiki 2008-05-05
- tested and working on DokuWiki 2009-12-25c
- tested and working on DokuWiki 2011-05-25a
Screenshots of before and after
please host this last image on your own website… i can't guarantee the imgshare link will last.
What you need
- Plain text editor1)
- DokuWiki files you'll be editing:
- inc/mail.php
- inc/common.php
Applying the hack
inc/mail.php
First, we need to create a new function that can handle our HTML e-mails. We'll do so by creating one based on mail_send() in mail.php. Open up the file and locate the mail_send() function
function mail_send($to, $subject, $body, $from='', $cc='', $bcc='', $headers=null, $params=null){
at line 364) of an unmodified mail.php. Insert the following code just above the mail_send() function.
/*********************************** * HTML Mail functions * * Sends HTML-formatted mail * By Lin Junjie (mail [dot] junjie [at] gmail [dot] com) * ***********************************/ function mail_send_html($to, $subject, $body, $bodyhtml, $from='', $cc='', $bcc='', $headers=null, $params=null){ if(defined('MAILHEADER_ASCIIONLY')){ $subject = utf8_deaccent($subject); $subject = utf8_strip($subject); } if(!utf8_isASCII($subject)) { $subject = '=?UTF-8?Q?'.mail_quotedprintable_encode($subject,0).'?='; // Spaces must be encoded according to rfc2047. Use the "_" shorthand $subject = preg_replace('/ /', '_', $subject); } $header = ''; $usenames = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true; $random_hash = md5(date('r', time())); // added $to = mail_encode_address($to,'',$usenames); $header .= mail_encode_address($from,'From'); $header .= mail_encode_address($cc,'Cc'); $header .= mail_encode_address($bcc,'Bcc'); $header .= 'MIME-Version: 1.0'.MAILHEADER_EOL; $header .= "Content-Type: multipart/alternative; boundary=PHP-alt-".$random_hash.MAILHEADER_EOL; $header .= $headers; $header = trim($header); $body = mail_quotedprintable_encode($body); $bodyhtml = mail_quotedprintable_encode($bodyhtml); $message = "--PHP-alt-".$random_hash."\r\n". "Content-Type: text/plain; charset=UTF-8"."\r\n". "Content-Transfer-Encoding: quoted-printable"."\r\n\r\n". $body."\r\n\r\n". "--PHP-alt-".$random_hash."\r\n". "Content-Type: text/html; charset=UTF-8"."\r\n". "Content-Transfer-Encoding: quoted-printable"."\r\n\r\n". $bodyhtml."\r\n". "--PHP-alt-".$random_hash."--"; if($params == null){ return @mail($to,$subject,$message,$header); }else{ return @mail($to,$subject,$message,$header,$params); } }
The function has the added advantage of sending along the standard plain-text version for mail clients that cannot display HTML formatting. That's all for mail.php.
inc/common.php
There are three parts of hack to apply to common.php.
Part 1
First, we need to intercept the mailing action and generate a HTML-formatted version of the notification. Locate the following code
$diff = $dformat->format($df);
in the notify() function at line 8775) of an unmodified common.php and insert the following code right after it:
/*********************************** * Generate HTML Notification Hack (Part 1) * * inc/common.php * By Lin Junjie (mail [dot] junjie [at] gmail [dot] com) * ***********************************/ $df = new Diff(explode("\n",htmlspecialchars(rawWiki($id,$rev))), explode("\n",htmlspecialchars(rawWiki($id,'')))); $left = '<a href="'.wl($id,"rev=$rev",true).'">'. $id.' '.strftime($conf['dformat']).'</a>'; $right = '<a href="'.wl($id,'',true).'">'. $id.' '.strftime($conf['dformat'],@filemtime(wikiFN($id))).'</a> ('. $lang['current'] . ')'; $tdf = new TableDiffFormatter(); $diffHTML = "<html>\n<body>\n<h1 style=\"font-size: xx-large;\"><a href=\"".wl($id,'',true)."\"><font color=\"#FF6600\">".$id. "</font></a> was just edited</h1>\n<h2 style=\"font-size: large;\">by <font color=\"#999999\"><b>". $_SERVER['REMOTE_USER']."</b></font> on ".strftime($conf['dformat'])."</h2><br />\n"."<table ". "width=600 style=\"font-family: courier new; font-size:medium;\">\n<tr>\n<th colspan=\"2\" ". "width=\"50%\" style=\"border-bottom: 1px solid #333333; font-weight: bold; text-align: left;\">\n". $left."\n</th>\n<th colspan=\"2\" width=\"50%\" style=\"border-bottom: 1px solid #333333; ". "font-weight: bold; text-align: left;\">".$right."</th>\n</tr>".$tdf->format($df). "</table>\n"."<br />\n<p style=\"font-size: medium;\">---<br />\nThis mail was ". "automatically generated by DokuWiki at<br/>\n<a href=\"".DOKU_URL."\">".DOKU_URL."</a></p>\n". "</body>\n</html>"; $diffHTML = str_replace('class="diff-blockheader"','style="font-weight: bold; font-family: courier new;"',$diffHTML); $diffHTML = str_replace('class="diff-addedline"','style="background-color: #ddffdd; font-family: courier new;"',$diffHTML); $diffHTML = str_replace('class="diff-deletedline"','style="background-color: #ffffbb; font-family: courier new;"',$diffHTML); $diffHTML = str_replace('class="diff-context"','style="background-color: #f5f5f5; font-family: courier new;"',$diffHTML); $diffHTML = str_replace('class="diffchange"','style="color: red;"',$diffHTML); $diffHTML = str_replace('<strong>','<strong><font color="#FF0000">',$diffHTML); $diffHTML = str_replace('</strong>','</font></strong>',$diffHTML); $diffHTML = str_replace('<td>','<td style="font-family: courier new;">',$diffHTML); /*********************************** * End Generate HTML Notification Hack (Part 1) ***********************************/
Part 2
Then intercept the mailing action and generate a HTML-formatted version of the notification on new page creation. Locate the following code
$diff = rawWiki($id);
in the notify() function of inc/common.php and insert the following code right after it:
/*********************************** * Generate HTML Notification Hack (Part 2) * * inc/common.php * By Berteh (berteh [at] hotmail [dot] com) * ***********************************/ $diffHTML = "<html>\n<body>\n<h1 style=\"font-size: xx-large;\"><a href=\"".wl($id,'',true)."\"><font color=\"#FF6600\">".$id. "</font></a> was just added</h1>\n<h2 style=\"font-size: large;\">by <font color=\"#999999\"><b>". $_SERVER['REMOTE_USER']."</b></font> on ".strftime($conf['dformat'])."</h2><br />\n".p_wiki_xhtml($id). "\n"."<br />\n<p style=\"font-size: medium;\">---<br />\nThis mail was ". "automatically generated by DokuWiki at<br/>\n<a href=\"".DOKU_URL."\">".DOKU_URL."</a></p>\n". "</body>\n</html>"; /*********************************** * End Generate HTML Notification Hack (Part 2) ***********************************/
Part 3
Next, we will need to call our mail_send_html() function to send out the HTML-formatted email that we have generated. Locate the following code
mail_send($to,$subject,$text,$conf['mailfrom'],'',$bcc);
right before the notify() function ends. REPLACE this line of code with the following code:
/*********************************** * Generate HTML Notification Hack (Part 3) * * inc/common.php * By Lin Junjie (mail [dot] junjie [at] gmail [dot] com) * ***********************************/ if ($diffHTML) { mail_send_html($to,$subject,$text,$diffHTML,$conf['mailfrom'],'',$bcc); }else { mail_send($to,$subject,$text,$conf['mailfrom'],'',$bcc); } /*********************************** * End Generate HTML Notification Hack (Part 3) ***********************************/
Note that part 3 of the hack has the added functionality of changing the sender of the mail to the name of the user that made the change.6) Do replace the two instances of “INSERT-YOUR-SERVER-HERE.com” with your own server.
If you want to show the mail of the user that made the change as mail sender rather than a no-reply address use
$sendermail = $INFO['userinfo']['name']. ' <'.$INFO['userinfo']['mail'].'>'; if ($diffHTML) { mail_send_html($to,$subject,$text,$diffHTML,$sendermail,'',$bcc); }else { mail_send($to,$subject,$text,$sendermail,'',$bcc); }
That's all folks
That's it! We're done! Leave a message here or contact me at mail [dot] junjie [at] gmail [dot] com. If you have any way of integrating this into a plugin, please do so and let us know here!
history
Questions and problems
- The HTML version of the e-mail works fine in my web mail, but MS Outlook shows the plain text version.
- I tried this hack on version 2011-05-25a, it works, but does not support extended notification (digest and so on), one should look at extend inc/subscription.php