From bb01c27c6c2c8e83091764cebadeef0489985b4b Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 2 Nov 2011 08:59:18 +0100 Subject: Added Mailer class --- inc/Mailer.class.php | 324 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 inc/Mailer.class.php (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php new file mode 100644 index 000000000..991ec6c3e --- /dev/null +++ b/inc/Mailer.class.php @@ -0,0 +1,324 @@ + + */ + + +// end of line for mail lines - RFC822 says CRLF but postfix (and other MTAs?) +// think different +if(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL',"\n"); +#define('MAILHEADER_ASCIIONLY',1); + + +class Mailer { + + private $headers = array(); + private $attach = array(); + private $html = ''; + private $text = ''; + + private $boundary = ''; + private $partid = ''; + private $sendparam= ''; + + function __construct(){ + $this->partid = md5(uniqid(rand(),true)).'@'.$_SERVER['SERVER_NAME']; + $this->boundary = '----------'.md5(uniqid(rand(),true)); + } + + /** + * Attach a file + * + * @param $path Path to the file to attach + * @param $mime Mimetype of the attached file + * @param $name The filename to use + * @param $embed Unique key to reference this file from the HTML part + */ + public function attachFile($path,$mime,$name='',$embed=''){ + if(!$name){ + $name = basename($path); + } + + $this->attach[] = array( + 'data' => file_get_contents($path), + 'mime' => $mime, + 'name' => $name, + 'embed' => $embed + ); + } + + /** + * Attach a file + * + * @param $path The file contents to attach + * @param $mime Mimetype of the attached file + * @param $name The filename to use + * @param $embed Unique key to reference this file from the HTML part + */ + public function attachContent($data,$mime,$name='',$embed=''){ + if(!$name){ + list($junk,$ext) = split('/',$mime); + $name = count($this->attach).".$ext"; + } + + $this->attach[] = array( + 'data' => $data, + 'mime' => $mime, + 'name' => $name, + 'embed' => $embed + ); + } + + /** + * Set the HTML part of the mail + * + * Placeholders can be used to reference embedded attachments + */ + public function setHTMLBody($html){ + $this->html = $html; + } + + /** + * Set the plain text part of the mail + */ + public function setTextBody($text){ + $this->text = $text; + } + + /** + * Ses an email address header with correct encoding + * + * Unicode characters will be deaccented and encoded base64 + * for headers. Addresses may not contain Non-ASCII data! + * + * Example: + * setAddress("föö , me@somewhere.com","TBcc"); + * + * @param string $address Multiple adresses separated by commas + * @param string $header Name of the header (To,Bcc,Cc,...) + */ + function mail_encode_address($address,$header){ + // No named recipients for To: in Windows (see FS#652) + $names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true; + + $headers = ''; + $parts = explode(',',$address); + foreach ($parts as $part){ + $part = trim($part); + + // parse address + if(preg_match('#(.*?)<(.*?)>#',$part,$matches)){ + $text = trim($matches[1]); + $addr = $matches[2]; + }else{ + $addr = $part; + } + // skip empty ones + if(empty($addr)){ + continue; + } + + // FIXME: is there a way to encode the localpart of a emailaddress? + if(!utf8_isASCII($addr)){ + msg(htmlspecialchars("E-Mail address <$addr> is not ASCII"),-1); + continue; + } + + if(!mail_isvalid($addr)){ + msg(htmlspecialchars("E-Mail address <$addr> is not valid"),-1); + continue; + } + + // text was given + if(!empty($text) && $names){ + // add address quotes + $addr = "<$addr>"; + + if(defined('MAILHEADER_ASCIIONLY')){ + $text = utf8_deaccent($text); + $text = utf8_strip($text); + } + + if(!utf8_isASCII($text)){ + //FIXME + // put the quotes outside as in =?UTF-8?Q?"Elan Ruusam=C3=A4e"?= vs "=?UTF-8?Q?Elan Ruusam=C3=A4e?=" + /* + if (preg_match('/^"(.+)"$/', $text, $matches)) { + $text = '"=?UTF-8?Q?'.mail_quotedprintable_encode($matches[1], 0).'?="'; + } else { + $text = '=?UTF-8?Q?'.mail_quotedprintable_encode($text, 0).'?='; + } + */ + $text = '=?UTF-8?B?'.base64_encode($text).'?='; + } + }else{ + $text = ''; + } + + // add to header comma seperated + if($headers != ''){ + $headers .= ','; + $headers .= MAILHEADER_EOL.' '; // avoid overlong mail headers + } + $headers .= $text.' '.$addr; + } + + if(empty($headers)) return false; + + $this->headers[$header] = $headers; + return $headers; + } + + /** + * Add the To: recipients + * + * @see setAddress + * @param string $address Multiple adresses separated by commas + */ + public function to($address){ + $this->setAddress($address, 'To'); + } + + /** + * Add the Cc: recipients + * + * @see setAddress + * @param string $address Multiple adresses separated by commas + */ + public function cc($address){ + $this->setAddress($address, 'Cc'); + } + + /** + * Add the Bcc: recipients + * + * @see setAddress + * @param string $address Multiple adresses separated by commas + */ + public function bcc($address){ + $this->setAddress($address, 'Bcc'); + } + + /** + * Add the mail's Subject: header + * + * @param string $subject the mail subject + */ + public function subject($subject){ + if(!utf8_isASCII($subject)){ + $subject = '=?UTF-8?B?'.base64_encode($subject).'?='; + } + $this->headers['Subject'] = $subject; + } + + /** + * Prepare the mime multiparts for all attachments + * + * Replaces placeholders in the HTML with the correct CIDs + */ + protected function prepareAttachments(){ + $mime = ''; + $part = 1; + // embedded attachments + foreach($this->attach as $media){ + // create content id + $cid = 'part'.$part.'.'.$this->partid; + + // replace wildcards + if($media['embed']){ + $this->html = str_replace('%%'.$media['embed'].'%%','cid:'.$cid,$this->html); + } + + $mime .= '--'.$this->boundary.MAILHEADER_EOL; + $mime .= 'Content-Type: '.$media['mime'].';'.MAILHEADER_EOL; + $mime .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; + $mime .= "Content-ID: <$cid>".MAILHEADER_EOL; + if($media['embed']){ + $mime .= 'Content-Disposition: inline; filename="'.$media['name'].'"'.MAILHEADER_EOL; + }else{ + $mime .= 'Content-Disposition: attachment; filename="'.$media['name'].'"'.MAILHEADER_EOL; + } + $mime .= MAILHEADER_EOL; //end of headers + $mime .= chunk_split(base64_encode($media['data']),74,MAILHEADER_EOL); + + $part++; + } + return $mime; + } + + protected function createBody(){ + // check for body + if(!$this->text && !$this->html){ + return false; + } + + // add general headers + $this->headers['MIME-Version'] = '1.0'; + + if(!$this->html && !count($this->attach)){ // we can send a simple single part message + $this->headers['Content-Type'] = 'text/plain; charset=UTF-8'; + $this->headers['Content-Transfer-Encoding'] = 'base64'; + $body = chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); + }else{ // multi part it is + + // prepare the attachments + $attachments = $this->prepareAttachments(); + + // do we have alternative text content? + if($this->text && $this->html){ + $this->headers['Content-Type'] = 'multipart/alternative; boundary="'.$this->boundary.'XX"'; + $body = "This is a multi-part message in MIME format.".MAILHEADER_EOL; + $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; + $body .= MAILHEADER_EOL; + $body .= 'Content-Type: text/plain; charset=UTF-8'; + $body .= 'Content-Transfer-Encoding: base64'; + $body .= chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); + $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; + $body .= 'Content-Type: multipart/related; boundary="'.$this->boundary.'"'.MAILHEADER_EOL; + $body .= MAILHEADER_EOL; + }else{ + $this->headers['Content-Type'] = 'multipart/related; boundary="'.$this->boundary.'"'; + $body = "This is a multi-part message in MIME format.".MAILHEADER_EOL; + } + + $body .= '--'.$this->boundary."\n"; + $body .= "Content-Type: text/html; charset=UTF-8\n"; + $body .= "Content-Transfer-Encoding: base64\n"; + $body .= MAILHEADER_EOL; + $body = chunk_split(base64_encode($this->html),74,MAILHEADER_EOL); + $body .= MAILHEADER_EOL; + $body .= $attachments; + $body .= '--'.$this->boundary.'--'.MAILHEADER_EOL; + + // close open multipart/alternative boundary + if($this->text && $this->html){ + $body .= '--'.$this->boundary.'XX--'.MAILHEADER_EOL; + } + } + + return $body; + } + + /** + * Create a string from the headers array + */ + protected function prepareHeaders(){ + $headers = ''; + foreach($this->headers as $key => $val){ + $headers .= "$key: $val".MAILHEADER_EOL; + } + return $headers; + } + + /** + * return a full email with all headers + * + * This is mainly for debugging and testing + */ + public function dump(){ + $headers = $this->prepareHeaders(); + $body = $this->prepareBody(); + + return $headers.MAILHEADER_EOL.$body; + } +} -- cgit v1.2.3 From 1d045709e66a239d6a0933c0d07dfbb9fb257d48 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 2 Nov 2011 19:19:11 +0100 Subject: The Mailer class should work now It's still not real world tested but the output *looks* right. Plugin hook support is still missing. --- inc/Mailer.class.php | 173 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 148 insertions(+), 25 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 991ec6c3e..420277d9e 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -1,15 +1,19 @@ */ - // end of line for mail lines - RFC822 says CRLF but postfix (and other MTAs?) // think different if(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL',"\n"); #define('MAILHEADER_ASCIIONLY',1); - class Mailer { private $headers = array(); @@ -19,10 +23,23 @@ class Mailer { private $boundary = ''; private $partid = ''; - private $sendparam= ''; + private $sendparam= null; + + private $validator = null; + + /** + * Constructor + * + * Initializes the boundary strings and part counters + */ + public function __construct(){ + if(isset($_SERVER['SERVER_NAME'])){ + $server = $_SERVER['SERVER_NAME']; + }else{ + $server = 'localhost'; + } - function __construct(){ - $this->partid = md5(uniqid(rand(),true)).'@'.$_SERVER['SERVER_NAME']; + $this->partid = md5(uniqid(rand(),true)).'@'.$server; $this->boundary = '----------'.md5(uniqid(rand(),true)); } @@ -69,24 +86,50 @@ class Mailer { ); } + /** + * Add an arbitrary header to the mail + * + * @param string $header the header name (no trailing colon!) + * @param string $value the value of the header + * @param bool $clean remove all non-ASCII chars and line feeds? + */ + public function setHeader($header,$value,$clean=true){ + $header = ucwords(strtolower($header)); // streamline casing + if($clean){ + $header = preg_replace('/[^\w \-\.\+\@]+/','',$header); + $value = preg_replace('/[^\w \-\.\+\@]+/','',$value); + } + $this->headers[$header] = $value; + } + + /** + * Set additional parameters to be passed to sendmail + * + * Whatever is set here is directly passed to PHP's mail() command as last + * parameter. Depending on the PHP setup this might break mailing alltogether + */ + public function setParameters($param){ + $this->sendparam = $param; + } + /** * Set the HTML part of the mail * * Placeholders can be used to reference embedded attachments */ - public function setHTMLBody($html){ + public function setHTML($html){ $this->html = $html; } /** * Set the plain text part of the mail */ - public function setTextBody($text){ + public function setText($text){ $this->text = $text; } /** - * Ses an email address header with correct encoding + * Sets an email address header with correct encoding * * Unicode characters will be deaccented and encoded base64 * for headers. Addresses may not contain Non-ASCII data! @@ -97,10 +140,13 @@ class Mailer { * @param string $address Multiple adresses separated by commas * @param string $header Name of the header (To,Bcc,Cc,...) */ - function mail_encode_address($address,$header){ + function setAddress($address,$header){ // No named recipients for To: in Windows (see FS#652) $names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true; + $header = ucwords(strtolower($header)); // streamline casing + $address = preg_replace('/[\r\n\0]+/',' ',$address); // remove attack vectors + $headers = ''; $parts = explode(',',$address); foreach ($parts as $part){ @@ -124,7 +170,11 @@ class Mailer { continue; } - if(!mail_isvalid($addr)){ + if(is_null($this->validator)){ + $this->validator = new EmailAddressValidator(); + $this->validator->allowLocalAddresses = true; + } + if(!$this->validator->check_email_address($addr)){ msg(htmlspecialchars("E-Mail address <$addr> is not valid"),-1); continue; } @@ -140,7 +190,7 @@ class Mailer { } if(!utf8_isASCII($text)){ - //FIXME + //FIXME check if this is needed for base64 too // put the quotes outside as in =?UTF-8?Q?"Elan Ruusam=C3=A4e"?= vs "=?UTF-8?Q?Elan Ruusam=C3=A4e?=" /* if (preg_match('/^"(.+)"$/', $text, $matches)) { @@ -199,6 +249,19 @@ class Mailer { $this->setAddress($address, 'Bcc'); } + /** + * Add the From: address + * + * This is set to $conf['mailfrom'] when not specified so you shouldn't need + * to call this function + * + * @see setAddress + * @param string $address from address + */ + public function from($address){ + $this->setAddress($address, 'From'); + } + /** * Add the mail's Subject: header * @@ -246,20 +309,33 @@ class Mailer { return $mime; } - protected function createBody(){ + /** + * Build the body and handles multi part mails + * + * Needs to be called before prepareHeaders! + * + * @return string the prepared mail body, false on errors + */ + protected function prepareBody(){ + global $conf; + // check for body if(!$this->text && !$this->html){ return false; } // add general headers + if(!isset($this->headers['From'])) $this->from($conf['mailfrom']); $this->headers['MIME-Version'] = '1.0'; + $body = ''; + if(!$this->html && !count($this->attach)){ // we can send a simple single part message $this->headers['Content-Type'] = 'text/plain; charset=UTF-8'; $this->headers['Content-Transfer-Encoding'] = 'base64'; - $body = chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); + $body .= chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); }else{ // multi part it is + $body .= "This is a multi-part message in MIME format.".MAILHEADER_EOL; // prepare the attachments $attachments = $this->prepareAttachments(); @@ -267,25 +343,21 @@ class Mailer { // do we have alternative text content? if($this->text && $this->html){ $this->headers['Content-Type'] = 'multipart/alternative; boundary="'.$this->boundary.'XX"'; - $body = "This is a multi-part message in MIME format.".MAILHEADER_EOL; $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; + $body .= 'Content-Type: text/plain; charset=UTF-8'.MAILHEADER_EOL; + $body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; $body .= MAILHEADER_EOL; - $body .= 'Content-Type: text/plain; charset=UTF-8'; - $body .= 'Content-Transfer-Encoding: base64'; $body .= chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; $body .= 'Content-Type: multipart/related; boundary="'.$this->boundary.'"'.MAILHEADER_EOL; $body .= MAILHEADER_EOL; - }else{ - $this->headers['Content-Type'] = 'multipart/related; boundary="'.$this->boundary.'"'; - $body = "This is a multi-part message in MIME format.".MAILHEADER_EOL; } - $body .= '--'.$this->boundary."\n"; - $body .= "Content-Type: text/html; charset=UTF-8\n"; - $body .= "Content-Transfer-Encoding: base64\n"; + $body .= '--'.$this->boundary.MAILHEADER_EOL; + $body .= 'Content-Type: text/html; charset=UTF-8'.MAILHEADER_EOL; + $body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; $body .= MAILHEADER_EOL; - $body = chunk_split(base64_encode($this->html),74,MAILHEADER_EOL); + $body .= chunk_split(base64_encode($this->html),74,MAILHEADER_EOL); $body .= MAILHEADER_EOL; $body .= $attachments; $body .= '--'.$this->boundary.'--'.MAILHEADER_EOL; @@ -301,6 +373,8 @@ class Mailer { /** * Create a string from the headers array + * + * @returns string the headers */ protected function prepareHeaders(){ $headers = ''; @@ -313,12 +387,61 @@ class Mailer { /** * return a full email with all headers * - * This is mainly for debugging and testing + * This is mainly intended for debugging and testing but could also be + * used for MHT exports + * + * @return string the mail, false on errors */ public function dump(){ - $headers = $this->prepareHeaders(); $body = $this->prepareBody(); + if($body === 'false') return false; + $headers = $this->prepareHeaders(); return $headers.MAILHEADER_EOL.$body; } + + /** + * Send the mail + * + * Call this after all data was set + * + * @fixme we need to support the old plugin hook here! + * @return bool true if the mail was successfully passed to the MTA + */ + public function send(){ + // any recipients? + if(trim($this->headers['To']) === '' && + trim($this->headers['Cc']) === '' && + trim($this->headers['Bcc']) === '') return false; + + // The To: header is special + if(isset($this->headers['To'])){ + $to = $this->headers['To']; + unset($this->headers['To']); + }else{ + $to = ''; + } + + // so is the subject + if(isset($this->headers['Subject'])){ + $subject = $this->headers['Subject']; + unset($this->headers['Subject']); + }else{ + $subject = ''; + } + + // make the body + $body = $this->prepareBody(); + if($body === 'false') return false; + + // cook the headers + $headers = $this->prepareHeaders(); + + // send the thing + if(is_null($this->sendparam)){ + return @mail($to,$subject,$body,$headers); + }else{ + return @mail($to,$subject,$body,$headers,$this->sendparam); + } + } } -- cgit v1.2.3 From a36fc3485fd92593133d56e9bb98d739d70ed94f Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Nov 2011 11:01:22 +0100 Subject: clean headers in a separate step this should make it easier to reintroduce a plugin hook compatible with the old one --- inc/Mailer.class.php | 179 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 115 insertions(+), 64 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 420277d9e..8f2992201 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -89,6 +89,8 @@ class Mailer { /** * Add an arbitrary header to the mail * + * If an empy value is passed, the header is removed + * * @param string $header the header name (no trailing colon!) * @param string $value the value of the header * @param bool $clean remove all non-ASCII chars and line feeds? @@ -99,7 +101,14 @@ class Mailer { $header = preg_replace('/[^\w \-\.\+\@]+/','',$header); $value = preg_replace('/[^\w \-\.\+\@]+/','',$value); } - $this->headers[$header] = $value; + + // empty value deletes + $value = trim($value); + if($value === ''){ + if(isset($this->headers[$header])) unset($this->headers[$header]); + }else{ + $this->headers[$header] = $value; + } } /** @@ -128,6 +137,58 @@ class Mailer { $this->text = $text; } + /** + * Add the To: recipients + * + * @see setAddress + * @param string $address Multiple adresses separated by commas + */ + public function to($address){ + $this->setHeader('To', $address, false); + } + + /** + * Add the Cc: recipients + * + * @see setAddress + * @param string $address Multiple adresses separated by commas + */ + public function cc($address){ + $this->setHeader('Cc', $address, false); + } + + /** + * Add the Bcc: recipients + * + * @see setAddress + * @param string $address Multiple adresses separated by commas + */ + public function bcc($address){ + $this->setHeader('Bcc', $address, false); + } + + /** + * Add the From: address + * + * This is set to $conf['mailfrom'] when not specified so you shouldn't need + * to call this function + * + * @see setAddress + * @param string $address from address + */ + public function from($address){ + $this->setHeader('From', $address, false); + } + + /** + * Add the mail's Subject: header + * + * @param string $subject the mail subject + */ + public function subject($subject){ + $this->headers['Subject'] = $subject; + } + /** * Sets an email address header with correct encoding * @@ -138,13 +199,12 @@ class Mailer { * setAddress("föö , me@somewhere.com","TBcc"); * * @param string $address Multiple adresses separated by commas - * @param string $header Name of the header (To,Bcc,Cc,...) + * @param string returns the prepared header (can contain multiple lines) */ - function setAddress($address,$header){ + public function cleanAddress($address){ // No named recipients for To: in Windows (see FS#652) $names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true; - $header = ucwords(strtolower($header)); // streamline casing $address = preg_replace('/[\r\n\0]+/',' ',$address); // remove attack vectors $headers = ''; @@ -207,72 +267,16 @@ class Mailer { // add to header comma seperated if($headers != ''){ - $headers .= ','; - $headers .= MAILHEADER_EOL.' '; // avoid overlong mail headers + $headers .= ', '; } $headers .= $text.' '.$addr; } if(empty($headers)) return false; - $this->headers[$header] = $headers; return $headers; } - /** - * Add the To: recipients - * - * @see setAddress - * @param string $address Multiple adresses separated by commas - */ - public function to($address){ - $this->setAddress($address, 'To'); - } - - /** - * Add the Cc: recipients - * - * @see setAddress - * @param string $address Multiple adresses separated by commas - */ - public function cc($address){ - $this->setAddress($address, 'Cc'); - } - - /** - * Add the Bcc: recipients - * - * @see setAddress - * @param string $address Multiple adresses separated by commas - */ - public function bcc($address){ - $this->setAddress($address, 'Bcc'); - } - - /** - * Add the From: address - * - * This is set to $conf['mailfrom'] when not specified so you shouldn't need - * to call this function - * - * @see setAddress - * @param string $address from address - */ - public function from($address){ - $this->setAddress($address, 'From'); - } - - /** - * Add the mail's Subject: header - * - * @param string $subject the mail subject - */ - public function subject($subject){ - if(!utf8_isASCII($subject)){ - $subject = '=?UTF-8?B?'.base64_encode($subject).'?='; - } - $this->headers['Subject'] = $subject; - } /** * Prepare the mime multiparts for all attachments @@ -325,7 +329,6 @@ class Mailer { } // add general headers - if(!isset($this->headers['From'])) $this->from($conf['mailfrom']); $this->headers['MIME-Version'] = '1.0'; $body = ''; @@ -342,14 +345,16 @@ class Mailer { // do we have alternative text content? if($this->text && $this->html){ - $this->headers['Content-Type'] = 'multipart/alternative; boundary="'.$this->boundary.'XX"'; + $this->headers['Content-Type'] = 'multipart/alternative;'.MAILHEADER_EOL. + ' boundary="'.$this->boundary.'XX"'; $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; $body .= 'Content-Type: text/plain; charset=UTF-8'.MAILHEADER_EOL; $body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; $body .= MAILHEADER_EOL; $body .= chunk_split(base64_encode($this->text),74,MAILHEADER_EOL); $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; - $body .= 'Content-Type: multipart/related; boundary="'.$this->boundary.'"'.MAILHEADER_EOL; + $body .= 'Content-Type: multipart/related;'.MAILHEADER_EOL. + ' boundary="'.$this->boundary.'"'.MAILHEADER_EOL; $body .= MAILHEADER_EOL; } @@ -371,6 +376,47 @@ class Mailer { return $body; } + /** + * Cleanup and encode the headers array + */ + protected function cleanHeaders(){ + global $conf; + + // clean up addresses + if(empty($this->headers['From'])) $this->from($conf['mailfrom']); + $addrs = array('To','From','Cc','Bcc'); + foreach($addrs as $addr){ + if(isset($this->headers[$addr])){ + $this->headers[$addr] = $this->cleanAddress($this->headers[$addr]); + } + } + + if(isset($subject)){ + // add prefix to subject + if($conf['mailprefix']){ + $prefix = '['.$conf['mailprefix'].']'; + $len = strlen($prefix); + if(substr($this->headers['subject'],0,$len) != $prefix){ + $this->headers['subject'] = $prefix.' '.$this->headers['subject']; + } + } + + // encode subject + if(defined('MAILHEADER_ASCIIONLY')){ + $this->headers['subject'] = utf8_deaccent($this->headers['subject']); + $this->headers['subject'] = utf8_strip($this->headers['subject']); + } + if(!utf8_isASCII($this->headers['Subject'])){ + $subject = '=?UTF-8?B?'.base64_encode($this->headers['Subject']).'?='; + } + } + + // wrap headers + foreach($this->headers as $key => $val){ + $this->headers[$key] = wordwrap($val,78,MAILHEADER_EOL.' '); + } + } + /** * Create a string from the headers array * @@ -393,6 +439,7 @@ class Mailer { * @return string the mail, false on errors */ public function dump(){ + $this->cleanHeaders(); $body = $this->prepareBody(); if($body === 'false') return false; $headers = $this->prepareHeaders(); @@ -409,6 +456,10 @@ class Mailer { * @return bool true if the mail was successfully passed to the MTA */ public function send(){ + // FIXME hook here + + $this->cleanHeaders(); + // any recipients? if(trim($this->headers['To']) === '' && trim($this->headers['Cc']) === '' && -- cgit v1.2.3 From 28d2ad801d5eafcfdfc9a122966458b2689a7ec6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Nov 2011 11:35:17 +0100 Subject: added old plugin hook back into Mailer class it now passes the whole Mail object and also signals if the mail sending was successful to the AFTER event. A bunch of references should make it compatible with old plugins. --- inc/Mailer.class.php | 95 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 33 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 8f2992201..3b7762e77 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -452,47 +452,76 @@ class Mailer { * * Call this after all data was set * - * @fixme we need to support the old plugin hook here! + * @triggers MAIL_MESSAGE_SEND * @return bool true if the mail was successfully passed to the MTA */ public function send(){ - // FIXME hook here - - $this->cleanHeaders(); - - // any recipients? - if(trim($this->headers['To']) === '' && - trim($this->headers['Cc']) === '' && - trim($this->headers['Bcc']) === '') return false; + $success = false; + + // prepare hook data + $data = array( + // pass the whole mail class to plugin + 'mail' => $this, + // pass references for backward compatibility + 'to' => &$this->headers['To'], + 'cc' => &$this->headers['Cc'], + 'bcc' => &$this->headers['Bcc'], + 'from' => &$this->headers['From'], + 'subject' => &$this->headers['Subject'], + 'body' => &$this->text, + 'params' => &$this->sendparams, + 'headers' => '', // plugins shouldn't use this + // signal if we mailed successfully to AFTER event + 'success' => &$success, + ); - // The To: header is special - if(isset($this->headers['To'])){ - $to = $this->headers['To']; - unset($this->headers['To']); - }else{ - $to = ''; - } + // do our thing if BEFORE hook approves + $evt = new Doku_Event('MAIL_MESSAGE_SEND', $data); + if ($evt->advise_before(true)) { + // clean up before using the headers + $this->cleanHeaders(); + + // any recipients? + if(trim($this->headers['To']) === '' && + trim($this->headers['Cc']) === '' && + trim($this->headers['Bcc']) === '') return false; + + // The To: header is special + if(isset($this->headers['To'])){ + $to = $this->headers['To']; + unset($this->headers['To']); + }else{ + $to = ''; + } - // so is the subject - if(isset($this->headers['Subject'])){ - $subject = $this->headers['Subject']; - unset($this->headers['Subject']); - }else{ - $subject = ''; - } + // so is the subject + if(isset($this->headers['Subject'])){ + $subject = $this->headers['Subject']; + unset($this->headers['Subject']); + }else{ + $subject = ''; + } - // make the body - $body = $this->prepareBody(); - if($body === 'false') return false; + // make the body + $body = $this->prepareBody(); + if($body === 'false') return false; - // cook the headers - $headers = $this->prepareHeaders(); + // cook the headers + $headers = $this->prepareHeaders(); + // add any headers set by legacy plugins + if(trim($data['headers'])){ + $headers .= MAILHEADER_EOL.trim($data['headers']); + } - // send the thing - if(is_null($this->sendparam)){ - return @mail($to,$subject,$body,$headers); - }else{ - return @mail($to,$subject,$body,$headers,$this->sendparam); + // send the thing + if(is_null($this->sendparam)){ + $success = @mail($to,$subject,$body,$headers); + }else{ + $success = @mail($to,$subject,$body,$headers,$this->sendparam); + } } + // any AFTER actions? + $evt->advise_after(); + return $success; } } -- cgit v1.2.3 From 54f3075553a782ff5e32a5326f0e225f4437be29 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Nov 2011 11:54:51 +0100 Subject: mail prefix defaults to title when empty --- inc/Mailer.class.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 3b7762e77..7b09cf75e 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -393,12 +393,14 @@ class Mailer { if(isset($subject)){ // add prefix to subject - if($conf['mailprefix']){ + if(empty($conf['mailprefix'])){ + $prefix = '['.$conf['title'].']'; + }else{ $prefix = '['.$conf['mailprefix'].']'; - $len = strlen($prefix); - if(substr($this->headers['subject'],0,$len) != $prefix){ - $this->headers['subject'] = $prefix.' '.$this->headers['subject']; - } + } + $len = strlen($prefix); + if(substr($this->headers['subject'],0,$len) != $prefix){ + $this->headers['subject'] = $prefix.' '.$this->headers['subject']; } // encode subject -- cgit v1.2.3 From 8a215f0965e27ba6b9e62b955890f1acc9445883 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Nov 2011 12:20:46 +0100 Subject: shorten title when used as prefix --- inc/Mailer.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 7b09cf75e..ffacc661d 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -394,7 +394,11 @@ class Mailer { if(isset($subject)){ // add prefix to subject if(empty($conf['mailprefix'])){ - $prefix = '['.$conf['title'].']'; + if(utf8_strlen($conf['title']) < 20) { + $prefix = '['.$conf['title'].']'; + }else{ + $prefix = '['.utf8_substr($conf['title'], 0, 20).'...]'; + } }else{ $prefix = '['.$conf['mailprefix'].']'; } -- cgit v1.2.3 From abbf08905d37ee82c6dda4c2afdbb54383c91517 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Nov 2011 13:02:00 +0100 Subject: Added setBody() to Mailer class This method makes it easy to send a HTML mail based on the default text mails. This is probably enough for simpler mails where no sophisticated HTML is needed except a bit of formatting and linked URLs. --- inc/Mailer.class.php | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index ffacc661d..b86a9d8f2 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -121,10 +121,80 @@ class Mailer { $this->sendparam = $param; } + /** + * Set the text and HTML body and apply replacements + * + * This function applies a whole bunch of default replacements in addition + * to the ones specidifed as parameters + * + * If you pass the HTML part or HTML replacements yourself you have to make + * sure you encode all HTML special chars correctly + * + * @fixme the HTML head and body still needs to be set + * @param string $text plain text body + * @param array $textrep replacements to apply on the text part + * @param array $htmlrep replacements to apply on the HTML part, leave null to use $textrep + * @param array $html the HTML body, leave null to create it from $text + */ + public function setBody($text, $textrep=null, $htmlrep=null, $html=null){ + global $INFO; + global $conf; + + // create HTML from text if not given + if(is_null($html)){ + $html = hsc($text); + $html = nl2br($text); + } + if(!is_null($textrep) && is_null($htmlrep)){ + $htmlrep = array_map('hsc',$textrep); + } + + // prepare default replacements + $ip = clientIP(); + $trep = array( + 'DATE' => dformat(), + 'BROWSER' => $_SERVER['HTTP_USER_AGENT'], + 'IPADDRESS' => $ip, + 'HOSTNAME' => gethostsbyaddrs($ip), + 'TITLE' => $conf['title'], + 'DOKUWIKIURL' => DOKU_URL, + 'USER' => $_SERVER['REMOTE_USER'], + 'NAME' => $INFO['userinfo']['name'], + 'MAIL' => $INFO['userinfo']['mail'], + ); + $trep = array_merge($trep,(array) $textrep); + $hrep = array( + 'DATE' => ''.hsc(dformat()).'', + 'BROWSER' => hsc($_SERVER['HTTP_USER_AGENT']), + 'IPADDRESS' => ''.hsc($ip).'', + 'HOSTNAME' => ''.hsc(gethostsbyaddrs($ip)).'', + 'TITLE' => hsc($conf['title']), + 'DOKUWIKIURL' => ''.DOKU_URL.'', + 'USER' => hsc($_SERVER['REMOTE_USER']), + 'NAME' => hsc($INFO['userinfo']['name']), + 'MAIL' => ''. + hsc($INFO['userinfo']['mail']).'', + ); + $hrep = array_merge($hrep,(array) $htmlrep); + + // Apply replacements + foreach ($trep as $key => $substitution) { + $text = str_replace('@'.strtoupper($key).'@',$substitution, $text); + } + foreach ($hrep as $key => $substitution) { + $html = str_replace('@'.strtoupper($key).'@',$substitution, $html); + } + + $this->setHTML($html); + $this->setText($text); + } + /** * Set the HTML part of the mail * * Placeholders can be used to reference embedded attachments + * + * You probably want to use setBody() instead */ public function setHTML($html){ $this->html = $html; @@ -132,6 +202,8 @@ class Mailer { /** * Set the plain text part of the mail + * + * You probably want to use setBody() instead */ public function setText($text){ $this->text = $text; -- cgit v1.2.3 From 76efd6d0637bb67b7dadf65f29a945fe2ce5fc25 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Nov 2011 17:00:25 +0100 Subject: Copy all text replacements to HTML replacements in Mailer With this change it's easy to just set the replacements for HTML that need special attention. --- inc/Mailer.class.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index b86a9d8f2..09e457243 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -139,14 +139,22 @@ class Mailer { public function setBody($text, $textrep=null, $htmlrep=null, $html=null){ global $INFO; global $conf; + $htmlrep = (array) $htmlrep; + $textrep = (array) $textrep; // create HTML from text if not given if(is_null($html)){ $html = hsc($text); $html = nl2br($text); } - if(!is_null($textrep) && is_null($htmlrep)){ - $htmlrep = array_map('hsc',$textrep); + // copy over all replacements missing for HTML (autolink URLs) + foreach($textrep as $key => $value){ + if(isset($htmlrep[$key])) continue; + if(preg_match('/^https?:\/\//i',$value)){ + $htmlrep[$key] = ''.hsc($value).''; + }else{ + $htmlrep[$key] = hsc($value); + } } // prepare default replacements -- cgit v1.2.3 From f08086ec453c4529ae7361f9540b430ee61238f0 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 13 Nov 2011 12:37:45 +0100 Subject: Added HTML wrapper for mails The mailwrap.html adds the standard headers and footers to all HTML mails. The signature present in the text body will be removed before inserting in the wrapper, allowing a nicer footer for HTML. Users can overwrite the file with their own to create HTML mails in corporate design. However, a way to automatically embed referenced images is missing currently. --- inc/Mailer.class.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 09e457243..cdd4b266a 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -130,13 +130,13 @@ class Mailer { * If you pass the HTML part or HTML replacements yourself you have to make * sure you encode all HTML special chars correctly * - * @fixme the HTML head and body still needs to be set * @param string $text plain text body * @param array $textrep replacements to apply on the text part * @param array $htmlrep replacements to apply on the HTML part, leave null to use $textrep * @param array $html the HTML body, leave null to create it from $text + * @param bool $wrap wrap the HTML in the default header/Footer */ - public function setBody($text, $textrep=null, $htmlrep=null, $html=null){ + public function setBody($text, $textrep=null, $htmlrep=null, $html=null, $wrap=true){ global $INFO; global $conf; $htmlrep = (array) $htmlrep; @@ -147,6 +147,12 @@ class Mailer { $html = hsc($text); $html = nl2br($text); } + if($wrap){ + $wrap = rawLocale('mailwrap','html'); + $html = preg_replace('/\n-- \n.*$/m','',$html); //strip signature + $html = str_replace('@HTMLBODY@',$html,$wrap); + } + // copy over all replacements missing for HTML (autolink URLs) foreach($textrep as $key => $value){ if(isset($htmlrep[$key])) continue; @@ -159,11 +165,12 @@ class Mailer { // prepare default replacements $ip = clientIP(); + $cip = gethostsbyaddrs($ip); $trep = array( 'DATE' => dformat(), 'BROWSER' => $_SERVER['HTTP_USER_AGENT'], 'IPADDRESS' => $ip, - 'HOSTNAME' => gethostsbyaddrs($ip), + 'HOSTNAME' => $cip, 'TITLE' => $conf['title'], 'DOKUWIKIURL' => DOKU_URL, 'USER' => $_SERVER['REMOTE_USER'], @@ -175,7 +182,7 @@ class Mailer { 'DATE' => ''.hsc(dformat()).'', 'BROWSER' => hsc($_SERVER['HTTP_USER_AGENT']), 'IPADDRESS' => ''.hsc($ip).'', - 'HOSTNAME' => ''.hsc(gethostsbyaddrs($ip)).'', + 'HOSTNAME' => ''.hsc($cip).'', 'TITLE' => hsc($conf['title']), 'DOKUWIKIURL' => ''.DOKU_URL.'', 'USER' => hsc($_SERVER['REMOTE_USER']), -- cgit v1.2.3 From 850dbf1f4b1e2bdee8b2e5f0438a5625d0a1bedf Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 13 Nov 2011 13:06:07 +0100 Subject: allow image embeds in HTML mail templates Using the place holder @MEDIA()@ you now can directly embed images from the media repository into your HTML mail template. An example was added to the mailwrap.html, but because images are embedded as is (no prescaling) this is suboptimal. If we keep it, a smaller version of the DokuWiki logo should be shipped with DokuWiki. --- inc/Mailer.class.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index cdd4b266a..7e6889292 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -86,6 +86,24 @@ class Mailer { ); } + /** + * Callback function to automatically embed images referenced in HTML templates + */ + protected function autoembed_cb($matches){ + static $embeds = 0; + $embeds++; + + // get file and mime type + $media = cleanID($matches[1]); + list($ext, $mime) = mimetype($media); + $file = mediaFN($media); + if(!file_exists($file)) return $matches[0]; //bad reference, keep as is + + // attach it and set placeholder + $this->attachFile($file,$mime,'','autoembed'.$embeds); + return '%%autoembed'.$embeds.'%%'; + } + /** * Add an arbitrary header to the mail * @@ -163,6 +181,10 @@ class Mailer { } } + // embed media from templates + $html = preg_replace_callback('/@MEDIA\(([^\)]+)\)@/', + array($this,'autoembed_cb'),$html); + // prepare default replacements $ip = clientIP(); $cip = gethostsbyaddrs($ip); -- cgit v1.2.3 From 45992a638a85374bf0df1084b3657c845abec060 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Mar 2012 07:58:02 +0100 Subject: fixed mailprefix handling --- inc/Mailer.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 7e6889292..5a5e7f2c6 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -500,7 +500,7 @@ class Mailer { } } - if(isset($subject)){ + if(isset($this->headers['Subject'])){ // add prefix to subject if(empty($conf['mailprefix'])){ if(utf8_strlen($conf['title']) < 20) { @@ -512,17 +512,17 @@ class Mailer { $prefix = '['.$conf['mailprefix'].']'; } $len = strlen($prefix); - if(substr($this->headers['subject'],0,$len) != $prefix){ - $this->headers['subject'] = $prefix.' '.$this->headers['subject']; + if(substr($this->headers['Subject'],0,$len) != $prefix){ + $this->headers['Subject'] = $prefix.' '.$this->headers['Subject']; } // encode subject if(defined('MAILHEADER_ASCIIONLY')){ - $this->headers['subject'] = utf8_deaccent($this->headers['subject']); - $this->headers['subject'] = utf8_strip($this->headers['subject']); + $this->headers['Subject'] = utf8_deaccent($this->headers['Subject']); + $this->headers['Subject'] = utf8_strip($this->headers['Subject']); } if(!utf8_isASCII($this->headers['Subject'])){ - $subject = '=?UTF-8?B?'.base64_encode($this->headers['Subject']).'?='; + $this->headers['Subject'] = '=?UTF-8?B?'.base64_encode($this->headers['Subject']).'?='; } } -- cgit v1.2.3 From a4c4a73d78c4db014dbc66ea67968472d52708f9 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Mar 2012 08:02:27 +0100 Subject: fixed signature stripping --- inc/Mailer.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 5a5e7f2c6..753ea3fd6 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -167,7 +167,7 @@ class Mailer { } if($wrap){ $wrap = rawLocale('mailwrap','html'); - $html = preg_replace('/\n-- \n.*$/m','',$html); //strip signature + $html = preg_replace('/\n--
.*$/s','',$html); //strip signature $html = str_replace('@HTMLBODY@',$html,$wrap); } -- cgit v1.2.3 From 9f3eca0b520fc5f689170108fbcbf490d12f2c2e Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Mar 2012 12:44:28 +0100 Subject: Add various headers to the mails FS#2247. pull request #83 closed --- inc/Mailer.class.php | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 753ea3fd6..141b69a18 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -33,14 +33,23 @@ class Mailer { * Initializes the boundary strings and part counters */ public function __construct(){ - if(isset($_SERVER['SERVER_NAME'])){ - $server = $_SERVER['SERVER_NAME']; - }else{ - $server = 'localhost'; - } + global $conf; + + $server = parse_url(DOKU_URL,PHP_URL_HOST); $this->partid = md5(uniqid(rand(),true)).'@'.$server; $this->boundary = '----------'.md5(uniqid(rand(),true)); + + $listid = join('.',array_reverse(explode('/',DOKU_BASE))).$server; + $listid = strtolower(trim($listid,'.')); + + // add some default headers for mailfiltering FS#2247 + $this->setHeader('X-Mailer','DokuWiki '.getVersion()); + $this->setHeader('X-DokuWiki-User', $_SERVER['REMOTE_USER']); + $this->setHeader('X-DokuWiki-Title', $conf['title']); + $this->setHeader('X-DokuWiki-Server', $server); + $this->setHeader('X-Auto-Response-Suppress', 'OOF'); + $this->setHeader('List-Id',$conf['title'].' <'.$listid.'>'); } /** @@ -114,10 +123,10 @@ class Mailer { * @param bool $clean remove all non-ASCII chars and line feeds? */ public function setHeader($header,$value,$clean=true){ - $header = ucwords(strtolower($header)); // streamline casing + $header = str_replace(' ','-',ucwords(strtolower(str_replace('-',' ',$header)))); // streamline casing if($clean){ $header = preg_replace('/[^\w \-\.\+\@]+/','',$header); - $value = preg_replace('/[^\w \-\.\+\@]+/','',$value); + $value = preg_replace('/[^\w \-\.\+\@<>]+/','',$value); } // empty value deletes -- cgit v1.2.3 From ba9c057b0126f2c449e16adf5073920b5a663773 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Mar 2012 12:50:34 +0100 Subject: use real HRs in HTML mails --- inc/Mailer.class.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 141b69a18..d7dc70ded 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -171,8 +171,10 @@ class Mailer { // create HTML from text if not given if(is_null($html)){ - $html = hsc($text); - $html = nl2br($text); + $html = $text; + $html = hsc($html); + $html = preg_replace('/^-----*$/m','
',$html); + $html = nl2br($html); } if($wrap){ $wrap = rawLocale('mailwrap','html'); -- cgit v1.2.3 From 052b2a1780ce07c45e80cd16a55e43177850de35 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 23 Mar 2012 11:39:25 +0100 Subject: removed commented code left from the quoted_printable days --- inc/Mailer.class.php | 9 --------- 1 file changed, 9 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index d7dc70ded..9744fa44e 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -370,15 +370,6 @@ class Mailer { } if(!utf8_isASCII($text)){ - //FIXME check if this is needed for base64 too - // put the quotes outside as in =?UTF-8?Q?"Elan Ruusam=C3=A4e"?= vs "=?UTF-8?Q?Elan Ruusam=C3=A4e?=" - /* - if (preg_match('/^"(.+)"$/', $text, $matches)) { - $text = '"=?UTF-8?Q?'.mail_quotedprintable_encode($matches[1], 0).'?="'; - } else { - $text = '=?UTF-8?Q?'.mail_quotedprintable_encode($text, 0).'?='; - } - */ $text = '=?UTF-8?B?'.base64_encode($text).'?='; } }else{ -- cgit v1.2.3 From 2398a2b54196667d6659d3d0489212b271c43703 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 15 Apr 2012 13:25:05 +0200 Subject: made it possible to disable HTML mails in the config --- inc/Mailer.class.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 9744fa44e..f04cdd3e2 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -26,6 +26,7 @@ class Mailer { private $sendparam= null; private $validator = null; + private $allowhtml = true; /** * Constructor @@ -43,6 +44,8 @@ class Mailer { $listid = join('.',array_reverse(explode('/',DOKU_BASE))).$server; $listid = strtolower(trim($listid,'.')); + $this->allowhtml = (bool) $conf['htmlmail']; + // add some default headers for mailfiltering FS#2247 $this->setHeader('X-Mailer','DokuWiki '.getVersion()); $this->setHeader('X-DokuWiki-User', $_SERVER['REMOTE_USER']); @@ -434,6 +437,11 @@ class Mailer { protected function prepareBody(){ global $conf; + // no HTML mails allowed? remove HTML body + if(!$this->allowhtml){ + $this->html = ''; + } + // check for body if(!$this->text && !$this->html){ return false; -- cgit v1.2.3 From f41c79d730286e8e8c95deb88a4c876e08e278a2 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 15 Apr 2012 13:26:57 +0200 Subject: changed internal Mailer members from private to protected --- inc/Mailer.class.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index f04cdd3e2..507150d00 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -16,17 +16,17 @@ if(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL',"\n"); class Mailer { - private $headers = array(); - private $attach = array(); - private $html = ''; - private $text = ''; + protected $headers = array(); + protected $attach = array(); + protected $html = ''; + protected $text = ''; - private $boundary = ''; - private $partid = ''; - private $sendparam= null; + protected $boundary = ''; + protected $partid = ''; + protected $sendparam= null; - private $validator = null; - private $allowhtml = true; + protected $validator = null; + protected $allowhtml = true; /** * Constructor -- cgit v1.2.3