WordPress.org

Make WordPress Core


Ignore:
Timestamp:
07/13/16 18:03:52 (12 months ago)
Author:
boonebgorges
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/pluggable.php

    r38028 r38058  
    217217 
    218218    // Headers 
     219    $cc = $bcc = $reply_to = array(); 
     220 
    219221    if ( empty( $headers ) ) { 
    220222        $headers = array(); 
     
    228230        } 
    229231        $headers = array(); 
    230         $cc = array(); 
    231         $bcc = array(); 
    232232 
    233233        // If it's actually got contents 
     
    292292                        $bcc = array_merge( (array) $bcc, explode( ',', $content ) ); 
    293293                        break; 
     294                    case 'reply-to': 
     295                        $reply_to = array_merge( (array) $reply_to, explode( ',', $content ) ); 
     296                        break; 
    294297                    default: 
    295298                        // Add it to our grand headers array 
     
    336339     * @param string $from_email Email address to send from. 
    337340     */ 
    338     $phpmailer->From = apply_filters( 'wp_mail_from', $from_email ); 
     341    $from_email = apply_filters( 'wp_mail_from', $from_email ); 
    339342 
    340343    /** 
     
    345348     * @param string $from_name Name associated with the "from" email address. 
    346349     */ 
    347     $phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name ); 
     350    $from_name = apply_filters( 'wp_mail_from_name', $from_name ); 
     351 
     352    $phpmailer->setFrom( $from_email, $from_name ); 
    348353 
    349354    // Set destination addresses 
     
    351356        $to = explode( ',', $to ); 
    352357 
    353     foreach ( (array) $to as $recipient ) { 
    354         try { 
    355             // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>" 
    356             $recipient_name = ''; 
    357             if ( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) { 
    358                 if ( count( $matches ) == 3 ) { 
    359                     $recipient_name = $matches[1]; 
    360                     $recipient = $matches[2]; 
    361                 } 
    362             } 
    363             $phpmailer->AddAddress( $recipient, $recipient_name); 
    364         } catch ( phpmailerException $e ) { 
    365             continue; 
    366         } 
    367     } 
    368  
    369358    // Set mail's subject and body 
    370359    $phpmailer->Subject = $subject; 
    371360    $phpmailer->Body    = $message; 
    372361 
    373     // Add any CC and BCC recipients 
    374     if ( !empty( $cc ) ) { 
    375         foreach ( (array) $cc as $recipient ) { 
     362    // Use appropriate methods for handling addresses, rather than treating them as generic headers 
     363    $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' ); 
     364 
     365    foreach ( $address_headers as $address_header => $addresses ) { 
     366        if ( empty( $addresses ) ) { 
     367            continue; 
     368        } 
     369 
     370        foreach ( (array) $addresses as $address ) { 
    376371            try { 
    377372                // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>" 
    378373                $recipient_name = ''; 
    379                 if ( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) { 
     374 
     375                if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) { 
    380376                    if ( count( $matches ) == 3 ) { 
    381377                        $recipient_name = $matches[1]; 
    382                         $recipient = $matches[2]; 
     378                        $address        = $matches[2]; 
    383379                    } 
    384380                } 
    385                 $phpmailer->AddCc( $recipient, $recipient_name ); 
    386             } catch ( phpmailerException $e ) { 
    387                 continue; 
    388             } 
    389         } 
    390     } 
    391  
    392     if ( !empty( $bcc ) ) { 
    393         foreach ( (array) $bcc as $recipient) { 
    394             try { 
    395                 // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>" 
    396                 $recipient_name = ''; 
    397                 if ( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) { 
    398                     if ( count( $matches ) == 3 ) { 
    399                         $recipient_name = $matches[1]; 
    400                         $recipient = $matches[2]; 
    401                     } 
     381 
     382                switch ( $address_header ) { 
     383                    case 'to': 
     384                        $phpmailer->addAddress( $address, $recipient_name ); 
     385                        break; 
     386                    case 'cc': 
     387                        $phpmailer->addCc( $address, $recipient_name ); 
     388                        break; 
     389                    case 'bcc': 
     390                        $phpmailer->addBcc( $address, $recipient_name ); 
     391                        break; 
     392                    case 'reply_to': 
     393                        $phpmailer->addReplyTo( $address, $recipient_name ); 
     394                        break; 
    402395                } 
    403                 $phpmailer->AddBcc( $recipient, $recipient_name ); 
    404396            } catch ( phpmailerException $e ) { 
    405397                continue; 
Note: See TracChangeset for help on using the changeset viewer.