diff --git a/class.phpmailer.php b/class.phpmailer.php
index 8d6c291fe..c891c3d03 100644
--- a/class.phpmailer.php
+++ b/class.phpmailer.php
@@ -570,6 +570,12 @@ class PHPMailer
*/
const CRLF = "\r\n";
+ /**
+ * The maximum line length allowed by RFC 2822 section 2.1.1
+ * @type integer
+ */
+ const MAX_LINE_LENGTH = 998;
+
/**
* Constructor.
* @param boolean $exceptions Should we throw external exceptions?
@@ -1001,8 +1007,9 @@ public function preSend()
throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
}
- $this->MIMEHeader = $this->createHeader();
+ //Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
$this->MIMEBody = $this->createBody();
+ $this->MIMEHeader = $this->createHeader();
// To capture the complete message when using mail(), create
// an extra header list which createHeader() doesn't fold in
@@ -1823,16 +1830,30 @@ public function createBody()
$bodyEncoding = $this->Encoding;
$bodyCharSet = $this->CharSet;
+ //Can we do a 7-bit downgrade?
if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
$bodyEncoding = '7bit';
$bodyCharSet = 'us-ascii';
}
+ //If lines are too long, change to quoted-printable transfer encoding
+ if (self::hasLineLongerThanMax($this->Body)) {
+ $this->Encoding = 'quoted-printable';
+ $bodyEncoding = 'quoted-printable';
+ $bodyCharSet = 'us-ascii'; //qp always fits into ascii
+ }
+
$altBodyEncoding = $this->Encoding;
$altBodyCharSet = $this->CharSet;
+ //Can we do a 7-bit downgrade?
if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
$altBodyEncoding = '7bit';
$altBodyCharSet = 'us-ascii';
}
+ //If lines are too long, change to quoted-printable transfer encoding
+ if (self::hasLineLongerThanMax($this->AltBody)) {
+ $altBodyEncoding = 'quoted-printable';
+ $altBodyCharSet = 'us-ascii';
+ }
switch ($this->message_type) {
case 'inline':
$body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
@@ -3371,6 +3392,18 @@ public function DKIM_Add($headers_line, $subject, $body)
return $dkimhdrs . $signed . "\r\n";
}
+ /**
+ * Detect if a string contains a line longer than the maximum line length allowed.
+ * @param $str
+ * @return boolean
+ * @static
+ */
+ public static function hasLineLongerThanMax($str)
+ {
+ //+2 to include CRLF line break for a 1000 total
+ return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str);
+ }
+
/**
* Allows for public read access to 'to' property.
* @access public
diff --git a/test/phpmailerTest.php b/test/phpmailerTest.php
index 4d519cb4f..c3247dad7 100644
--- a/test/phpmailerTest.php
+++ b/test/phpmailerTest.php
@@ -146,12 +146,12 @@ public function buildBody()
// Determine line endings for message
if ($this->Mail->ContentType == 'text/html' || strlen($this->Mail->AltBody) > 0) {
- $eol = '
';
+ $eol = "
". PHPMailer::CRLF;
$bullet = '