mirror of
https://github.com/PHPMailer/PHPMailer.git
synced 2024-09-20 10:02:14 +02:00
Deal with excessively long lines, see #314
This commit is contained in:
parent
de5c035380
commit
aa8e499b8a
@ -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 @@ class PHPMailer
|
||||
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 @@ class PHPMailer
|
||||
|
||||
$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 @@ class PHPMailer
|
||||
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
|
||||
|
@ -146,12 +146,12 @@ class PHPMailerTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
// Determine line endings for message
|
||||
if ($this->Mail->ContentType == 'text/html' || strlen($this->Mail->AltBody) > 0) {
|
||||
$eol = '<br/>';
|
||||
$eol = "<br/>". PHPMailer::CRLF;
|
||||
$bullet = '<li>';
|
||||
$bullet_start = '<ul>';
|
||||
$bullet_end = '</ul>';
|
||||
} else {
|
||||
$eol = "\n";
|
||||
$eol = PHPMailer::CRLF;
|
||||
$bullet = ' - ';
|
||||
$bullet_start = '';
|
||||
$bullet_end = '';
|
||||
@ -1040,6 +1040,57 @@ EOT;
|
||||
$this->assertFalse($this->Mail->send(), $this->Mail->ErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructing a message that contains lines that are too long for RFC compliance.
|
||||
*/
|
||||
public function testLongBody()
|
||||
{
|
||||
$oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . PHPMailer::CRLF, 10);
|
||||
$badlen = str_repeat(str_repeat('1', PHPMailer::MAX_LINE_LENGTH + 1) . PHPMailer::CRLF, 2);
|
||||
|
||||
$this->Mail->Body = "This message contains lines that are too long.".
|
||||
PHPMailer::CRLF . PHPMailer::CRLF . $oklen . $badlen . $oklen;
|
||||
$this->assertTrue(
|
||||
PHPMailer::hasLineLongerThanMax($this->Mail->Body),
|
||||
'Test content does not contain long lines!'
|
||||
);
|
||||
$this->buildBody();
|
||||
$this->Mail->Encoding = '8bit';
|
||||
$this->Mail->preSend();
|
||||
$message = $this->Mail->getSentMIMEMessage();
|
||||
$this->assertFalse(PHPMailer::hasLineLongerThanMax($message), 'Long line not corrected.');
|
||||
$this->assertContains(
|
||||
'Content-Transfer-Encoding: quoted-printable',
|
||||
$message,
|
||||
'Long line did not cause transfer encoding switch.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructing a message that does NOT contain lines that are too long for RFC compliance.
|
||||
*/
|
||||
public function testShortBody()
|
||||
{
|
||||
$oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . PHPMailer::CRLF, 10);
|
||||
|
||||
$this->Mail->Body = "This message does not contain lines that are too long.".
|
||||
PHPMailer::CRLF . PHPMailer::CRLF . $oklen;
|
||||
$this->assertFalse(
|
||||
PHPMailer::hasLineLongerThanMax($this->Mail->Body),
|
||||
'Test content contains long lines!'
|
||||
);
|
||||
$this->buildBody();
|
||||
$this->Mail->Encoding = '8bit';
|
||||
$this->Mail->preSend();
|
||||
$message = $this->Mail->getSentMIMEMessage();
|
||||
$this->assertFalse(PHPMailer::hasLineLongerThanMax($message), 'Long line not corrected.');
|
||||
$this->assertNotContains(
|
||||
'Content-Transfer-Encoding: quoted-printable',
|
||||
$message,
|
||||
'Short line caused transfer encoding switch.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test keepalive (sending multiple messages in a single connection)
|
||||
*/
|
||||
@ -1288,6 +1339,20 @@ EOT;
|
||||
$this->assertEquals($target, PHPMailer::normalizeBreaks($mixedsrc), 'Mixed break reformatting failed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test line length detection
|
||||
*/
|
||||
public function testLineLength()
|
||||
{
|
||||
$oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH)."\r\n", 10);
|
||||
$badlen = str_repeat(str_repeat('1', PHPMailer::MAX_LINE_LENGTH + 1) . "\r\n", 2);
|
||||
$this->assertTrue(PHPMailer::hasLineLongerThanMax($badlen), 'Long line not detected (only)');
|
||||
$this->assertTrue(PHPMailer::hasLineLongerThanMax($oklen . $badlen), 'Long line not detected (first)');
|
||||
$this->assertTrue(PHPMailer::hasLineLongerThanMax($badlen . $oklen), 'Long line not detected (last)');
|
||||
$this->assertTrue(PHPMailer::hasLineLongerThanMax($oklen . $badlen . $oklen), 'Long line not detected (middle)');
|
||||
$this->assertFalse(PHPMailer::hasLineLongerThanMax($oklen), 'Long line false positive');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting and retrieving message ID
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user