From 6e530502d24ba7836efc7a99c46a60f367bede13 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Thu, 15 Sep 2016 06:26:31 +0900 Subject: [PATCH] Implemented Bug #68776 mail() does not have mail header injection prevention for additional headers (PR 2060) --- NEWS | 2 + UPGRADING | 8 + ext/mbstring/mbstring.c | 41 +++-- ext/standard/mail.c | 217 +++++++++++++++++++++- ext/standard/php_mail.h | 32 +++- ext/standard/tests/mail/mail_basic7.phpt | 218 +++++++++++++++++++++++ 6 files changed, 498 insertions(+), 20 deletions(-) create mode 100644 ext/standard/tests/mail/mail_basic7.phpt diff --git a/NEWS b/NEWS index 2f3609298d..f8704db09e 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Removed the sql.safe_mode directive. (Kalle) . Fixed bug #54535 (WSA cleanup executes before MSHUTDOWN). (Kalle) + . Implemented bug #68776 (mail() does not have mail header injection prevention + for additional headers) (Yasuo) - EXIF: . Added support for vendor specific tags for the following formats: diff --git a/UPGRADING b/UPGRADING index 75b936eaaf..feef5d61c8 100644 --- a/UPGRADING +++ b/UPGRADING @@ -55,6 +55,14 @@ PHP 7.2 UPGRADE NOTES 'PASSWORD_ARGON2_DEFAULT_TIME_COST', and 'PASSWORD_ARGON2_DEFAULT_THREADS' respectively if not set. . password_verify() can verify Argon2i hashes. . password_get_info() and password_needs_rehash() can accept Argon2i hashes. + . mail()/mb_send_mail() accept array $extra_header. Array paramter is checked against RFC 2822. + Array format is + $extra_headers = [ + 'Header-Name' => 'Header value', + 'Multiple' => ['One header', 'Another header'], + 'Multiline' = "FirstLine\r\n SecondLine", + ]; + ======================================== 6. New Functions diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 296686309a..2a7bba0368 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -4392,11 +4392,11 @@ PHP_FUNCTION(mb_send_mail) size_t to_len; char *message = NULL; size_t message_len; - char *headers = NULL; - size_t headers_len; char *subject = NULL; - zend_string *extra_cmd = NULL; size_t subject_len; + zval *headers = NULL; + zend_string *extra_cmd = NULL; + zend_string *str_headers=NULL, *tmp_headers; int i; char *to_r = NULL; char *force_extra_parameters = INI_STR("mail.force_extra_parameters"); @@ -4436,7 +4436,7 @@ PHP_FUNCTION(mb_send_mail) body_enc = lang->mail_body_encoding; } - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|sS", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &headers_len, &extra_cmd) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|zS", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &extra_cmd) == FAILURE) { return; } @@ -4445,7 +4445,20 @@ PHP_FUNCTION(mb_send_mail) MAIL_ASCIIZ_CHECK_MBSTRING(subject, subject_len); MAIL_ASCIIZ_CHECK_MBSTRING(message, message_len); if (headers) { - MAIL_ASCIIZ_CHECK_MBSTRING(headers, headers_len); + switch(Z_TYPE_P(headers)) { + case IS_STRING: + tmp_headers = zend_string_init(Z_STRVAL_P(headers), Z_STRLEN_P(headers), 0); + MAIL_ASCIIZ_CHECK_MBSTRING(ZSTR_VAL(tmp_headers), ZSTR_LEN(tmp_headers)); + str_headers = php_trim(tmp_headers, NULL, 0, 2); + zend_string_release(tmp_headers); + break; + case IS_ARRAY: + str_headers = php_mail_build_headers(headers); + break; + default: + php_error_docref(NULL, E_WARNING, "headers parameter must be string or array"); + RETURN_FALSE; + } } if (extra_cmd) { MAIL_ASCIIZ_CHECK_MBSTRING(ZSTR_VAL(extra_cmd), ZSTR_LEN(extra_cmd)); @@ -4453,8 +4466,8 @@ PHP_FUNCTION(mb_send_mail) zend_hash_init(&ht_headers, 0, NULL, ZVAL_PTR_DTOR, 0); - if (headers != NULL) { - _php_mbstr_parse_mail_headers(&ht_headers, headers, headers_len); + if (str_headers != NULL) { + _php_mbstr_parse_mail_headers(&ht_headers, ZSTR_VAL(str_headers), ZSTR_LEN(str_headers)); } if ((s = zend_hash_str_find(&ht_headers, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1))) { @@ -4597,10 +4610,11 @@ PHP_FUNCTION(mb_send_mail) #define PHP_MBSTR_MAIL_MIME_HEADER2 "Content-Type: text/plain" #define PHP_MBSTR_MAIL_MIME_HEADER3 "; charset=" #define PHP_MBSTR_MAIL_MIME_HEADER4 "Content-Transfer-Encoding: " - if (headers != NULL) { - p = headers; - n = headers_len; + if (str_headers != NULL) { + p = ZSTR_VAL(str_headers); + n = ZSTR_LEN(str_headers); mbfl_memory_device_strncat(&device, p, n); + zend_string_release(str_headers); if (n > 0 && p[n - 1] != '\n') { mbfl_memory_device_strncat(&device, "\n", 1); } @@ -4633,7 +4647,7 @@ PHP_FUNCTION(mb_send_mail) mbfl_memory_device_unput(&device); mbfl_memory_device_output('\0', &device); - headers = (char *)device.buffer; + str_headers = zend_string_init((char *)device.buffer, strlen((char *)device.buffer), 0); if (force_extra_parameters) { extra_cmd = php_escape_shell_cmd(force_extra_parameters); @@ -4641,7 +4655,7 @@ PHP_FUNCTION(mb_send_mail) extra_cmd = php_escape_shell_cmd(ZSTR_VAL(extra_cmd)); } - if (!err && php_mail(to_r, subject, message, headers, extra_cmd ? ZSTR_VAL(extra_cmd) : NULL)) { + if (!err && php_mail(to_r, subject, message, ZSTR_VAL(str_headers), extra_cmd ? ZSTR_VAL(extra_cmd) : NULL)) { RETVAL_TRUE; } else { RETVAL_FALSE; @@ -4662,6 +4676,9 @@ PHP_FUNCTION(mb_send_mail) } mbfl_memory_device_clear(&device); zend_hash_destroy(&ht_headers); + if (str_headers) { + zend_string_release(str_headers); + } } #undef SKIP_LONG_HEADER_SEP_MBSTRING diff --git a/ext/standard/mail.c b/ext/standard/mail.c index b27e12adc1..8d70e5a47b 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -27,6 +27,7 @@ #include "ext/standard/php_string.h" #include "ext/standard/basic_functions.h" #include "ext/date/php_date.h" +#include "zend_smart_str.h" #if HAVE_SYSEXITS_H #include @@ -96,20 +97,210 @@ PHP_FUNCTION(ezmlm_hash) } /* }}} */ + +static zend_bool php_mail_build_headers_check_field_value(zval *val) +{ + size_t len = 0; + zend_string *value = Z_STR_P(val); + + /* https://tools.ietf.org/html/rfc2822#section-2.2.1 */ + /* https://tools.ietf.org/html/rfc2822#section-2.2.3 */ + while (len < value->len) { + if (*(value->val+len) == '\r') { + if (value->len - len >= 3 + && *(value->val+len+1) == '\n' + && (*(value->val+len+2) == ' ' || *(value->val+len+2) == '\t')) { + len += 3; + continue; + } + return FAILURE; + } + if (*(value->val+len) == '\0') { + return FAILURE; + } + len++; + } + return SUCCESS; +} + + +static zend_bool php_mail_build_headers_check_field_name(zend_string *key) +{ + size_t len = 0; + + /* https://tools.ietf.org/html/rfc2822#section-2.2 */ + while (len < key->len) { + if (*(key->val+len) < 33 || *(key->val+len) > 126 || *(key->val+len) == ':') { + return FAILURE; + } + len++; + } + return SUCCESS; +} + + +static void php_mail_build_headers_elems(smart_str *s, zend_string *key, zval *val); + +static void php_mail_build_headers_elem(smart_str *s, zend_string *key, zval *val) +{ + switch(Z_TYPE_P(val)) { + case IS_STRING: + if (php_mail_build_headers_check_field_name(key) != SUCCESS) { + php_error_docref(NULL, E_WARNING, "Header field name (%s) contains invalid chars", ZSTR_VAL(key)); + return; + } + if (php_mail_build_headers_check_field_value(val) != SUCCESS) { + php_error_docref(NULL, E_WARNING, "Header field value (%s => %s) contains invalid chars or format", ZSTR_VAL(key), Z_STRVAL_P(val)); + return; + } + smart_str_append(s, key); + smart_str_appendl(s, ": ", 2); + smart_str_appends(s, Z_STRVAL_P(val)); + smart_str_appendl(s, "\r\n", 2); + break; + case IS_ARRAY: + php_mail_build_headers_elems(s, key, val); + break; + default: + php_error_docref(NULL, E_WARNING, "headers array elements must be string or array (%s)", ZSTR_VAL(key)); + } +} + + +static void php_mail_build_headers_elems(smart_str *s, zend_string *key, zval *val) +{ + zend_ulong idx; + zend_string *tmp_key; + zval *tmp_val; + + (void)(idx); + ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(val), idx, tmp_key, tmp_val) { + if (tmp_key) { + php_error_docref(NULL, E_WARNING, "Multiple header key must be numeric index (%s)", ZSTR_VAL(tmp_key)); + continue; + } + if (Z_TYPE_P(tmp_val) != IS_STRING) { + php_error_docref(NULL, E_WARNING, "Multiple header values must be string (%s)", ZSTR_VAL(key)); + continue; + } + php_mail_build_headers_elem(s, key, tmp_val); + } ZEND_HASH_FOREACH_END(); +} + + +PHPAPI zend_string *php_mail_build_headers(zval *headers) +{ + zend_ulong idx; + zend_string *key; + zval *val; + smart_str s = {0}; + + ZEND_ASSERT(Z_TYPE_P(headers) == IS_ARRAY); + + ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(headers), idx, key, val) { + if (!key) { + php_error_docref(NULL, E_WARNING, "Found numeric header (" ZEND_LONG_FMT ")", idx); + continue; + } + /* https://tools.ietf.org/html/rfc2822#section-3.6 */ + switch(ZSTR_LEN(key)) { + case sizeof("orig-date")-1: + if (!strncasecmp("orig-date", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("orig-date", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("from")-1: + if (!strncasecmp("from", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("from", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("sender")-1: + if (!strncasecmp("sender", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("sender", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("reply-to")-1: + if (!strncasecmp("reply-to", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("reply-to", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("to")-1: /* "to", "cc" */ + if (!strncasecmp("to", ZSTR_VAL(key), ZSTR_LEN(key))) { + php_error_docref(NULL, E_WARNING, "Extra header cannot contain 'To' header"); + continue; + } + if (!strncasecmp("cc", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("cc", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("bcc")-1: + if (!strncasecmp("bcc", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("bcc", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("message-id")-1: /* "references" */ + if (!strncasecmp("message-id", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("message-id", s, key, val); + } else if (!strncasecmp("references", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("references", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("in-reply-to")-1: + if (!strncasecmp("in-reply-to", ZSTR_VAL(key), ZSTR_LEN(key))) { + PHP_MAIL_BUILD_HEADER_CHECK("in-reply-to", s, key, val); + } else { + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + break; + case sizeof("subject")-1: + if (!strncasecmp("subject", ZSTR_VAL(key), ZSTR_LEN(key))) { + php_error_docref(NULL, E_WARNING, "Extra header cannot contain 'Subject' header"); + continue; + } + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + break; + default: + PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val); + } + } ZEND_HASH_FOREACH_END(); + + /* Remove the last \r\n */ + if (s.s) s.s->len -= 2; + smart_str_0(&s); + + return s.s; +} + + /* {{{ proto int mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]]) Send an email message */ PHP_FUNCTION(mail) { char *to=NULL, *message=NULL; char *subject=NULL; - zend_string *extra_cmd=NULL, *headers=NULL, *headers_trimmed=NULL; + zend_string *extra_cmd=NULL, *str_headers=NULL, *tmp_headers; + zval *headers = NULL; size_t to_len, message_len; size_t subject_len, i; char *force_extra_parameters = INI_STR("mail.force_extra_parameters"); char *to_r, *subject_r; char *p, *e; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|SS", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &extra_cmd) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|zS", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &extra_cmd) == FAILURE) { return; } @@ -118,8 +309,20 @@ PHP_FUNCTION(mail) MAIL_ASCIIZ_CHECK(subject, subject_len); MAIL_ASCIIZ_CHECK(message, message_len); if (headers) { - MAIL_ASCIIZ_CHECK(ZSTR_VAL(headers), ZSTR_LEN(headers)); - headers_trimmed = php_trim(headers, NULL, 0, 2); + switch(Z_TYPE_P(headers)) { + case IS_STRING: + tmp_headers = zend_string_init(Z_STRVAL_P(headers), Z_STRLEN_P(headers), 0); + MAIL_ASCIIZ_CHECK(ZSTR_VAL(tmp_headers), ZSTR_LEN(tmp_headers)); + str_headers = php_trim(tmp_headers, NULL, 0, 2); + zend_string_release(tmp_headers); + break; + case IS_ARRAY: + str_headers = php_mail_build_headers(headers); + break; + default: + php_error_docref(NULL, E_WARNING, "headers parameter must be string or array"); + RETURN_FALSE; + } } if (extra_cmd) { MAIL_ASCIIZ_CHECK(ZSTR_VAL(extra_cmd), ZSTR_LEN(extra_cmd)); @@ -171,14 +374,14 @@ PHP_FUNCTION(mail) extra_cmd = php_escape_shell_cmd(ZSTR_VAL(extra_cmd)); } - if (php_mail(to_r, subject_r, message, headers_trimmed ? ZSTR_VAL(headers_trimmed) : NULL, extra_cmd ? ZSTR_VAL(extra_cmd) : NULL)) { + if (php_mail(to_r, subject_r, message, str_headers ? ZSTR_VAL(str_headers) : NULL, extra_cmd ? ZSTR_VAL(extra_cmd) : NULL)) { RETVAL_TRUE; } else { RETVAL_FALSE; } - if (headers_trimmed) { - zend_string_release(headers_trimmed); + if (str_headers) { + zend_string_release(str_headers); } if (extra_cmd) { diff --git a/ext/standard/php_mail.h b/ext/standard/php_mail.h index 514b189681..6f7d703312 100644 --- a/ext/standard/php_mail.h +++ b/ext/standard/php_mail.h @@ -22,9 +22,39 @@ #define PHP_MAIL_H PHP_FUNCTION(mail); +PHP_FUNCTION(ezmlm_hash); + PHP_MINFO_FUNCTION(mail); -PHP_FUNCTION(ezmlm_hash); +PHPAPI zend_string *php_mail_build_headers(zval *headers); PHPAPI extern int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd); +#define PHP_MAIL_BUILD_HEADER_CHECK(target, s, key, val) \ +do { \ + if (Z_TYPE_P(val) == IS_STRING) { \ + php_mail_build_headers_elem(&s, key, val); \ + } else if (Z_TYPE_P(val) == IS_ARRAY) { \ + if (!strncasecmp(target, ZSTR_VAL(key), ZSTR_LEN(key))) { \ + php_error_docref(NULL, E_WARNING, "'%s' header must be at most one header. Array is passed for '%s'", target, target); \ + continue; \ + } \ + php_mail_build_headers_elems(&s, key, val); \ + } else { \ + php_error_docref(NULL, E_WARNING, "Extra header element '%s' cannot be other than string or array.", ZSTR_VAL(key)); \ + } \ +} while(0) + + +#define PHP_MAIL_BUILD_HEADER_DEFAULT(s, key, val) \ +do { \ + if (Z_TYPE_P(val) == IS_STRING) { \ + php_mail_build_headers_elem(&s, key, val); \ + } else if (Z_TYPE_P(val) == IS_ARRAY) { \ + php_mail_build_headers_elems(&s, key, val); \ + } else { \ + php_error_docref(NULL, E_WARNING, "Extra header element '%s' cannot be other than string or array.", ZSTR_VAL(key)); \ + } \ +} while(0) + + #endif /* PHP_MAIL_H */ diff --git a/ext/standard/tests/mail/mail_basic7.phpt b/ext/standard/tests/mail/mail_basic7.phpt new file mode 100644 index 0000000000..3b389d2c4e --- /dev/null +++ b/ext/standard/tests/mail/mail_basic7.phpt @@ -0,0 +1,218 @@ +--TEST-- +Test mail() function : array extra header basic functionality +--INI-- +sendmail_path=tee mailBasic.out >/dev/null +mail.add_x_header = Off +--SKIPIF-- + +--FILE-- + 'aaaa', + 'bcc'=>'foo@bar', + 'foo'=> + array( + "bar\r\n hoge", + "bar\r\n\t fuga", + ), +); +$outFile = "mailBasic.out"; +@unlink($outFile); + +echo "-- All Mail Content Parameters --\n"; +// Calling mail() with all additional headers +var_dump( mail($to, $subject, $message, $additional_headers) ); +echo file_get_contents($outFile); +unlink($outFile); + + +echo "\n\n************* TEST ******************\n"; +// Should fail all +// Initialise all required variables +$to = 'user@example.com'; +$subject = 'Test Subject'; +$message = 'A Message'; +// Headers should not have array values +$additional_headers = array( + 'orig-date' => array('foo1'), + 'from' => array('foo2'), + 'sender' => array('foo3'), + 'reply-to' => array('foo4'), + 'to' => array('foo5'), + 'bcc' => array('foo6'), + 'message-id' => array('foo7'), + 'in-reply-to'=> array('foo8'), +); +$outFile = "mailBasic.out"; +@unlink($outFile); + +echo "-- All Mail Content Parameters --\n"; +// Calling mail() with all additional headers +var_dump( mail($to, $subject, $message, $additional_headers) ); +echo file_get_contents($outFile); +unlink($outFile); + + +echo "\n\n************* TEST ******************\n"; +// Should fail all +// Initialise all required variables +$to = 'user@example.com'; +$subject = 'Test Subject'; +$message = 'A Message'; +$additional_headers = array( + 'foo1' => array('foo1'=>'bar1'), + 'foo2' => array('foo2', array('foo3')), + 'foo3' => array(123), + 'foo4' => array(123.456), + 'foo5' => array(FALSE), + 'foo6' => array(NULL), + 'foo7' => array(new StdClass), +); +$outFile = "mailBasic.out"; +@unlink($outFile); + +echo "-- All Mail Content Parameters --\n"; +// Calling mail() with all additional headers +var_dump( mail($to, $subject, $message, $additional_headers) ); +echo file_get_contents($outFile); +unlink($outFile); + + +echo "\n\n************* TEST ******************\n"; +// Should fail most +// Initialise all required variables +$to = 'user@example.com'; +$subject = 'Test Subject'; +$message = 'A Message'; +$additional_headers = array( + '*:foo1' => array('bar1'), + 'foo2:::' => array('bar1'), + 'foo3()' => array('bar1'), + 'foo4@' => array('bar1'), + 'foo5|' => array('bar1'), + "\0foo6" => array('bar1'), + "foo7\0" => array('bar1'), + "foo8" => array(), + "foo9" => '%&$#!', + "foo10" => "abc\0\tdef", +); +$outFile = "mailBasic.out"; +@unlink($outFile); + +echo "-- All Mail Content Parameters --\n"; +// Calling mail() with all additional headers +var_dump( mail($to, $subject, $message, $additional_headers) ); +echo file_get_contents($outFile); +unlink($outFile); + +?> +===DONE=== +--EXPECTF-- +*** Testing mail() : basic functionality *** + + +************* TEST ****************** +-- All Mail Content Parameters -- +bool(true) +To: user@example.com +Subject: Test Subject +KHeaders: aaaa +bcc: foo@bar +foo: bar + hoge +foo: bar + fuga + +A Message + + +************* TEST ****************** +-- All Mail Content Parameters -- + +Warning: mail(): 'orig-date' header must be at most one header. Array is passed for 'orig-date' in %s on line 59 + +Warning: mail(): 'from' header must be at most one header. Array is passed for 'from' in %s on line 59 + +Warning: mail(): 'sender' header must be at most one header. Array is passed for 'sender' in %s on line 59 + +Warning: mail(): 'reply-to' header must be at most one header. Array is passed for 'reply-to' in %s on line 59 + +Warning: mail(): Extra header cannot contain 'To' header in %s on line 59 + +Warning: mail(): 'bcc' header must be at most one header. Array is passed for 'bcc' in %s on line 59 + +Warning: mail(): 'message-id' header must be at most one header. Array is passed for 'message-id' in %s on line 59 + +Warning: mail(): 'in-reply-to' header must be at most one header. Array is passed for 'in-reply-to' in %s on line 59 +bool(true) +To: user@example.com +Subject: Test Subject + +A Message + + +************* TEST ****************** +-- All Mail Content Parameters -- + +Warning: mail(): Multiple header key must be numeric index (foo1) in %s on line 84 + +Warning: mail(): Multiple header values must be string (foo2) in %s on line 84 + +Warning: mail(): Multiple header values must be string (foo3) in %s on line 84 + +Warning: mail(): Multiple header values must be string (foo4) in %s on line 84 + +Warning: mail(): Multiple header values must be string (foo5) in %s on line 84 + +Warning: mail(): Multiple header values must be string (foo6) in %s on line 84 + +Warning: mail(): Multiple header values must be string (foo7) in %s on line 84 +bool(true) +To: user@example.com +Subject: Test Subject +foo2: foo2 + +A Message + + +************* TEST ****************** +-- All Mail Content Parameters -- + +Warning: mail(): Header field name (*:foo1) contains invalid chars in %s on line 112 + +Warning: mail(): Header field name (foo2:::) contains invalid chars in %s on line 112 + +Warning: mail(): Header field name () contains invalid chars in %s on line 112 + +Warning: mail(): Header field name (foo7) contains invalid chars in %s on line 112 + +Warning: mail(): Header field value (foo10 => abc) contains invalid chars or format in %s on line 112 +bool(true) +To: user@example.com +Subject: Test Subject +foo3(): bar1 +foo4@: bar1 +foo5|: bar1 +foo9: %&$#! + +A Message +===DONE=== -- 2.40.0