Skip to content

Commit 881e43a

Browse files
committed
Fix #72964: White space not unfolded for CC/Bcc headers
`\r\n` does only terminate a header, if not followed by `\t` or ` `. We have to cater to that when determining the end position of the respective headers. Closes GH-6420.
1 parent c2b1182 commit 881e43a

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ PHP NEWS
77
(cmb)
88
. Fixed bug #80345 (PHPIZE configuration has outdated PHP_RELEASE_VERSION).
99
(cmb)
10+
. Fixed bug #72964 (White space not unfolded for CC/Bcc headers). (cmb)
1011

1112
26 Nov 2020, PHP 7.4.13
1213

ext/standard/tests/mail/bug72964.phpt

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--TEST--
2+
Bug #72964 (White space not unfolded for CC/Bcc headers)
3+
--SKIPIF--
4+
<?php
5+
if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only test');
6+
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
7+
require_once __DIR__ . '/mail_skipif.inc';
8+
?>
9+
--INI--
10+
SMTP=localhost
11+
smtp_port=25
12+
--FILE--
13+
<?php
14+
require_once __DIR__ . '/mail_include.inc';
15+
16+
function find_and_delete_message($username, $subject) {
17+
global $default_mailbox, $password;
18+
19+
$imap_stream = imap_open($default_mailbox, $username, $password);
20+
if ($imap_stream === false) {
21+
die("Cannot connect to IMAP server $server: " . imap_last_error() . "\n");
22+
}
23+
24+
$found = false;
25+
$repeat_count = 20; // we will repeat a max of 20 times
26+
while (!$found && $repeat_count > 0) {
27+
// sleep for a while to allow msg to be delivered
28+
sleep(1);
29+
30+
$num_messages = imap_check($imap_stream)->Nmsgs;
31+
for ($i = $num_messages; $i > 0; $i--) {
32+
$info = imap_headerinfo($imap_stream, $i);
33+
if ($info->subject === $subject) {
34+
imap_delete($imap_stream, $i);
35+
$found = true;
36+
break;
37+
}
38+
}
39+
$repeat_count--;
40+
}
41+
42+
imap_close($imap_stream, CL_EXPUNGE);
43+
return $found;
44+
}
45+
46+
$to = "{$users[2]}@$domain";
47+
$subject = bin2hex(random_bytes(16));
48+
$message = 'hello';
49+
$headers = "From: [email protected]\r\n"
50+
. "Cc: {$users[0]}@$domain,\r\n\t{$users[1]}@$domain\r\n"
51+
. "Bcc: {$users[2]}@$domain,\r\n {$users[3]}@$domain\r\n";
52+
53+
$res = mail($to, $subject, $message, $headers);
54+
if ($res !== true) {
55+
die("TEST FAILED : Unable to send test email\n");
56+
} else {
57+
echo "Message sent OK\n";
58+
}
59+
60+
foreach ($users as $user) {
61+
if (!find_and_delete_message("$user@$domain", $subject)) {
62+
echo "TEST FAILED: email not delivered\n";
63+
} else {
64+
echo "TEST PASSED: Message sent and deleted OK\n";
65+
}
66+
}
67+
?>
68+
--EXPECT--
69+
Message sent OK
70+
TEST PASSED: Message sent and deleted OK
71+
TEST PASSED: Message sent and deleted OK
72+
TEST PASSED: Message sent and deleted OK
73+
TEST PASSED: Message sent and deleted OK

win32/sendmail.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,16 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
458458
if (NULL == (pos2 = strstr(pos1, "\r\n"))) {
459459
tempMailTo = estrndup(pos1, strlen(pos1));
460460
} else {
461+
char *pos3;
462+
while (pos2[2] == ' ' || pos2[2] == '\t') {
463+
pos3 = strstr(pos2 + 2, "\r\n");
464+
if (pos3 != NULL) {
465+
pos2 = pos3;
466+
} else {
467+
pos2 += strlen(pos2);
468+
break;
469+
}
470+
}
461471
tempMailTo = estrndup(pos1, pos2 - pos1);
462472
}
463473

@@ -516,7 +526,22 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
516526
header we know it was the last thing. */
517527
pos2 = pos1;
518528
} else {
529+
char *pos3 = NULL;
530+
while (pos2[2] == ' ' || pos2[2] == '\t') {
531+
pos3 = strstr(pos2 + 2, "\r\n");
532+
if (pos3 != NULL) {
533+
pos2 = pos3;
534+
} else {
535+
pos2 += strlen(pos2);
536+
break;
537+
}
538+
}
519539
tempMailTo = estrndup(pos1, pos2 - pos1);
540+
if (pos3 == NULL) {
541+
/* Later, when we remove the Bcc: out of the
542+
header we know it was the last thing. */
543+
pos2 = pos1;
544+
}
520545
}
521546

522547
token = strtok(tempMailTo, ",");

0 commit comments

Comments
 (0)