DokuWiki

It's better when it's simple

User Tools

Site Tools


tips:betteremailnotifications

This is an old revision of the document!


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

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

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 36 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 877 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.4) 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

  • 2008.10.23: update to handle notifications on new pages —berteh
  • 2008.10.23: update to get absolute links in notifications titles, using wl( .. ,.., true); function —berteh

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
1)
I used TextWrangler on the Mac. You should probably use Wordpad if you're on Windows because Notepad doesn't understand the Unix style line endings.
2)
Line numbers are given based on this version.
3)
tested and working with DokuWiki 2008-05-05 & 2009-12-25c, but line numbers don't match the hack explanation, feel free to correct.
tips/betteremailnotifications.1316028053.txt.gz · Last modified: 2011-09-14 21:20 by 89.217.134.128

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki