Mail: Improve handling of UTF-8 address headers.

Previously, `wp_mail()` implemented Reply-To as a generic header, using
PHPMailer's `addCustomHeader()`. As such, the email address portion of
the header was being incorrectly encoded when the name portion
contained UTF-8 characters. Switching to PHPMailer's more specific
`addReplyTo()` method fixes the issue.

For greater readability, the handling of all address-related headers
(To, CC, BCC, Reply-To) has been standardized.

Props szepe.viktor, iandunn, bpetty, stephenharris.
Fixes #21659.
Built from https://develop.svn.wordpress.org/trunk@38058


git-svn-id: http://core.svn.wordpress.org/trunk@37999 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Boone Gorges 2016-07-13 18:04:28 +00:00
parent 98d03cb738
commit 905f4ec0f8
2 changed files with 36 additions and 44 deletions

View File

@ -216,6 +216,8 @@ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array()
} }
// Headers // Headers
$cc = $bcc = $reply_to = array();
if ( empty( $headers ) ) { if ( empty( $headers ) ) {
$headers = array(); $headers = array();
} else { } else {
@ -227,8 +229,6 @@ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array()
$tempheaders = $headers; $tempheaders = $headers;
} }
$headers = array(); $headers = array();
$cc = array();
$bcc = array();
// If it's actually got contents // If it's actually got contents
if ( !empty( $tempheaders ) ) { if ( !empty( $tempheaders ) ) {
@ -291,6 +291,9 @@ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array()
case 'bcc': case 'bcc':
$bcc = array_merge( (array) $bcc, explode( ',', $content ) ); $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
break; break;
case 'reply-to':
$reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
break;
default: default:
// Add it to our grand headers array // Add it to our grand headers array
$headers[trim( $name )] = trim( $content ); $headers[trim( $name )] = trim( $content );
@ -335,7 +338,7 @@ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array()
* *
* @param string $from_email Email address to send from. * @param string $from_email Email address to send from.
*/ */
$phpmailer->From = apply_filters( 'wp_mail_from', $from_email ); $from_email = apply_filters( 'wp_mail_from', $from_email );
/** /**
* Filters the name to associate with the "from" email address. * Filters the name to associate with the "from" email address.
@ -344,63 +347,52 @@ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array()
* *
* @param string $from_name Name associated with the "from" email address. * @param string $from_name Name associated with the "from" email address.
*/ */
$phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name ); $from_name = apply_filters( 'wp_mail_from_name', $from_name );
$phpmailer->setFrom( $from_email, $from_name );
// Set destination addresses // Set destination addresses
if ( !is_array( $to ) ) if ( !is_array( $to ) )
$to = explode( ',', $to ); $to = explode( ',', $to );
foreach ( (array) $to as $recipient ) {
try {
// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
$recipient_name = '';
if ( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {
if ( count( $matches ) == 3 ) {
$recipient_name = $matches[1];
$recipient = $matches[2];
}
}
$phpmailer->AddAddress( $recipient, $recipient_name);
} catch ( phpmailerException $e ) {
continue;
}
}
// Set mail's subject and body // Set mail's subject and body
$phpmailer->Subject = $subject; $phpmailer->Subject = $subject;
$phpmailer->Body = $message; $phpmailer->Body = $message;
// Add any CC and BCC recipients // Use appropriate methods for handling addresses, rather than treating them as generic headers
if ( !empty( $cc ) ) { $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
foreach ( (array) $cc as $recipient ) {
try {
// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
$recipient_name = '';
if ( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {
if ( count( $matches ) == 3 ) {
$recipient_name = $matches[1];
$recipient = $matches[2];
}
}
$phpmailer->AddCc( $recipient, $recipient_name );
} catch ( phpmailerException $e ) {
continue;
}
}
}
if ( !empty( $bcc ) ) { foreach ( $address_headers as $address_header => $addresses ) {
foreach ( (array) $bcc as $recipient) { if ( empty( $addresses ) ) {
continue;
}
foreach ( (array) $addresses as $address ) {
try { try {
// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>" // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
$recipient_name = ''; $recipient_name = '';
if ( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {
if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
if ( count( $matches ) == 3 ) { if ( count( $matches ) == 3 ) {
$recipient_name = $matches[1]; $recipient_name = $matches[1];
$recipient = $matches[2]; $address = $matches[2];
} }
} }
$phpmailer->AddBcc( $recipient, $recipient_name );
switch ( $address_header ) {
case 'to':
$phpmailer->addAddress( $address, $recipient_name );
break;
case 'cc':
$phpmailer->addCc( $address, $recipient_name );
break;
case 'bcc':
$phpmailer->addBcc( $address, $recipient_name );
break;
case 'reply_to':
$phpmailer->addReplyTo( $address, $recipient_name );
break;
}
} catch ( phpmailerException $e ) { } catch ( phpmailerException $e ) {
continue; continue;
} }

View File

@ -4,7 +4,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '4.6-beta2-38057'; $wp_version = '4.6-beta2-38058';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.