From 45197f9d4ee9e21e874a35d9edc695a2373955b8 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers Date: Tue, 22 Sep 2020 18:35:10 +0000 Subject: [PATCH] External Libraries: Upgrade PHPMailer to version 6.1.7. For a full list of changes in this update, see the PHPMailer GitHub: https://github.com/PHPMailer/PHPMailer/compare/v6.1.6...v6.1.7. Props ayeshrajans, jrf. Fixes #51311. git-svn-id: https://develop.svn.wordpress.org/trunk@49034 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/PHPMailer/PHPMailer.php | 13 ++-- src/wp-includes/PHPMailer/SMTP.php | 91 ++++++++++++++++++++----- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/src/wp-includes/PHPMailer/PHPMailer.php b/src/wp-includes/PHPMailer/PHPMailer.php index 27af1a937b..a1fe3dec24 100644 --- a/src/wp-includes/PHPMailer/PHPMailer.php +++ b/src/wp-includes/PHPMailer/PHPMailer.php @@ -441,6 +441,8 @@ class PHPMailer * Only supported in `mail` and `sendmail` transports, not in SMTP. * * @var bool + * + * @deprecated 6.0.0 PHPMailer isn't a mailing list manager! */ public $SingleTo = false; @@ -745,7 +747,7 @@ class PHPMailer * * @var string */ - const VERSION = '6.1.6'; + const VERSION = '6.1.7'; /** * Error severity: message only, continue processing. @@ -1307,7 +1309,7 @@ class PHPMailer $patternselect = static::$validator; } if (is_callable($patternselect)) { - return $patternselect($address); + return call_user_func($patternselect, $address); } //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 if (strpos($address, "\n") !== false || strpos($address, "\r") !== false) { @@ -1401,7 +1403,6 @@ class PHPMailer //Ignore IDE complaints about this line - method signature changed in PHP 5.4 $errorcode = 0; if (defined('INTL_IDNA_VARIANT_UTS46')) { - // phpcs:ignore PHPCompatibility.ParameterValues.NewIDNVariantDefault.NotSet $punycode = idn_to_ascii($domain, $errorcode, INTL_IDNA_VARIANT_UTS46); } elseif (defined('INTL_IDNA_VARIANT_2003')) { // phpcs:ignore PHPCompatibility.Constants.RemovedConstants.intl_idna_variant_2003Deprecated @@ -2978,7 +2979,6 @@ class PHPMailer if ('' === $name) { $name = $filename; } - if (!$this->validateEncoding($encoding)) { throw new Exception($this->lang('encoding') . $encoding); } @@ -3993,7 +3993,8 @@ class PHPMailer * @param string $message HTML message string * @param string $basedir Absolute path to a base directory to prepend to relative paths to images * @param bool|callable $advanced Whether to use the internal HTML to text converter - * or your own custom converter @return string $message The transformed message Body + * or your own custom converter + * @return string The transformed message body * * @throws Exception * @@ -4117,7 +4118,7 @@ class PHPMailer public function html2text($html, $advanced = false) { if (is_callable($advanced)) { - return $advanced($html); + return call_user_func($advanced, $html); } return html_entity_decode( diff --git a/src/wp-includes/PHPMailer/SMTP.php b/src/wp-includes/PHPMailer/SMTP.php index aa5555149a..6b0b73ddd9 100644 --- a/src/wp-includes/PHPMailer/SMTP.php +++ b/src/wp-includes/PHPMailer/SMTP.php @@ -34,7 +34,7 @@ class SMTP * * @var string */ - const VERSION = '6.1.6'; + const VERSION = '6.1.7'; /** * SMTP line break constant. @@ -311,12 +311,6 @@ class SMTP */ public function connect($host, $port = null, $timeout = 30, $options = []) { - static $streamok; - //This is enabled by default since 5.0.0 but some providers disable it - //Check this once and cache the result - if (null === $streamok) { - $streamok = function_exists('stream_socket_client'); - } // Clear errors to avoid confusion $this->setError(''); // Make sure we are __not__ connected @@ -335,12 +329,48 @@ class SMTP (count($options) > 0 ? var_export($options, true) : 'array()'), self::DEBUG_CONNECTION ); + + $this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $options); + + if ($this->smtp_conn === false) { + //Error info already set inside `getSMTPConnection()` + return false; + } + + $this->edebug('Connection: opened', self::DEBUG_CONNECTION); + + // Get any announcement + $this->last_reply = $this->get_lines(); + $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); + + return true; + } + + /** + * Create connection to the SMTP server. + * + * @param string $host SMTP server IP or host name + * @param int $port The port number to connect to + * @param int $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() + * + * @return false|resource + */ + protected function getSMTPConnection($host, $port = null, $timeout = 30, $options = []) + { + static $streamok; + //This is enabled by default since 5.0.0 but some providers disable it + //Check this once and cache the result + if (null === $streamok) { + $streamok = function_exists('stream_socket_client'); + } + $errno = 0; $errstr = ''; if ($streamok) { $socket_context = stream_context_create($options); set_error_handler([$this, 'errorHandler']); - $this->smtp_conn = stream_socket_client( + $connection = stream_socket_client( $host . ':' . $port, $errno, $errstr, @@ -356,7 +386,7 @@ class SMTP self::DEBUG_CONNECTION ); set_error_handler([$this, 'errorHandler']); - $this->smtp_conn = fsockopen( + $connection = fsockopen( $host, $port, $errno, @@ -365,8 +395,9 @@ class SMTP ); restore_error_handler(); } + // Verify we connected properly - if (!is_resource($this->smtp_conn)) { + if (!is_resource($connection)) { $this->setError( 'Failed to connect to server', '', @@ -381,22 +412,19 @@ class SMTP return false; } - $this->edebug('Connection: opened', self::DEBUG_CONNECTION); + // SMTP server can take longer to respond, give longer timeout for first read // Windows does not have support for this timeout function if (strpos(PHP_OS, 'WIN') !== 0) { - $max = (int) ini_get('max_execution_time'); + $max = (int)ini_get('max_execution_time'); // Don't bother if unlimited if (0 !== $max && $timeout > $max) { @set_time_limit($timeout); } - stream_set_timeout($this->smtp_conn, $timeout, 0); + stream_set_timeout($connection, $timeout, 0); } - // Get any announcement - $announce = $this->get_lines(); - $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER); - return true; + return $connection; } /** @@ -1166,13 +1194,40 @@ class SMTP $selW = null; while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { //Must pass vars in here as params are by reference - if (!stream_select($selR, $selW, $selW, $this->Timelimit)) { + //solution for signals inspired by https://github.com/symfony/symfony/pull/6540 + set_error_handler([$this, 'errorHandler']); + $n = stream_select($selR, $selW, $selW, $this->Timelimit); + restore_error_handler(); + + if ($n === false) { + $message = $this->getError()['detail']; + + $this->edebug( + 'SMTP -> get_lines(): select failed (' . $message . ')', + self::DEBUG_LOWLEVEL + ); + + //stream_select returns false when the `select` system call is interrupted by an incoming signal, try the select again + if (stripos($message, 'interrupted system call') !== false) { + $this->edebug( + 'SMTP -> get_lines(): retrying stream_select', + self::DEBUG_LOWLEVEL + ); + $this->setError(''); + continue; + } + + break; + } + + if (!$n) { $this->edebug( 'SMTP -> get_lines(): select timed-out in (' . $this->Timelimit . ' sec)', self::DEBUG_LOWLEVEL ); break; } + //Deliberate noise suppression - errors are handled afterwards $str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH); $this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);