Make WordPress Core


Ignore:
Timestamp:
02/21/2021 09:32:41 AM (3 years ago)
Author:
SergeyBiryukov
Message:

External Libraries: Upgrade PHPMailer to version 6.3.0.

This is a maintenance release. Changes include:

  • Handle early connection errors such as 421 during connection and EHLO states.
  • Make the mail() and sendmail transports set the envelope sender the same way as SMTP does, i.e. use whatever From is set to, only falling back to the sendmail_from php.ini setting if From is unset. This avoids errors from the mail() function if Sender is not set explicitly and php.ini is not configured. This is a minor functionality change, so bumps the minor version number.
  • Extend parseAddresses to decode encoded names.

Release notes: https://github.com/PHPMailer/PHPMailer/releases/tag/v6.3.0

For a full list of changes in this update, see the PHPMailer GitHub:
https://github.com/PHPMailer/PHPMailer/compare/v6.2.0...v6.3.0

Props ayeshrajans.
Fixes #52577.

File:
1 edited

Legend:

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

    r49713 r50397  
    3636     * @var string
    3737     */
    38     const VERSION = '6.2.0';
     38    const VERSION = '6.3.0';
    3939
    4040    /**
     
    313313    public function connect($host, $port = null, $timeout = 30, $options = [])
    314314    {
    315         // Clear errors to avoid confusion
     315        //Clear errors to avoid confusion
    316316        $this->setError('');
    317         // Make sure we are __not__ connected
     317        //Make sure we are __not__ connected
    318318        if ($this->connected()) {
    319             // Already connected, generate error
     319            //Already connected, generate error
    320320            $this->setError('Already connected to a server');
    321321
     
    325325            $port = self::DEFAULT_PORT;
    326326        }
    327         // Connect to the SMTP server
     327        //Connect to the SMTP server
    328328        $this->edebug(
    329329            "Connection: opening to $host:$port, timeout=$timeout, options=" .
     
    341341        $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
    342342
    343         // Get any announcement
     343        //Get any announcement
    344344        $this->last_reply = $this->get_lines();
    345345        $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
    346 
    347         return true;
     346        $responseCode = (int)substr($this->last_reply, 0, 3);
     347        if ($responseCode === 220) {
     348            return true;
     349        }
     350        //Anything other than a 220 response means something went wrong
     351        //RFC 5321 says the server will wait for us to send a QUIT in response to a 554 error
     352        //https://tools.ietf.org/html/rfc5321#section-3.1
     353        if ($responseCode === 554) {
     354            $this->quit();
     355        }
     356        //This will handle 421 responses which may not wait for a QUIT (e.g. if the server is being shut down)
     357        $this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION);
     358        $this->close();
     359        return false;
    348360    }
    349361
     
    398410        }
    399411
    400         // Verify we connected properly
     412        //Verify we connected properly
    401413        if (!is_resource($connection)) {
    402414            $this->setError(
     
    415427        }
    416428
    417         // SMTP server can take longer to respond, give longer timeout for first read
    418         // Windows does not have support for this timeout function
     429        //SMTP server can take longer to respond, give longer timeout for first read
     430        //Windows does not have support for this timeout function
    419431        if (strpos(PHP_OS, 'WIN') !== 0) {
    420432            $max = (int)ini_get('max_execution_time');
    421             // Don't bother if unlimited, or if set_time_limit is disabled
     433            //Don't bother if unlimited, or if set_time_limit is disabled
    422434            if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functions'), 'set_time_limit') === false) {
    423435                @set_time_limit($timeout);
     
    450462        }
    451463
    452         // Begin encrypted connection
     464        //Begin encrypted connection
    453465        set_error_handler([$this, 'errorHandler']);
    454466        $crypto_ok = stream_socket_enable_crypto(
     
    488500
    489501        if (array_key_exists('EHLO', $this->server_caps)) {
    490             // SMTP extensions are available; try to find a proper authentication method
     502            //SMTP extensions are available; try to find a proper authentication method
    491503            if (!array_key_exists('AUTH', $this->server_caps)) {
    492504                $this->setError('Authentication is not allowed at this stage');
    493                 // 'at this stage' means that auth may be allowed after the stage changes
    494                 // e.g. after STARTTLS
     505                //'at this stage' means that auth may be allowed after the stage changes
     506                //e.g. after STARTTLS
    495507
    496508                return false;
     
    536548        switch ($authtype) {
    537549            case 'PLAIN':
    538                 // Start authentication
     550                //Start authentication
    539551                if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
    540552                    return false;
    541553                }
    542                 // Send encoded username and password
     554                //Send encoded username and password
    543555                if (
    544556                    !$this->sendCommand(
     
    552564                break;
    553565            case 'LOGIN':
    554                 // Start authentication
     566                //Start authentication
    555567                if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
    556568                    return false;
     
    564576                break;
    565577            case 'CRAM-MD5':
    566                 // Start authentication
     578                //Start authentication
    567579                if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
    568580                    return false;
    569581                }
    570                 // Get the challenge
     582                //Get the challenge
    571583                $challenge = base64_decode(substr($this->last_reply, 4));
    572584
    573                 // Build the response
     585                //Build the response
    574586                $response = $username . ' ' . $this->hmac($challenge, $password);
    575587
    576                 // send encoded credentials
     588                //send encoded credentials
    577589                return $this->sendCommand('Username', base64_encode($response), 235);
    578590            case 'XOAUTH2':
     
    583595                $oauth = $OAuth->getOauth64();
    584596
    585                 // Start authentication
     597                //Start authentication
    586598                if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
    587599                    return false;
     
    613625        }
    614626
    615         // The following borrowed from
    616         // http://php.net/manual/en/function.mhash.php#27225
    617 
    618         // RFC 2104 HMAC implementation for php.
    619         // Creates an md5 HMAC.
    620         // Eliminates the need to install mhash to compute a HMAC
    621         // by Lance Rushing
    622 
    623         $bytelen = 64; // byte length for md5
     627        //The following borrowed from
     628        //http://php.net/manual/en/function.mhash.php#27225
     629
     630        //RFC 2104 HMAC implementation for php.
     631        //Creates an md5 HMAC.
     632        //Eliminates the need to install mhash to compute a HMAC
     633        //by Lance Rushing
     634
     635        $bytelen = 64; //byte length for md5
    624636        if (strlen($key) > $bytelen) {
    625637            $key = pack('H*', md5($key));
     
    644656            $sock_status = stream_get_meta_data($this->smtp_conn);
    645657            if ($sock_status['eof']) {
    646                 // The socket is valid but we are not connected
     658                //The socket is valid but we are not connected
    647659                $this->edebug(
    648660                    'SMTP NOTICE: EOF caught while checking if connected',
     
    654666            }
    655667
    656             return true; // everything looks good
     668            return true; //everything looks good
    657669        }
    658670
     
    672684        $this->helo_rply = null;
    673685        if (is_resource($this->smtp_conn)) {
    674             // close the connection and cleanup
     686            //Close the connection and cleanup
    675687            fclose($this->smtp_conn);
    676688            $this->smtp_conn = null; //Makes for cleaner serialization
     
    707719         */
    708720
    709         // Normalize line breaks before exploding
     721        //Normalize line breaks before exploding
    710722        $lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
    711723
     
    753765            //Send the lines to the server
    754766            foreach ($lines_out as $line_out) {
    755                 //RFC2821 section 4.5.2
     767                //Dot-stuffing as per RFC5321 section 4.5.2
     768                //https://tools.ietf.org/html/rfc5321#section-4.5.2
    756769                if (!empty($line_out) && $line_out[0] === '.') {
    757770                    $line_out = '.' . $line_out;
     
    787800    {
    788801        //Try extended hello first (RFC 2821)
    789         return $this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host);
     802        if ($this->sendHello('EHLO', $host)) {
     803            return true;
     804        }
     805
     806        //Some servers shut down the SMTP service here (RFC 5321)
     807        if (substr($this->helo_rply, 0, 3) == '421') {
     808            return false;
     809        }
     810
     811        return $this->sendHello('HELO', $host);
    790812    }
    791813
     
    977999
    9781000        $this->last_reply = $this->get_lines();
    979         // Fetch SMTP code and possible error code explanation
     1001        //Fetch SMTP code and possible error code explanation
    9801002        $matches = [];
    9811003        if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) {
    9821004            $code = (int) $matches[1];
    9831005            $code_ex = (count($matches) > 2 ? $matches[2] : null);
    984             // Cut off error code from each response line
     1006            //Cut off error code from each response line
    9851007            $detail = preg_replace(
    9861008                "/{$code}[ -]" .
     
    9901012            );
    9911013        } else {
    992             // Fall back to simple parsing if regex fails
     1014            //Fall back to simple parsing if regex fails
    9931015            $code = (int) substr($this->last_reply, 0, 3);
    9941016            $code_ex = null;
     
    11851207    protected function get_lines()
    11861208    {
    1187         // If the connection is bad, give up straight away
     1209        //If the connection is bad, give up straight away
    11881210        if (!is_resource($this->smtp_conn)) {
    11891211            return '';
     
    12381260            $this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);
    12391261            $data .= $str;
    1240             // If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
    1241             // or 4th character is a space or a line break char, we are done reading, break the loop.
    1242             // String array access is a significant micro-optimisation over strlen
     1262            //If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
     1263            //or 4th character is a space or a line break char, we are done reading, break the loop.
     1264            //String array access is a significant micro-optimisation over strlen
    12431265            if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") {
    12441266                break;
    12451267            }
    1246             // Timed-out? Log and break
     1268            //Timed-out? Log and break
    12471269            $info = stream_get_meta_data($this->smtp_conn);
    12481270            if ($info['timed_out']) {
     
    12531275                break;
    12541276            }
    1255             // Now check if reads took too long
     1277            //Now check if reads took too long
    12561278            if ($endtime && time() > $endtime) {
    12571279                $this->edebug(
Note: See TracChangeset for help on using the changeset viewer.