From b6c97c7072748fa573d54a91c1be14e496fd9990 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 3 Aug 2013 22:26:38 +0200 Subject: FS#2677 support arrays in to, cc, bcc headers in Mailer This does not fix FS#2677, it only adds support for fixing it later. --- inc/Mailer.class.php | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index cb5f22f54..0f3321bb9 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -137,7 +137,13 @@ class Mailer { } // empty value deletes - $value = trim($value); + if(is_array($value)){ + $value = array_map('trim', $value); + $value = array_filter($value); + if(!$value) $value = ''; + }else{ + $value = trim($value); + } if($value === '') { if(isset($this->headers[$header])) unset($this->headers[$header]); } else { @@ -270,7 +276,7 @@ class Mailer { * Add the To: recipients * * @see setAddress - * @param string $address Multiple adresses separated by commas + * @param string|array $address Multiple adresses separated by commas or as array */ public function to($address) { $this->setHeader('To', $address, false); @@ -280,7 +286,7 @@ class Mailer { * Add the Cc: recipients * * @see setAddress - * @param string $address Multiple adresses separated by commas + * @param string|array $address Multiple adresses separated by commas or as array */ public function cc($address) { $this->setHeader('Cc', $address, false); @@ -290,7 +296,7 @@ class Mailer { * Add the Bcc: recipients * * @see setAddress - * @param string $address Multiple adresses separated by commas + * @param string|array $address Multiple adresses separated by commas or as array */ public function bcc($address) { $this->setHeader('Bcc', $address, false); @@ -327,18 +333,20 @@ class Mailer { * Example: * setAddress("föö , me@somewhere.com","TBcc"); * - * @param string $address Multiple adresses separated by commas + * @param string|array $address Multiple adresses separated by commas or as array * @return bool|string the prepared header (can contain multiple lines) */ - public function cleanAddress($address) { + public function cleanAddress($addresses) { // No named recipients for To: in Windows (see FS#652) $names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true; - $address = preg_replace('/[\r\n\0]+/', ' ', $address); // remove attack vectors - $headers = ''; - $parts = explode(',', $address); - foreach($parts as $part) { + if(!is_array($addresses)){ + $addresses = explode(',', $addresses); + } + + foreach($addresses as $part) { + $part = preg_replace('/[\r\n\0]+/', ' ', $part); // remove attack vectors $part = trim($part); // parse address @@ -378,7 +386,7 @@ class Mailer { $text = utf8_strip($text); } - if(!utf8_isASCII($text)) { + if(strpos($text, ',') !== false || !utf8_isASCII($text)) { $text = '=?UTF-8?B?'.base64_encode($text).'?='; } } else { @@ -392,6 +400,7 @@ class Mailer { $headers .= $text.' '.$addr; } + $headers = trim($headers); if(empty($headers)) return false; return $headers; -- cgit v1.2.3 From d6e04b603a81d6c55c3bb71974689892762b6a01 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Oct 2013 13:30:54 +0200 Subject: successfully validate Mailer mails with msglint --- inc/Mailer.class.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 0f3321bb9..ff29c2a36 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -41,6 +41,7 @@ class Mailer { global $conf; $server = parse_url(DOKU_URL, PHP_URL_HOST); + if(strpos($server,'.') === false) $server = $server.'.localhost'; $this->partid = md5(uniqid(rand(), true)).'@'.$server; $this->boundary = '----------'.md5(uniqid(rand(), true)); @@ -57,6 +58,7 @@ class Mailer { $this->setHeader('X-DokuWiki-Server', $server); $this->setHeader('X-Auto-Response-Suppress', 'OOF'); $this->setHeader('List-Id', $conf['title'].' <'.$listid.'>'); + $this->setHeader('Date', date('r'), false); } /** @@ -426,7 +428,8 @@ class Mailer { } $mime .= '--'.$this->boundary.MAILHEADER_EOL; - $mime .= 'Content-Type: '.$media['mime'].';'.MAILHEADER_EOL; + $mime .= 'Content-Type: '.$media['mime'].';'.MAILHEADER_EOL. + ' id="'.$cid.'"'.MAILHEADER_EOL; $mime .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; $mime .= "Content-ID: <$cid>".MAILHEADER_EOL; if($media['embed']) { @@ -487,7 +490,8 @@ class Mailer { $body .= chunk_split(base64_encode($this->text), 74, MAILHEADER_EOL); $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; $body .= 'Content-Type: multipart/related;'.MAILHEADER_EOL. - ' boundary="'.$this->boundary.'"'.MAILHEADER_EOL; + ' boundary="'.$this->boundary.'";'.MAILHEADER_EOL. + ' type="text/html"'.MAILHEADER_EOL; $body .= MAILHEADER_EOL; } -- cgit v1.2.3 From b3577cf9084e7dee70c3d09426087262da0f2849 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Oct 2013 13:34:14 +0200 Subject: use different boundary prefix FS#2846 The used boundary should have been correct but might throw off MTAs not expecting more than two dashes at the start. This is just a wild guess and may not fix anything (but shouldn't break anything either). --- 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 ff29c2a36..34d1c8af6 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -44,7 +44,7 @@ class Mailer { if(strpos($server,'.') === false) $server = $server.'.localhost'; $this->partid = md5(uniqid(rand(), true)).'@'.$server; - $this->boundary = '----------'.md5(uniqid(rand(), true)); + $this->boundary = '__________'.md5(uniqid(rand(), true)); $listid = join('.', array_reverse(explode('/', DOKU_BASE))).$server; $listid = strtolower(trim($listid, '.')); -- cgit v1.2.3 From ce9d2cc8973fa97d222b00d8b5861a5e3c3a36c3 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Oct 2013 14:08:34 +0200 Subject: filename in email should be an atom not a quoted string --- inc/Mailer.class.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 34d1c8af6..e3cc2008c 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -419,6 +419,8 @@ class Mailer { $part = 1; // embedded attachments foreach($this->attach as $media) { + $media['name'] = str_replace(':', '_', cleanID($media['name'], true)); + // create content id $cid = 'part'.$part.'.'.$this->partid; -- cgit v1.2.3 From be3cc6ab00486166279563052bee534bfc992917 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 12 Oct 2013 14:09:15 +0200 Subject: base64 should be split at 4 bytes only FS#2864 --- inc/Mailer.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index e3cc2008c..6a6468ab4 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -435,9 +435,9 @@ class Mailer { $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; + $mime .= 'Content-Disposition: inline; filename='.$media['name'].''.MAILHEADER_EOL; } else { - $mime .= 'Content-Disposition: attachment; filename="'.$media['name'].'"'.MAILHEADER_EOL; + $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); @@ -474,7 +474,7 @@ class Mailer { 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), 72, MAILHEADER_EOL); } else { // multi part it is $body .= "This is a multi-part message in MIME format.".MAILHEADER_EOL; @@ -489,7 +489,7 @@ class Mailer { $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 .= chunk_split(base64_encode($this->text), 72, MAILHEADER_EOL); $body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL; $body .= 'Content-Type: multipart/related;'.MAILHEADER_EOL. ' boundary="'.$this->boundary.'";'.MAILHEADER_EOL. @@ -501,7 +501,7 @@ class Mailer { $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), 72, MAILHEADER_EOL); $body .= MAILHEADER_EOL; $body .= $attachments; $body .= '--'.$this->boundary.'--'.MAILHEADER_EOL; -- cgit v1.2.3 From 1d8036c2a36d5e226e4a58657e9d859cbc241508 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 22 Oct 2013 20:55:21 +0200 Subject: Mailer: avoid overlong headers in content ids FS#2868 --- inc/Mailer.class.php | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'inc/Mailer.class.php') diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 6a6468ab4..186bd531a 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -43,7 +43,7 @@ class Mailer { $server = parse_url(DOKU_URL, PHP_URL_HOST); if(strpos($server,'.') === false) $server = $server.'.localhost'; - $this->partid = md5(uniqid(rand(), true)).'@'.$server; + $this->partid = substr(md5(uniqid(rand(), true)),0, 8).'@'.$server; $this->boundary = '__________'.md5(uniqid(rand(), true)); $listid = join('.', array_reverse(explode('/', DOKU_BASE))).$server; @@ -430,14 +430,13 @@ class Mailer { } $mime .= '--'.$this->boundary.MAILHEADER_EOL; - $mime .= 'Content-Type: '.$media['mime'].';'.MAILHEADER_EOL. - ' id="'.$cid.'"'.MAILHEADER_EOL; - $mime .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL; - $mime .= "Content-ID: <$cid>".MAILHEADER_EOL; + $mime .= $this->wrappedHeaderLine('Content-Type', $media['mime'].'; id="'.$cid.'"'); + $mime .= $this->wrappedHeaderLine('Content-Transfer-Encoding', 'base64'); + $mime .= $this->wrappedHeaderLine('Content-ID',"<$cid>"); if($media['embed']) { - $mime .= 'Content-Disposition: inline; filename='.$media['name'].''.MAILHEADER_EOL; + $mime .= $this->wrappedHeaderLine('Content-Disposition', 'inline; filename='.$media['name']); } else { - $mime .= 'Content-Disposition: attachment; filename='.$media['name'].''.MAILHEADER_EOL; + $mime .= $this->wrappedHeaderLine('Content-Disposition', 'attachment; filename='.$media['name']); } $mime .= MAILHEADER_EOL; //end of headers $mime .= chunk_split(base64_encode($media['data']), 74, MAILHEADER_EOL); @@ -556,10 +555,17 @@ class Mailer { } } - // wrap headers - foreach($this->headers as $key => $val) { - $this->headers[$key] = wordwrap($val, 78, MAILHEADER_EOL.' '); - } + } + + /** + * Returns a complete, EOL terminated header line, wraps it if necessary + * + * @param $key + * @param $val + * @return string + */ + protected function wrappedHeaderLine($key, $val){ + return wordwrap("$key: $val", 78, MAILHEADER_EOL.' ').MAILHEADER_EOL; } /** @@ -571,7 +577,7 @@ class Mailer { $headers = ''; foreach($this->headers as $key => $val) { if ($val === '') continue; - $headers .= "$key: $val".MAILHEADER_EOL; + $headers .= $this->wrappedHeaderLine($key, $val); } return $headers; } -- cgit v1.2.3