Index: mimemail.inc =================================================================== RCS file: /cvs/drupal/contributions/modules/mimemail/mimemail.inc,v retrieving revision 1.41 diff -u -r1.41 mimemail.inc --- mimemail.inc 24 Mar 2010 21:36:41 -0000 1.41 +++ mimemail.inc 8 Apr 2010 18:46:47 -0000 @@ -87,11 +87,22 @@ $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(); @@ -593,3 +604,60 @@ return FALSE; } + +/** + * 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) + */ +function chunk_split_for_8bit_encoding_xfer($string) { + $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; + } +}