From bffb632183343b3e65bbdd565ba83aae1f03b05e Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Tue, 7 Apr 2015 20:09:46 +0000 Subject: [PATCH] Improve handling of incomplete From and Content-Type headers in `wp_mail()`. When an incomplete header is provided (eg, 'From' with an email address but no name), ensure that the WP defaults are filled in properly. Props valendesigns. Fixes #30266. git-svn-id: https://develop.svn.wordpress.org/trunk@32070 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/pluggable.php | 33 ++++++++----- tests/phpunit/tests/mail.php | 90 +++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 13 deletions(-) diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php index 574fc129e8..0e02782b3d 100644 --- a/src/wp-includes/pluggable.php +++ b/src/wp-includes/pluggable.php @@ -302,30 +302,37 @@ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() switch ( strtolower( $name ) ) { // Mainly for legacy -- process a From: header if it's there case 'from': - if ( strpos($content, '<' ) !== false ) { - // So... making my life hard again? - $from_name = substr( $content, 0, strpos( $content, '<' ) - 1 ); - $from_name = str_replace( '"', '', $from_name ); - $from_name = trim( $from_name ); + $bracket_pos = strpos( $content, '<' ); + if ( $bracket_pos !== false ) { + // Text before the bracketed email is the "From" name. + if ( $bracket_pos > 0 ) { + $from_name = substr( $content, 0, $bracket_pos - 1 ); + $from_name = str_replace( '"', '', $from_name ); + $from_name = trim( $from_name ); + } - $from_email = substr( $content, strpos( $content, '<' ) + 1 ); + $from_email = substr( $content, $bracket_pos + 1 ); $from_email = str_replace( '>', '', $from_email ); $from_email = trim( $from_email ); - } else { + + // Avoid setting an empty $from_email. + } elseif ( '' !== trim( $content ) ) { $from_email = trim( $content ); } break; case 'content-type': if ( strpos( $content, ';' ) !== false ) { - list( $type, $charset ) = explode( ';', $content ); + list( $type, $charset_content ) = explode( ';', $content ); $content_type = trim( $type ); - if ( false !== stripos( $charset, 'charset=' ) ) { - $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset ) ); - } elseif ( false !== stripos( $charset, 'boundary=' ) ) { - $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset ) ); + if ( false !== stripos( $charset_content, 'charset=' ) ) { + $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) ); + } elseif ( false !== stripos( $charset_content, 'boundary=' ) ) { + $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) ); $charset = ''; } - } else { + + // Avoid setting an empty $content_type. + } elseif ( '' !== trim( $content ) ) { $content_type = trim( $content ); } break; diff --git a/tests/phpunit/tests/mail.php b/tests/phpunit/tests/mail.php index 2ca73dd1ec..4053966d71 100644 --- a/tests/phpunit/tests/mail.php +++ b/tests/phpunit/tests/mail.php @@ -156,4 +156,94 @@ class Tests_Mail extends WP_UnitTestCase { // Fatal errors $this->assertFalse( wp_mail( 'invalid.address', 'subject', 'body', '', array() ) ); } + + /** + * @ticket 30266 + */ + public function test_wp_mail_with_valid_from_header() { + $to = "address@tld.com"; + $subject = "Testing"; + $message = "Test Message"; + $headers = "From: Foo "; + $expected = "From: Foo "; + + wp_mail( $to, $subject, $message, $headers ); + + $this->assertTrue( strpos( $GLOBALS['phpmailer']->mock_sent[0]['header'], $expected ) > 0 ); + } + + /** + * @ticket 30266 + */ + public function test_wp_mail_with_empty_from_header() { + $to = "address@tld.com"; + $subject = "Testing"; + $message = "Test Message"; + $headers = "From: "; + $expected = "From: WordPress "; + + wp_mail( $to, $subject, $message, $headers ); + + $this->assertTrue( strpos( $GLOBALS['phpmailer']->mock_sent[0]['header'], $expected ) > 0 ); + } + + /** + * @ticket 30266 + */ + public function test_wp_mail_with_empty_from_name_for_the_from_header() { + $to = "address@tld.com"; + $subject = "Testing"; + $message = "Test Message"; + $headers = "From: "; + $expected = "From: WordPress "; + + wp_mail( $to, $subject, $message, $headers ); + + $this->assertTrue( strpos( $GLOBALS['phpmailer']->mock_sent[0]['header'], $expected ) > 0 ); + } + + /** + * @ticket 30266 + */ + public function test_wp_mail_with_valid_content_type_header() { + $to = "address@tld.com"; + $subject = "Testing"; + $message = "Test Message"; + $headers = "Content-Type: text/html; charset=iso-8859-1"; + $expected = "Content-Type: text/html; charset=iso-8859-1"; + + wp_mail( $to, $subject, $message, $headers ); + + $this->assertTrue( strpos( $GLOBALS['phpmailer']->mock_sent[0]['header'], $expected ) > 0 ); + } + + /** + * @ticket 30266 + */ + public function test_wp_mail_with_empty_content_type_header() { + $to = "address@tld.com"; + $subject = "Testing"; + $message = "Test Message"; + $headers = "Content-Type: "; + $expected = "Content-Type: text/plain; charset=UTF-8"; + + wp_mail( $to, $subject, $message, $headers ); + + $this->assertTrue( strpos( $GLOBALS['phpmailer']->mock_sent[0]['header'], $expected ) > 0 ); + } + + /** + * @ticket 30266 + */ + public function test_wp_mail_with_empty_charset_for_the_content_type_header() { + $to = "address@tld.com"; + $subject = "Testing"; + $message = "Test Message"; + $headers = "Content-Type: text/plain;"; + $expected = "Content-Type: text/plain; charset=UTF-8"; + + wp_mail( $to, $subject, $message, $headers ); + + $this->assertTrue( strpos( $GLOBALS['phpmailer']->mock_sent[0]['header'], $expected ) > 0 ); + } }