WordPress.org

Make WordPress Core

Ticket #15448: 15448_Sep2019.11.diff

File 15448_Sep2019.11.diff, 8.3 KB (added by bgermann, 4 months ago)

Refresh of the patch

  • src/wp-includes/pluggable.php

    diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php
    index 9336e03c7e..09ec4503db 100644
    a b if ( ! function_exists( 'wp_mail' ) ) : 
    153153         * However, you can set the content type of the email by using the
    154154         * {@see 'wp_mail_content_type'} filter.
    155155         *
     156         * If $message is an array, the key of each is used to add as an attachment
     157         * with the value used as the body. The 'text/plain' element is used as the
     158         * text version of the body, with the 'text/html' element used as the HTML
     159         * version of the body. All other types are added as attachments.
     160         *
    156161         * The default charset is based on the charset used on the blog. The charset can
    157162         * be set using the {@see 'wp_mail_charset'} filter.
    158163         *
    if ( ! function_exists( 'wp_mail' ) ) : 
    162167         *
    163168         * @param string|array $to          Array or comma-separated list of email addresses to send message.
    164169         * @param string       $subject     Email subject
    165          * @param string      $message     Message contents
     170         * @param string|array $message     Message contents
    166171         * @param string|array $headers     Optional. Additional headers.
    167172         * @param string|array $attachments Optional. Files to attach.
    168173         * @return bool Whether the email contents were sent successfully.
    if ( ! function_exists( 'wp_mail' ) ) : 
    273278                                                        }
    274279                                                        break;
    275280                                                case 'content-type':
     281                                                        if ( is_array( $message ) ) {
     282                                                                // Multipart email, ignore the content-type header
     283                                                                break;
     284                                                        }
    276285                                                        if ( strpos( $content, ';' ) !== false ) {
    277286                                                                list( $type, $charset_content ) = explode( ';', $content );
    278287                                                                $content_type                   = trim( $type );
    if ( ! function_exists( 'wp_mail' ) ) : 
    312321                $phpmailer->clearCustomHeaders();
    313322                $phpmailer->clearReplyTos();
    314323
     324                $phpmailer->Body= '';
     325                $phpmailer->AltBody= '';
     326
    315327                // From email and name
    316328                // If we don't have a name from the input headers
    317329                if ( ! isset( $from_name ) ) {
    if ( ! function_exists( 'wp_mail' ) ) : 
    365377                        return false;
    366378                }
    367379
    368                 // Set mail's subject and body
    369                 $phpmailer->Subject = $subject;
    370                 $phpmailer->Body    = $message;
    371 
    372380                // Set destination addresses, using appropriate methods for handling addresses
    373381                $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
    374382
    if ( ! function_exists( 'wp_mail' ) ) : 
    409417                        }
    410418                }
    411419
    412                 // Set to use PHP's mail()
    413                 $phpmailer->isMail();
    414 
    415                 // Set Content-Type and charset
    416                 // If we don't have a content-type from the input headers
    417                 if ( ! isset( $content_type ) ) {
    418                         $content_type = 'text/plain';
    419                 }
    420 
    421                 /**
    422                  * Filters the wp_mail() content type.
    423                  *
    424                  * @since 2.3.0
    425                  *
    426                  * @param string $content_type Default wp_mail() content type.
    427                  */
    428                 $content_type = apply_filters( 'wp_mail_content_type', $content_type );
    429 
    430                 $phpmailer->ContentType = $content_type;
    431 
    432                 // Set whether it's plaintext, depending on $content_type
    433                 if ( 'text/html' == $content_type ) {
    434                         $phpmailer->isHTML( true );
    435                 }
    436 
     420                // Set a charset
    437421                // If we don't have a charset from the input headers
    438422                if ( ! isset( $charset ) ) {
    439423                        $charset = get_bloginfo( 'charset' );
    440424                }
    441425
    442                 // Set the content-type and charset
    443 
    444426                /**
    445427                 * Filters the default wp_mail() charset.
    446428                 *
    if ( ! function_exists( 'wp_mail' ) ) : 
    450432                 */
    451433                $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
    452434
    453                 // Set custom headers
    454                 if ( ! empty( $headers ) ) {
    455                         foreach ( (array) $headers as $name => $content ) {
    456                                 $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
     435                // Set mail's subject and body
     436                $phpmailer->Subject = $subject;
     437
     438                if ( is_string( $message ) ) {
     439                        $phpmailer->Body = $message;
     440
     441                        // Set Content-Type
     442                        // If we don't have a content-type from the input headers
     443                        if ( ! isset( $content_type ) ) {
     444                                $content_type = 'text/plain';
    457445                        }
    458446
     447                        /**
     448                         * Filters the wp_mail() content type.
     449                         *
     450                         * @since 2.3.0
     451                         *
     452                         * @param string $content_type Default wp_mail() content type.
     453                         */
     454                        $content_type = apply_filters( 'wp_mail_content_type', $content_type );
     455
     456                        $phpmailer->ContentType = $content_type;
     457
     458                        // Set whether it's plaintext, depending on $content_type
     459                        if ( 'text/html' === $content_type ) {
     460                                $phpmailer->isHTML( true );
     461                        }
     462
     463                        // For backwards compatibility, new multipart emails should use
     464                        // the array style $message. This never really worked well anyway
    459465                        if ( false !== stripos( $content_type, 'multipart' ) && ! empty( $boundary ) ) {
    460466                                $phpmailer->addCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
    461467                        }
     468                } elseif ( is_array( $message ) ) {
     469                        foreach ( $message as $type => $bodies ) {
     470                                foreach ( (array) $bodies as $body ) {
     471                                        if ( 'text/html' === $type ) {
     472                                                $phpmailer->Body = $body;
     473                                        } elseif ( 'text/plain' === $type ) {
     474                                                $phpmailer->AltBody = $body;
     475                                        } else {
     476                                                $phpmailer->addAttachment( $body, '', 'base64', $type );
     477                                        }
     478                                }
     479                        }
     480                }
     481
     482                // Set to use PHP's mail()
     483                $phpmailer->isMail();
     484
     485                // Set custom headers
     486                if ( ! empty( $headers ) ) {
     487                        foreach ( (array) $headers as $name => $content ) {
     488                                $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
     489                        }
    462490                }
    463491
    464492                if ( ! empty( $attachments ) ) {
  • tests/phpunit/tests/mail.php

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