WordPress.org

Make WordPress Core

Ticket #15448: 15448_Sep2016.diff

File 15448_Sep2016.diff, 7.9 KB (added by gitlost, 3 years ago)

Refresh for 4.7. Includes unit tests.

  • src/wp-includes/pluggable.php

     
    156156 * However, you can set the content type of the email by using the
    157157 * {@see 'wp_mail_content_type'} filter.
    158158 *
     159 * If $message is an array, the key of each is used to add as an attachment
     160 * with the value used as the body. The 'text/plain' element is used as the
     161 * text version of the body, with the 'text/html' element used as the HTML
     162 * version of the body. All other types are added as attachments.
     163 *
    159164 * The default charset is based on the charset used on the blog. The charset can
    160165 * be set using the {@see 'wp_mail_charset'} filter.
    161166 *
     
    165170 *
    166171 * @param string|array $to          Array or comma-separated list of email addresses to send message.
    167172 * @param string       $subject     Email subject
    168  * @param string      $message     Message contents
     173 * @param string|array $message     Message contents
    169174 * @param string|array $headers     Optional. Additional headers.
    170175 * @param string|array $attachments Optional. Files to attach.
    171176 * @return bool Whether the email contents were sent successfully.
     
    270275                                                }
    271276                                                break;
    272277                                        case 'content-type':
     278                                                if ( is_array( $message ) ) {
     279                                                        // Multipart email, ignore the content-type header
     280                                                        break;
     281                                                }
    273282                                                if ( strpos( $content, ';' ) !== false ) {
    274283                                                        list( $type, $charset_content ) = explode( ';', $content );
    275284                                                        $content_type = trim( $type );
     
    309318        $phpmailer->ClearCustomHeaders();
    310319        $phpmailer->ClearReplyTos();
    311320
     321        $phpmailer->Body= '';
     322        $phpmailer->AltBody= '';
     323
    312324        // From email and name
    313325        // If we don't have a name from the input headers
    314326        if ( !isset( $from_name ) )
     
    355367        if ( !is_array( $to ) )
    356368                $to = explode( ',', $to );
    357369
    358         // Set mail's subject and body
    359         $phpmailer->Subject = $subject;
    360         $phpmailer->Body    = $message;
    361 
    362370        // Use appropriate methods for handling addresses, rather than treating them as generic headers
    363371        $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
    364372
     
    399407                }
    400408        }
    401409
    402         // Set to use PHP's mail()
    403         $phpmailer->IsMail();
    404 
    405         // Set Content-Type and charset
    406         // If we don't have a content-type from the input headers
    407         if ( !isset( $content_type ) )
    408                 $content_type = 'text/plain';
    409 
    410         /**
    411          * Filters the wp_mail() content type.
    412          *
    413          * @since 2.3.0
    414          *
    415          * @param string $content_type Default wp_mail() content type.
    416          */
    417         $content_type = apply_filters( 'wp_mail_content_type', $content_type );
    418 
    419         $phpmailer->ContentType = $content_type;
    420 
    421         // Set whether it's plaintext, depending on $content_type
    422         if ( 'text/html' == $content_type )
    423                 $phpmailer->IsHTML( true );
    424 
     410        // Set charset
    425411        // If we don't have a charset from the input headers
    426412        if ( !isset( $charset ) )
    427413                $charset = get_bloginfo( 'charset' );
    428414
    429         // Set the content-type and charset
    430 
    431415        /**
    432416         * Filters the default wp_mail() charset.
    433417         *
     
    437421         */
    438422        $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
    439423
     424        // Set mail's subject and body
     425        $phpmailer->Subject = $subject;
     426
     427        if ( is_string( $message ) ) {
     428                $phpmailer->Body = $message;
     429
     430                // Set Content-Type
     431                // If we don't have a content-type from the input headers
     432                if ( ! isset( $content_type ) ) {
     433                        $content_type = 'text/plain';
     434                }
     435
     436                /**
     437                 * Filters the wp_mail() content type.
     438                 *
     439                 * @since 2.3.0
     440                 *
     441                 * @param string $content_type Default wp_mail() content type.
     442                 */
     443                $content_type = apply_filters( 'wp_mail_content_type', $content_type );
     444
     445                $phpmailer->ContentType = $content_type;
     446
     447                // Set whether it's plaintext, depending on $content_type
     448                if ( 'text/html' === $content_type ) {
     449                        $phpmailer->IsHTML( true );
     450                }
     451
     452                // For backwards compatibility, new multipart emails should use
     453                // the array style $message. This never really worked well anyway
     454                if ( false !== stripos( $content_type, 'multipart' ) && ! empty( $boundary ) ) {
     455                        $phpmailer->AddCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
     456                }
     457        } elseif ( is_array( $message ) ) {
     458                foreach ( $message as $type => $bodies ) {
     459                        foreach ( (array) $bodies as $body ) {
     460                                if ( 'text/html' === $type ) {
     461                                        $phpmailer->Body = $body;
     462                                } elseif ( 'text/plain' === $type ) {
     463                                        $phpmailer->AltBody = $body;
     464                                } else {
     465                                        $phpmailer->AddAttachment( $body, '', 'base64', $type );
     466                                }
     467                        }
     468                }
     469        }
     470
     471        // Set to use PHP's mail()
     472        $phpmailer->IsMail();
     473
    440474        // Set custom headers
    441475        if ( !empty( $headers ) ) {
    442476                foreach ( (array) $headers as $name => $content ) {
    443477                        $phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
    444478                }
    445 
    446                 if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) )
    447                         $phpmailer->AddCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
    448479        }
    449480
    450481        if ( !empty( $attachments ) ) {
  • tests/phpunit/tests/mail.php

     
    8787        }
    8888
    8989        /**
     90         * @ticket 15448
     91         */
     92        function test_wp_mail_plain_and_html() {
     93                $to = 'user@example.com';
     94                $subject = 'Test email with plain text and html versions';
     95                $messages = array( 'text/plain' => 'Here is some plain text.',
     96                                           'text/html' =>'<html><head></head><body>Here is the HTML with UTF-8 γειά σου Κόσμε;-)<body></html>' );
     97
     98                wp_mail( $to, $subject, $messages );
     99
     100                preg_match( '/boundary="(.*)"/', $GLOBALS['phpmailer']->mock_sent[0]['header'], $matches );
     101                $boundry = $matches[1];
     102                $body = 'This is a multi-part message in MIME format.
     103
     104--' . $boundry . '
     105Content-Type: text/plain; charset=us-ascii
     106
     107Here is some plain text.
     108
     109
     110--' . $boundry . '
     111Content-Type: text/html; charset=UTF-8
     112Content-Transfer-Encoding: 8bit
     113
     114<html><head></head><body>Here is the HTML with UTF-8 γειά σου Κόσμε;-)<body></html>
     115
     116
     117
     118--' . $boundry . '--
     119';
     120                // We need some better assertions here but these test the behaviour for now.
     121                $this->assertEquals( $body, $GLOBALS['phpmailer']->mock_sent[0]['body'] );
     122                $this->assertSame( 1, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['header'], 'Content-Type: multipart/alternative;' ) );
     123                $this->assertSame( 1, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['header'], 'Content-Type:' ) );
     124        }
     125
     126        /*
     127         * 'phpmailer_init' action for test_wp_mail_plain_and_html_workaround().
     128         */
     129        function wp_mail_set_alt_body( $mailer ) {
     130                $mailer->AltBody = strip_tags( $mailer->Body );
     131        }
     132
     133        /**
     134         * @ticket 15448
     135         *
     136         * Check workarounds using phpmailer_init still work around.
     137         */
     138        function test_wp_mail_plain_and_html_workaround() {
     139                $to = 'user@example.com';
     140                $subject = 'Test email with plain text derived from html version';
     141                $message = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><p>Hello World! γειά σου Κόσμε</p></body></html>';
     142
     143                add_action( 'phpmailer_init', array( $this, 'wp_mail_set_alt_body' ) );
     144                wp_mail( $to, $subject, $message );
     145                remove_action( 'phpmailer_init', array( $this, 'wp_mail_set_alt_body' ) );
     146
     147                $this->assertSame( 1, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['header'], 'Content-Type: multipart/alternative;' ) );
     148                $this->assertSame( 1, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['header'], 'Content-Type:' ) );
     149                $this->assertSame( 1, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['body'], 'Content-Type: text/plain; charset=UTF-8' ) );
     150                $this->assertSame( 1, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['body'], 'Content-Type: text/html; charset=UTF-8' ) );
     151                $this->assertSame( 2, substr_count( $GLOBALS['phpmailer']->mock_sent[0]['body'], 'Content-Type:' ) );
     152        }
     153
     154        /**
    90155         * @ticket 17305
    91156         */
    92157        function test_wp_mail_rfc2822_addresses() {