Index: wp-includes/class-phpmailer.php
===================================================================
--- wp-includes/class-phpmailer.php	(revision 5954)
+++ wp-includes/class-phpmailer.php	(working copy)
@@ -1165,14 +1165,86 @@
       // Try to select the encoding which should produce the shortest output
       if (strlen($str)/3 < $x) {
         $encoding = 'B';
-        $encoded = base64_encode($str);
         $maxlen -= $maxlen % 4;
-        $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+
+		if ('UTF-8' == $this->CharSet) {
+			$chunks = array();
+			$start = 0;
+			$i = 0;
+			while ($i < strlen($str)) {
+				if (ord($str[$i]) < 0x80) $n = 0; # 0bbbbbbb; equal to US-ASCII; one octet only.
+				elseif ((ord($str[$i]) & 0xE0) == 0xC0) $n = 1; # 110bbbbb; followed by 1 octet.
+				elseif ((ord($str[$i]) & 0xF0) == 0xE0) $n = 2; # 1110bbbb; followed by 2 octet.
+				elseif ((ord($str[$i]) & 0xF8) == 0xF0) $n = 3; # 11110bbb; followed by 3 octet.
+				elseif ((ord($str[$i]) & 0xFC) == 0xF8) $n = 4; # 111110bb; followed by 4 octet.
+				elseif ((ord($str[$i]) & 0xFE) == 0xFC) $n = 5; # 1111110b; followed by 5 octet.
+				else { # second or later octet.
+					$i++;
+					continue;
+				}
+
+				// Base64 encoded size
+				$encoded_length = ceil(($i + $n - $start) * 8 / 6);
+				$encoded_length = ceil($encoded_length / 4) * 4; // padding
+
+				if ($maxlen < $encoded_length) {
+					$chunks[] = substr($str, $start, $i - $start); // get one octet back.
+					$start = $i;
+				} else {
+					$i = $i + $n + 1;
+				}
+			}
+			$chunks[] = substr($str, $start); // rest
+
+			$encoded = "\n";
+			foreach ($chunks as $chunk) {
+				$encoded .= base64_encode($chunk) . "\n";
+			}
+			$encoded = trim($encoded);
+
+		} else {
+			$encoded = base64_encode($str);
+			$encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+		}
       } else {
         $encoding = 'Q';
         $encoded = $this->EncodeQ($str, $position);
-        $encoded = $this->WrapText($encoded, $maxlen, true);
-        $encoded = str_replace("=".$this->LE, "\n", trim($encoded));
+
+		if ('UTF-8' == $this->CharSet) {
+			$chunks = array();
+			$pos = 0;
+			while (strlen($encoded) - $pos > $maxlen) {
+				$len = $maxlen;
+				$part = substr($encoded, $pos, $len);
+
+				if (substr($part, $len - 1, 1) == "=")
+					$len -= 1;
+				elseif (substr($part, $len - 2, 1) == "=")
+					$len -= 2;
+				$part = substr($encoded, $pos, $len);
+
+				if (preg_match('/=[0-9A-F]{2}$/', $part)
+					&& preg_match('/=([0-9A-F]{2})/', substr($encoded, $pos + $len, 3), $matches)
+					&& (hexdec($matches[1]) & 0xC0) == 0x80) { # 10bbbbbb; following octet
+
+					while (preg_match('/=([0-9A-F]{2})$/', $part, $matches)) {
+						$len -= 3;
+						$part = substr($encoded, $pos, $len);
+						if ((hexdec($matches[1]) & 0xC0) != 0x80)
+							break;
+					}
+				}
+
+				$chunks[] = $part;
+				$pos += $len;
+			}
+
+			$chunks[] = substr($encoded, $pos); // rest
+			$encoded = trim(join($chunks, "\n"));
+		} else {
+			$encoded = $this->WrapText($encoded, $maxlen, true);
+			$encoded = str_replace("=".$this->LE, "\n", trim($encoded));
+		}
       }
 
       $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
