]> granicus.if.org Git - php/commitdiff
Fix #80706: mail(): Headers after Bcc headers may be ignored
authorChristoph M. Becker <cmbecker69@gmx.de>
Thu, 4 Feb 2021 16:43:53 +0000 (17:43 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Mon, 8 Feb 2021 17:42:31 +0000 (18:42 +0100)
We need to handle the case where a CRLF after a Bcc header is not the
beginning of a folding marker, because in that case the Bcc header was
not the last "thing".

Closes GH-6666.

NEWS
ext/standard/tests/mail/bug80706.phpt [new file with mode: 0644]
win32/sendmail.c

diff --git a/NEWS b/NEWS
index c9fd50f4f5ebcec858d3df9877c3abb7844fb666..de699350cd2d76c3258521695760eaf9865d5edd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2021, PHP 7.4.16
 
+- Core:
+  . Fixed #80706 (mail(): Headers after Bcc headers may be ignored). (cmb)
+
 - MySQLi:
   . Fixed bug #74779 (x() and y() truncating floats to integers). (cmb)
 
diff --git a/ext/standard/tests/mail/bug80706.phpt b/ext/standard/tests/mail/bug80706.phpt
new file mode 100644 (file)
index 0000000..b478c49
--- /dev/null
@@ -0,0 +1,76 @@
+--TEST--
+Bug #72964 (White space not unfolded for CC/Bcc headers)
+--SKIPIF--
+<?php
+if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only test');
+if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
+require_once __DIR__ . '/mail_skipif.inc';
+?>
+--INI--
+SMTP=localhost
+smtp_port=25
+--FILE--
+<?php
+require_once __DIR__ . '/mail_include.inc';
+
+function find_and_delete_message($username, $subject) {
+    global $default_mailbox, $password;
+
+    $imap_stream = imap_open($default_mailbox, $username, $password);
+    if ($imap_stream === false) {
+        die("Cannot connect to IMAP server $server: " . imap_last_error() . "\n");
+    }
+
+    $found = false;
+    $repeat_count = 20; // we will repeat a max of 20 times
+    while (!$found && $repeat_count > 0) {
+        // sleep for a while to allow msg to be delivered
+        sleep(1);
+    
+        $num_messages = imap_check($imap_stream)->Nmsgs;
+        for ($i = $num_messages; $i > 0; $i--) {
+            $info = imap_headerinfo($imap_stream, $i);
+            if ($info->subject === $subject) {
+                $header = imap_fetchheader($imap_stream, $i);
+                echo "X-Mailer header found: ";
+                var_dump(strpos($header, 'X-Mailer: bug80706') !== false);
+                imap_delete($imap_stream, $i);
+                $found = true;
+                break;
+            }
+        }
+        $repeat_count--;
+    }
+
+    imap_close($imap_stream, CL_EXPUNGE);
+    return $found;
+}
+
+$to = "{$users[1]}@$domain";
+$subject = bin2hex(random_bytes(16));
+$message = 'hello';
+$headers = "From: webmaster@example.com\r\n"
+    . "Bcc: {$users[2]}@$domain\r\n"
+    . "X-Mailer: bug80706";
+
+$res = mail($to, $subject, $message, $headers);
+if ($res !== true) {
+       die("TEST FAILED : Unable to send test email\n");
+} else {
+       echo "Message sent OK\n";
+}
+
+foreach ([$users[1], $users[2]] as $user) {
+    if (!find_and_delete_message("$user@$domain", $subject)) {
+        echo "TEST FAILED: email not delivered\n";
+    } else {
+        echo "TEST PASSED: Message sent and deleted OK\n";
+    }
+}
+?>
+--EXPECT--
+Message sent OK
+X-Mailer header found: bool(true)
+TEST PASSED: Message sent and deleted OK
+X-Mailer header found: bool(true)
+TEST PASSED: Message sent and deleted OK
index c82dc7b3c6caf8fc1404773311a8fa91a86e4e9c..0e38d7092f1d7692b718dd8ee68489d36195b9f2 100644 (file)
@@ -526,7 +526,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
                                   header we know it was the last thing. */
                                pos2 = pos1;
                        } else {
-                               char *pos3 = NULL;
+                               char *pos3 = pos2;
                                while (pos2[2] == ' ' || pos2[2] == '\t') {
                                        pos3 = strstr(pos2 + 2, "\r\n");
                                        if (pos3 != NULL) {