--- mimemail/mimemail.inc.ORIG 2010-03-24 22:36:41.000000000 +0100 +++ mimemail/mimemail.inc 2010-04-02 17:55:30.000000000 +0200 @@ -87,11 +87,22 @@ function mimemail_extract_files($html) { $pattern = '/(]+href=[\'"]?|]+codebase=[\'"]?|@import |src=[\'"]?)([^\'>"]+)([\'"]?)/mis'; $html = preg_replace_callback($pattern, '_mimemail_replace_files', $html); - $document = array(array( - 'Content-Type' => "text/html; charset=utf-8", - 'Content-Transfer-Encoding' => '8bit', - 'content' => $html, - )); + $chopped_html = chunk_split_for_8bit_encoding_xfer($html); + if ($chopped_html == FALSE) { + // 8bit encoded trasnsfer may not be safe (CR/LFs could be inserted where not desired) + $document = array(array( + 'Content-Type' => "text/html; charset=utf-8", + 'Content-Transfer-Encoding' => 'base64', + 'content' => chunk_split(base64_encode($html)), + )); + } + else { + $document = array(array( + 'Content-Type' => "text/html; charset=utf-8", + 'Content-Transfer-Encoding' => '8bit', + 'content' => $chopped_html, + )); + } $files = _mimemail_file(); @@ -153,6 +164,7 @@ function _mimemail_file($url = NULL, $na $ret = $files; $files = array(); + $filenames = array(); return $ret; } @@ -305,7 +317,7 @@ function mimemail_html_body($body, $subj )); } } - $content_type = 'multipart/alternative'; + $content_type = 'multipart/related; type="multipart/alternative"'; $text_part = array('Content-Type' => 'text/plain; charset=utf-8', 'content' => $text); @@ -316,22 +328,20 @@ function mimemail_html_body($body, $subj $mime_parts = mimemail_extract_files($body); $content = array($text_part, array_shift($mime_parts)); - $content = mimemail_multipart_body($content, $content_type, TRUE); + $content = mimemail_multipart_body($content, 'multipart/alternative', TRUE); $parts = array(array('Content-Type' => $content['headers']['Content-Type'], 'content' => $content['body'])); if ($mime_parts) { - $content_type = 'multipart/related'; $parts = array_merge($parts, $mime_parts); } foreach ($attachments as $a) { $a = (object) $a; - $content_type = 'multipart/mixed'; _mimemail_file($a->filepath, $a->filename, $a->filemime, 'attachment'); $parts = array_merge($parts, _mimemail_file()); } - return mimemail_multipart_body($parts, "$content_type; charset=utf-8"); + return mimemail_multipart_body($parts, $content_type); } function mimemail_parse($message) { @@ -593,3 +603,62 @@ function mimemail_address($address) { return FALSE; } + +function chunk_split_for_8bit_encoding_xfer($string) { + +// Here you can adjust the max. chunk length (in characters) and max. number of chunks +// Be aware that 1 character in UTF-8 encoding is 1 - 4 octets long, and SMTP transfer +// is limited to the maximal length of 998 octets within 1 chunk (so if you are using +// only common characters (1 or 2 bytes long), you can try to increase this limit to +// approx. 500, but be aware that you may get some CR/LFs where not desired; with +// default value 248 you are on the absolutely safe side (even if all characters are +// 4 Bytes long) + + $char_limit = 248; + $loop_limit = 1000; + +// Nothing to touch below this line... + + $return_string = ""; + $loop = 0; + + while (strlen($string) > $char_limit && $loop < $loop_limit) { + + $tmp = substr($string, 0, $char_limit); + + if ($to = strrpos($tmp, "\r\n")) { + // If there are 1 or more CR/LFs, just continue at the last one... + $return_string .= substr($string, 0, $to + 2); + $string = substr($string, $to + 2); + $loop++; + } + elseif ($to = strrpos($tmp, "\n")) { + // We try Unix line breaking (LF only) first; if found, replace the last + // LF (within the max. chunk length) with CR/LF (or, should we append it?!) + $return_string .= substr($string, 0, $to) . "\r\n"; + $string = substr($string, $to + 1); + $loop++; + } + elseif ($to = strrpos($tmp, " ")) { + // We try a space at the end; here, we append CR/LF as they should both be + // displayed as a single space (or, do we have to replace it?!) + $return_string .= substr($string, 0, $to + 1) . "\r\n"; + $string = substr($string, $to + 1); + $loop++; + } + else { + // We can not safely chop HTML file, give up... + $loop = $loop_limit; + } + } + + if ((strlen($string) < $char_limit + 1) && $loop < $loop_limit) { + // Append the residual chunk and return chopped HTML file... + $return_string .= $string; + return $return_string; + } + else { + // We can not safely chop HTML file; return error... + return FALSE; + } +}