Make WordPress Core


Ignore:
Timestamp:
01/06/2017 05:42:02 AM (7 years ago)
Author:
dd32
Message:

Mail: Upgrade PHPMailer to 5.2.21.

Merges [39645], [36083] to the 4.3 branch.
See #37210.

Location:
branches/4.3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/4.3

  • branches/4.3/src/wp-includes/class-smtp.php

    r33124 r39725  
    2929    /**
    3030     * The PHPMailer SMTP version number.
    31      * @type string
    32      */
    33     const VERSION = '5.2.10';
     31     * @var string
     32     */
     33    const VERSION = '5.2.21';
    3434
    3535    /**
    3636     * SMTP line break constant.
    37      * @type string
     37     * @var string
    3838     */
    3939    const CRLF = "\r\n";
     
    4141    /**
    4242     * The SMTP port to use if one is not specified.
    43      * @type integer
     43     * @var integer
    4444     */
    4545    const DEFAULT_SMTP_PORT = 25;
     
    4747    /**
    4848     * The maximum line length allowed by RFC 2822 section 2.1.1
    49      * @type integer
     49     * @var integer
    5050     */
    5151    const MAX_LINE_LENGTH = 998;
     
    7878    /**
    7979     * The PHPMailer SMTP Version number.
    80      * @type string
     80     * @var string
    8181     * @deprecated Use the `VERSION` constant instead
    8282     * @see SMTP::VERSION
    8383     */
    84     public $Version = '5.2.10';
     84    public $Version = '5.2.21';
    8585
    8686    /**
    8787     * SMTP server port number.
    88      * @type integer
     88     * @var integer
    8989     * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead
    9090     * @see SMTP::DEFAULT_SMTP_PORT
     
    9494    /**
    9595     * SMTP reply line ending.
    96      * @type string
     96     * @var string
    9797     * @deprecated Use the `CRLF` constant instead
    9898     * @see SMTP::CRLF
     
    108108     * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status
    109109     * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages
    110      * @type integer
     110     * @var integer
    111111     */
    112112    public $do_debug = self::DEBUG_OFF;
     
    123123     * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
    124124     * </code>
    125      * @type string|callable
     125     * @var string|callable
    126126     */
    127127    public $Debugoutput = 'echo';
     
    131131     * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
    132132     * @link http://www.postfix.org/VERP_README.html Info on VERP
    133      * @type boolean
     133     * @var boolean
    134134     */
    135135    public $do_verp = false;
     
    140140     * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
    141141     * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
    142      * @type integer
     142     * @var integer
    143143     */
    144144    public $Timeout = 300;
     
    147147     * How long to wait for commands to complete, in seconds.
    148148     * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
    149      * @type integer
     149     * @var integer
    150150     */
    151151    public $Timelimit = 300;
    152152
     153    /**
     154     * @var array patterns to extract smtp transaction id from smtp reply
     155     * Only first capture group will be use, use non-capturing group to deal with it
     156     * Extend this class to override this property to fulfil your needs.
     157     */
     158    protected $smtp_transaction_id_patterns = array(
     159        'exim' => '/[0-9]{3} OK id=(.*)/',
     160        'sendmail' => '/[0-9]{3} 2.0.0 (.*) Message/',
     161        'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/'
     162    );
     163
    153164    /**
    154165     * The socket for the server connection.
    155      * @type resource
     166     * @var resource
    156167     */
    157168    protected $smtp_conn;
     
    159170    /**
    160171     * Error information, if any, for the last SMTP command.
    161      * @type array
     172     * @var array
    162173     */
    163174    protected $error = array(
     
    171182     * The reply the server sent to us for HELO.
    172183     * If null, no HELO string has yet been received.
    173      * @type string|null
     184     * @var string|null
    174185     */
    175186    protected $helo_rply = null;
     
    182193     * Other values can be boolean TRUE or an array containing extension options.
    183194     * If null, no HELO/EHLO string has yet been received.
    184      * @type array|null
     195     * @var array|null
    185196     */
    186197    protected $server_caps = null;
     
    188199    /**
    189200     * The most recent reply received from the server.
    190      * @type string
     201     * @var string
    191202     */
    192203    protected $last_reply = '';
     
    207218        //Avoid clash with built-in function names
    208219        if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
    209             call_user_func($this->Debugoutput, $str, $this->do_debug);
     220            call_user_func($this->Debugoutput, $str, $level);
    210221            return;
    211222        }
     
    273284        if ($streamok) {
    274285            $socket_context = stream_context_create($options);
    275             //Suppress errors; connection failures are handled at a higher level
    276             $this->smtp_conn = @stream_socket_client(
     286            set_error_handler(array($this, 'errorHandler'));
     287            $this->smtp_conn = stream_socket_client(
    277288                $host . ":" . $port,
    278289                $errno,
     
    282293                $socket_context
    283294            );
     295            restore_error_handler();
    284296        } else {
    285297            //Fall back to fsockopen which should work in more places, but is missing some features
     
    288300                self::DEBUG_CONNECTION
    289301            );
     302            set_error_handler(array($this, 'errorHandler'));
    290303            $this->smtp_conn = fsockopen(
    291304                $host,
     
    295308                $timeout
    296309            );
     310            restore_error_handler();
    297311        }
    298312        // Verify we connected properly
     
    337351            return false;
    338352        }
     353
     354        //Allow the best TLS version(s) we can
     355        $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
     356
     357        //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
     358        //so add them back in manually if we can
     359        if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
     360            $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
     361            $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
     362        }
     363
    339364        // Begin encrypted connection
    340365        if (!stream_socket_enable_crypto(
    341366            $this->smtp_conn,
    342367            true,
    343             STREAM_CRYPTO_METHOD_TLS_CLIENT
     368            $crypto_method
    344369        )) {
    345370            return false;
     
    352377     * Must be run after hello().
    353378     * @see hello()
    354      * @param string $username    The user name
    355      * @param string $password    The password
    356      * @param string $authtype    The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)
    357      * @param string $realm       The auth realm for NTLM
     379     * @param string $username The user name
     380     * @param string $password The password
     381     * @param string $authtype The auth type (PLAIN, LOGIN, CRAM-MD5)
     382     * @param string $realm The auth realm for NTLM
    358383     * @param string $workstation The auth workstation for NTLM
    359      * @access public
    360      * @return boolean True if successfully authenticated.
     384     * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth)
     385     * @return bool True if successfully authenticated.* @access public
    361386     */
    362387    public function authenticate(
     
    365390        $authtype = null,
    366391        $realm = '',
    367         $workstation = ''
     392        $workstation = '',
     393        $OAuth = null
    368394    ) {
    369395        if (!$this->server_caps) {
     
    389415
    390416            if (empty($authtype)) {
    391                 foreach (array('LOGIN', 'CRAM-MD5', 'PLAIN') as $method) {
     417                foreach (array('CRAM-MD5', 'LOGIN', 'PLAIN') as $method) {
    392418                    if (in_array($method, $this->server_caps['AUTH'])) {
    393419                        $authtype = $method;
     
    673699    {
    674700        $this->server_caps = array();
    675         $lines = explode("\n", $this->last_reply);
     701        $lines = explode("\n", $this->helo_rply);
     702
    676703        foreach ($lines as $n => $s) {
     704            //First 4 chars contain response code followed by - or space
    677705            $s = trim(substr($s, 4));
    678             if (!$s) {
     706            if (empty($s)) {
    679707                continue;
    680708            }
     
    686714                } else {
    687715                    $name = array_shift($fields);
    688                     if ($name == 'SIZE') {
    689                         $fields = ($fields) ? $fields[0] : 0;
     716                    switch ($name) {
     717                        case 'SIZE':
     718                            $fields = ($fields ? $fields[0] : 0);
     719                            break;
     720                        case 'AUTH':
     721                            if (!is_array($fields)) {
     722                                $fields = array();
     723                            }
     724                            break;
     725                        default:
     726                            $fields = true;
    690727                    }
    691728                }
    692                 $this->server_caps[$name] = ($fields ? $fields : true);
     729                $this->server_caps[$name] = $fields;
    693730            }
    694731        }
     
    740777     * Returns true if the recipient was accepted false if it was rejected.
    741778     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
    742      * @param string $toaddr The address the message is being sent to
    743      * @access public
    744      * @return boolean
    745      */
    746     public function recipient($toaddr)
     779     * @param string $address The address the message is being sent to
     780     * @access public
     781     * @return boolean
     782     */
     783    public function recipient($address)
    747784    {
    748785        return $this->sendCommand(
    749786            'RCPT TO',
    750             'RCPT TO:<' . $toaddr . '>',
     787            'RCPT TO:<' . $address . '>',
    751788            array(250, 251)
    752789        );
     
    767804    /**
    768805     * Send a command to an SMTP server and check its return code.
    769      * @param string $command       The command name - not sent to the server
     806     * @param string $command The command name - not sent to the server
    770807     * @param string $commandstring The actual command to send
    771      * @param integer|array $expect     One or more expected integer success codes
     808     * @param integer|array $expect One or more expected integer success codes
    772809     * @access protected
    773810     * @return boolean True on success.
     
    777814        if (!$this->connected()) {
    778815            $this->setError("Called $command without being connected");
     816            return false;
     817        }
     818        //Reject line breaks in all commands
     819        if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) {
     820            $this->setError("Command '$command' contained line breaks");
    779821            return false;
    780822        }
     
    9821024        while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
    9831025            $str = @fgets($this->smtp_conn, 515);
    984             $this->edebug("SMTP -> get_lines(): \$data was \"$data\"", self::DEBUG_LOWLEVEL);
    985             $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL);
     1026            $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
     1027            $this->edebug("SMTP -> get_lines(): \$str is  \"$str\"", self::DEBUG_LOWLEVEL);
    9861028            $data .= $str;
    987             $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
    9881029            // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen
    9891030            if ((isset($str[3]) and $str[3] == ' ')) {
     
    11001141        return $this->Timeout;
    11011142    }
     1143
     1144    /**
     1145     * Reports an error number and string.
     1146     * @param integer $errno The error number returned by PHP.
     1147     * @param string $errmsg The error message returned by PHP.
     1148     */
     1149    protected function errorHandler($errno, $errmsg)
     1150    {
     1151        $notice = 'Connection: Failed to connect to server.';
     1152        $this->setError(
     1153            $notice,
     1154            $errno,
     1155            $errmsg
     1156        );
     1157        $this->edebug(
     1158            $notice . ' Error number ' . $errno . '. "Error notice: ' . $errmsg,
     1159            self::DEBUG_CONNECTION
     1160        );
     1161    }
     1162
     1163    /**
     1164     * Will return the ID of the last smtp transaction based on a list of patterns provided
     1165     * in SMTP::$smtp_transaction_id_patterns.
     1166     * If no reply has been received yet, it will return null.
     1167     * If no pattern has been matched, it will return false.
     1168     * @return bool|null|string
     1169     */
     1170    public function getLastTransactionID()
     1171    {
     1172        $reply = $this->getLastReply();
     1173
     1174        if (empty($reply)) {
     1175            return null;
     1176        }
     1177
     1178        foreach($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
     1179            if(preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
     1180                return $matches[1];
     1181            }
     1182        }
     1183
     1184        return false;
     1185    }
    11021186}
Note: See TracChangeset for help on using the changeset viewer.