From e3af7c572be06e6aa1491c50787a932e147ccf2e Mon Sep 17 00:00:00 2001 From: Stewart Lord Date: Mon, 11 Feb 2013 23:16:00 -0800 Subject: [PATCH 1/2] Fixed a bug where mail messages were malformed when using the Sendmail transport on Unix systems with certain versions of sendmail (e.g. Postfix < 2.9). Specifically, message headers spilled into the body and the body text was double-spaced. The source of the problem was the use of CRLF as the EOL sequence when sending messages via PHP's built-in mail() function on Unix systems. Despite what the PHP manual says, LF should be used as the sole EOL character on Unix. This is because mail() is a wrapper for sendmail on Unix and does not speak SMTP except on Windows. --- library/Zend/Mail/Transport/Sendmail.php | 10 +++++++--- tests/ZendTest/Mail/Transport/SendmailTest.php | 12 ++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/library/Zend/Mail/Transport/Sendmail.php b/library/Zend/Mail/Transport/Sendmail.php index d5d607cf972..5a1f73fd152 100644 --- a/library/Zend/Mail/Transport/Sendmail.php +++ b/library/Zend/Mail/Transport/Sendmail.php @@ -190,8 +190,9 @@ protected function prepareSubject(Mail\Message $message) protected function prepareBody(Mail\Message $message) { if (!$this->isWindowsOs()) { - // *nix platforms can simply return the body text - return $message->getBodyText(); + // On *nix platforms, we should replace \r\n with \n + // sendmail is not an SMTP server, it is a unix command - it expects LF + return str_replace("\r\n", "\n", $message->getBodyText()); } // On windows, lines beginning with a full stop need to be fixed @@ -217,7 +218,10 @@ protected function prepareHeaders(Mail\Message $message) $headers = clone $message->getHeaders(); $headers->removeHeader('To'); $headers->removeHeader('Subject'); - return $headers->toString(); + + // On *nix platforms, we should replace \r\n with \n + // sendmail is not an SMTP server, it is a unix command - it expects LF + return str_replace("\r\n", "\n", $headers->toString()); } /** diff --git a/tests/ZendTest/Mail/Transport/SendmailTest.php b/tests/ZendTest/Mail/Transport/SendmailTest.php index 9cde9ca59ef..0b6eebd048d 100644 --- a/tests/ZendTest/Mail/Transport/SendmailTest.php +++ b/tests/ZendTest/Mail/Transport/SendmailTest.php @@ -83,12 +83,12 @@ public function testReceivesMailArtifactsOnUnixSystems() $this->assertEquals('ZF DevTeam ', $this->to); $this->assertEquals('Testing Zend\Mail\Transport\Sendmail', $this->subject); $this->assertEquals('This is only a test.', trim($this->message)); - $this->assertNotContains("To: ZF DevTeam \r\n", $this->additional_headers); - $this->assertContains("Cc: matthew@zend.com\r\n", $this->additional_headers); - $this->assertContains("Bcc: \"CR-Team, ZF Project\" \r\n", $this->additional_headers); - $this->assertContains("From: zf-devteam@zend.com,\r\n Matthew \r\n", $this->additional_headers); - $this->assertContains("X-Foo-Bar: Matthew\r\n", $this->additional_headers); - $this->assertContains("Sender: Ralph Schindler \r\n", $this->additional_headers); + $this->assertNotContains("To: ZF DevTeam \n", $this->additional_headers); + $this->assertContains("Cc: matthew@zend.com\n", $this->additional_headers); + $this->assertContains("Bcc: \"CR-Team, ZF Project\" \n", $this->additional_headers); + $this->assertContains("From: zf-devteam@zend.com,\n Matthew \n", $this->additional_headers); + $this->assertContains("X-Foo-Bar: Matthew\n", $this->additional_headers); + $this->assertContains("Sender: Ralph Schindler \n", $this->additional_headers); $this->assertEquals('-R hdrs -f ralph.schindler@zend.com', $this->additional_parameters); } From 6dc2cc53df577eae4890d54b4b7a68810a122345 Mon Sep 17 00:00:00 2001 From: Stewart Lord Date: Tue, 12 Feb 2013 01:02:17 -0800 Subject: [PATCH 2/2] Cast a wider net for EOL translation. The to and subject headers were being independantly wrapped. Now we convert line-endings on $to, $subject, $body and $headers immediately before calling mail(). --- library/Zend/Mail/Transport/Sendmail.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/Zend/Mail/Transport/Sendmail.php b/library/Zend/Mail/Transport/Sendmail.php index 5a1f73fd152..fbe8583fd01 100644 --- a/library/Zend/Mail/Transport/Sendmail.php +++ b/library/Zend/Mail/Transport/Sendmail.php @@ -127,6 +127,15 @@ public function send(Mail\Message $message) $headers = $this->prepareHeaders($message); $params = $this->prepareParameters($message); + // On *nix platforms, we need to replace \r\n with \n + // sendmail is not an SMTP server, it is a unix command - it expects LF + if (!$this->isWindowsOs()) { + $to = str_replace("\r\n", "\n", $to); + $subject = str_replace("\r\n", "\n", $subject); + $body = str_replace("\r\n", "\n", $body); + $headers = str_replace("\r\n", "\n", $headers); + } + call_user_func($this->callable, $to, $subject, $body, $headers, $params); } @@ -190,9 +199,8 @@ protected function prepareSubject(Mail\Message $message) protected function prepareBody(Mail\Message $message) { if (!$this->isWindowsOs()) { - // On *nix platforms, we should replace \r\n with \n - // sendmail is not an SMTP server, it is a unix command - it expects LF - return str_replace("\r\n", "\n", $message->getBodyText()); + // *nix platforms can simply return the body text + return $message->getBodyText(); } // On windows, lines beginning with a full stop need to be fixed @@ -218,10 +226,7 @@ protected function prepareHeaders(Mail\Message $message) $headers = clone $message->getHeaders(); $headers->removeHeader('To'); $headers->removeHeader('Subject'); - - // On *nix platforms, we should replace \r\n with \n - // sendmail is not an SMTP server, it is a unix command - it expects LF - return str_replace("\r\n", "\n", $headers->toString()); + return $headers->toString(); } /**