Commit 40ad8b5e authored by catch's avatar catch
Browse files

Issue #3270647 by P44T, AndyF, Sander Edwards van Muijen, Nitin shrivastava,...

Issue #3270647 by P44T, AndyF, Sander Edwards van Muijen, Nitin shrivastava, Albert Volkman, mr.baileys, jshimota01, catch, mpellegrin, poker10, alexpott: PhpMail : broken mail headers in PHP 8.0+ because of LF characters
parent e3973cad
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -101,10 +101,20 @@ public function mail(array $message) {
    // line-ending format appropriate for your system. If you need to
    // override this, adjust $settings['mail_line_endings'] in settings.php.
    $mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']);
    $mail_headers = $headers->toString();

    // Since Drupal 10+ does not support PHP < 8, this block is only relevant for Drupal 9.x.
    // See: https://www.drupal.org/node/3270647
    if (version_compare(PHP_VERSION, '8.0.0') < 0) {
      // For headers, PHP's API suggests that we use CRLF normally,
      // but some MTAs incorrectly replace LF with CRLF. See #234403.
    $mail_headers = str_replace("\r\n", "\n", $headers->toString());
      // PHP 8+ requires headers to be separated by CRLF,
      // so we'll replace CRLF by LF only when using PHP < 8. See:
      // - https://bugs.php.net/bug.php?id=81158
      // - https://github.com/php/php-src/commit/6983ae751cd301886c966b84367fc7aaa1273b2d#diff-c6922cd89f6f75912eb377833ca1eddb7dd41de088be821024b8a0e340fed3df
      $mail_headers = str_replace("\r\n", "\n", $mail_headers);
      $mail_subject = str_replace("\r\n", "\n", $mail_subject);
    }

    if (substr(PHP_OS, 0, 3) != 'WIN') {
      // On most non-Windows systems, the "-f" option to the sendmail command
+26 −5
Original line number Diff line number Diff line
@@ -53,9 +53,6 @@ protected function createPhpMailInstance(): PhpMail {
      ->onlyMethods(['doMail'])
      ->getMock();

    $mailer->expects($this->once())->method('doMail')
      ->willReturn(TRUE);

    return $mailer;
  }

@@ -76,20 +73,44 @@ public function testMail() {
      'langcode' => 'en',
      'params' => [],
      'send' => TRUE,
      'subject' => '',
      'subject' => "test\r\nsubject",
      'body' => '',
      'headers' => [
        'MIME-Version' => '1.0',
        'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
        'Content-Transfer-Encoding' => '8Bit',
        'X-Mailer' => 'Drupal',
        'Return-Path' => 'from@example.org',
        'From' => '"Foo, Bar, and Baz" <from@example.org>',
        'Reply-to' => 'from@example.org',
        'Return-Path' => 'from@example.org',
      ],
    ];

    $mailer = $this->createPhpMailInstance();

    // Verify we use line endings consistent with the PHP mail() function, which
    // changed with PHP 8. See:
    // - https://www.drupal.org/node/3270647
    // - https://bugs.php.net/bug.php?id=81158
    // Since Drupal 10+ does not support PHP < 8, the PHP version check in the next line can be removed in Drupal 10+.
    $line_end = PHP_MAJOR_VERSION < 8 ? "\n" : "\r\n";

    $expected_headers = "MIME-Version: 1.0$line_end";
    $expected_headers .= "Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes$line_end";
    $expected_headers .= "Content-Transfer-Encoding: 8Bit$line_end";
    $expected_headers .= "X-Mailer: Drupal$line_end";
    $expected_headers .= "From: \"Foo, Bar, and Baz\" <from@example.org>$line_end";
    $expected_headers .= "Reply-to: from@example.org$line_end";

    $mailer->expects($this->once())->method('doMail')
      ->with(
        $this->equalTo('to@example.org'),
        $this->equalTo("=?utf-8?Q?test?={$line_end} =?utf-8?Q?subject?="),
        $this->equalTo(''),
        $this->stringStartsWith($expected_headers),
      )
      ->willReturn(TRUE);

    $this->assertTrue($mailer->mail($message));
  }