"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/SMTP.php" between
PHPMailer-6.2.0.tar.gz and PHPMailer-6.3.0.tar.gz

About: PHPMailer is a PHP email transport class that features multiple file attachments, CCs, BCCs, REPLY-TOs, HTML messages, redundant SMTP servers, and word wrap, among others.

SMTP.php  (PHPMailer-6.2.0):SMTP.php  (PHPMailer-6.3.0)
skipping to change at line 38 skipping to change at line 38
* @author Chris Ryan * @author Chris Ryan
* @author Marcus Bointon <phpmailer@synchromedia.co.uk> * @author Marcus Bointon <phpmailer@synchromedia.co.uk>
*/ */
class SMTP class SMTP
{ {
/** /**
* The PHPMailer SMTP version number. * The PHPMailer SMTP version number.
* *
* @var string * @var string
*/ */
const VERSION = '6.2.0'; const VERSION = '6.3.0';
/** /**
* SMTP line break constant. * SMTP line break constant.
* *
* @var string * @var string
*/ */
const LE = "\r\n"; const LE = "\r\n";
/** /**
* The SMTP port to use if one is not specified. * The SMTP port to use if one is not specified.
skipping to change at line 315 skipping to change at line 315
* *
* @param string $host SMTP server IP or host name * @param string $host SMTP server IP or host name
* @param int $port The port number to connect to * @param int $port The port number to connect to
* @param int $timeout How long to wait for the connection to open * @param int $timeout How long to wait for the connection to open
* @param array $options An array of options for stream_context_create() * @param array $options An array of options for stream_context_create()
* *
* @return bool * @return bool
*/ */
public function connect($host, $port = null, $timeout = 30, $options = []) public function connect($host, $port = null, $timeout = 30, $options = [])
{ {
// Clear errors to avoid confusion //Clear errors to avoid confusion
$this->setError(''); $this->setError('');
// Make sure we are __not__ connected //Make sure we are __not__ connected
if ($this->connected()) { if ($this->connected()) {
// Already connected, generate error //Already connected, generate error
$this->setError('Already connected to a server'); $this->setError('Already connected to a server');
return false; return false;
} }
if (empty($port)) { if (empty($port)) {
$port = self::DEFAULT_PORT; $port = self::DEFAULT_PORT;
} }
// Connect to the SMTP server //Connect to the SMTP server
$this->edebug( $this->edebug(
"Connection: opening to $host:$port, timeout=$timeout, options=" . "Connection: opening to $host:$port, timeout=$timeout, options=" .
(count($options) > 0 ? var_export($options, true) : 'array()'), (count($options) > 0 ? var_export($options, true) : 'array()'),
self::DEBUG_CONNECTION self::DEBUG_CONNECTION
); );
$this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $opt ions); $this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $opt ions);
if ($this->smtp_conn === false) { if ($this->smtp_conn === false) {
//Error info already set inside `getSMTPConnection()` //Error info already set inside `getSMTPConnection()`
return false; return false;
} }
$this->edebug('Connection: opened', self::DEBUG_CONNECTION); $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
// Get any announcement //Get any announcement
$this->last_reply = $this->get_lines(); $this->last_reply = $this->get_lines();
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERV ER); $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERV ER);
$responseCode = (int)substr($this->last_reply, 0, 3);
return true; if ($responseCode === 220) {
return true;
}
//Anything other than a 220 response means something went wrong
//RFC 5321 says the server will wait for us to send a QUIT in response t
o a 554 error
//https://tools.ietf.org/html/rfc5321#section-3.1
if ($responseCode === 554) {
$this->quit();
}
//This will handle 421 responses which may not wait for a QUIT (e.g. if
the server is being shut down)
$this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION
);
$this->close();
return false;
} }
/** /**
* Create connection to the SMTP server. * Create connection to the SMTP server.
* *
* @param string $host SMTP server IP or host name * @param string $host SMTP server IP or host name
* @param int $port The port number to connect to * @param int $port The port number to connect to
* @param int $timeout How long to wait for the connection to open * @param int $timeout How long to wait for the connection to open
* @param array $options An array of options for stream_context_create() * @param array $options An array of options for stream_context_create()
* *
skipping to change at line 400 skipping to change at line 412
$connection = fsockopen( $connection = fsockopen(
$host, $host,
$port, $port,
$errno, $errno,
$errstr, $errstr,
$timeout $timeout
); );
restore_error_handler(); restore_error_handler();
} }
// Verify we connected properly //Verify we connected properly
if (!is_resource($connection)) { if (!is_resource($connection)) {
$this->setError( $this->setError(
'Failed to connect to server', 'Failed to connect to server',
'', '',
(string) $errno, (string) $errno,
$errstr $errstr
); );
$this->edebug( $this->edebug(
'SMTP ERROR: ' . $this->error['error'] 'SMTP ERROR: ' . $this->error['error']
. ": $errstr ($errno)", . ": $errstr ($errno)",
self::DEBUG_CLIENT self::DEBUG_CLIENT
); );
return false; return false;
} }
// SMTP server can take longer to respond, give longer timeout for first //SMTP server can take longer to respond, give longer timeout for first
read read
// Windows does not have support for this timeout function //Windows does not have support for this timeout function
if (strpos(PHP_OS, 'WIN') !== 0) { 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, or if set_time_limit is disabled //Don't bother if unlimited, or if set_time_limit is disabled
if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functio ns'), 'set_time_limit') === false) { if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functio ns'), 'set_time_limit') === false) {
@set_time_limit($timeout); @set_time_limit($timeout);
} }
stream_set_timeout($connection, $timeout, 0); stream_set_timeout($connection, $timeout, 0);
} }
return $connection; return $connection;
} }
/** /**
skipping to change at line 452 skipping to change at line 464
//Allow the best TLS version(s) we can //Allow the best TLS version(s) we can
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT; $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
//PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD _TLS_CLIENT //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD _TLS_CLIENT
//so add them back in manually if we can //so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
} }
// Begin encrypted connection //Begin encrypted connection
set_error_handler([$this, 'errorHandler']); set_error_handler([$this, 'errorHandler']);
$crypto_ok = stream_socket_enable_crypto( $crypto_ok = stream_socket_enable_crypto(
$this->smtp_conn, $this->smtp_conn,
true, true,
$crypto_method $crypto_method
); );
restore_error_handler(); restore_error_handler();
return (bool) $crypto_ok; return (bool) $crypto_ok;
} }
skipping to change at line 490 skipping to change at line 502
$authtype = null, $authtype = null,
$OAuth = null $OAuth = null
) { ) {
if (!$this->server_caps) { if (!$this->server_caps) {
$this->setError('Authentication is not allowed before HELO/EHLO'); $this->setError('Authentication is not allowed before HELO/EHLO');
return false; return false;
} }
if (array_key_exists('EHLO', $this->server_caps)) { if (array_key_exists('EHLO', $this->server_caps)) {
// SMTP extensions are available; try to find a proper authenticatio n method //SMTP extensions are available; try to find a proper authentication method
if (!array_key_exists('AUTH', $this->server_caps)) { if (!array_key_exists('AUTH', $this->server_caps)) {
$this->setError('Authentication is not allowed at this stage'); $this->setError('Authentication is not allowed at this stage');
// 'at this stage' means that auth may be allowed after the stag //'at this stage' means that auth may be allowed after the stage
e changes changes
// e.g. after STARTTLS //e.g. after STARTTLS
return false; return false;
} }
$this->edebug('Auth method requested: ' . ($authtype ?: 'UNSPECIFIED '), self::DEBUG_LOWLEVEL); $this->edebug('Auth method requested: ' . ($authtype ?: 'UNSPECIFIED '), self::DEBUG_LOWLEVEL);
$this->edebug( $this->edebug(
'Auth methods available on the server: ' . implode(',', $this->s erver_caps['AUTH']), 'Auth methods available on the server: ' . implode(',', $this->s erver_caps['AUTH']),
self::DEBUG_LOWLEVEL self::DEBUG_LOWLEVEL
); );
skipping to change at line 538 skipping to change at line 550
if (!in_array($authtype, $this->server_caps['AUTH'], true)) { if (!in_array($authtype, $this->server_caps['AUTH'], true)) {
$this->setError("The requested authentication method \"$authtype \" is not supported by the server"); $this->setError("The requested authentication method \"$authtype \" is not supported by the server");
return false; return false;
} }
} elseif (empty($authtype)) { } elseif (empty($authtype)) {
$authtype = 'LOGIN'; $authtype = 'LOGIN';
} }
switch ($authtype) { switch ($authtype) {
case 'PLAIN': case 'PLAIN':
// Start authentication //Start authentication
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) { if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
return false; return false;
} }
// Send encoded username and password //Send encoded username and password
if ( if (
!$this->sendCommand( !$this->sendCommand(
'User & Password', 'User & Password',
base64_encode("\0" . $username . "\0" . $password), base64_encode("\0" . $username . "\0" . $password),
235 235
) )
) { ) {
return false; return false;
} }
break; break;
case 'LOGIN': case 'LOGIN':
// Start authentication //Start authentication
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
return false; return false;
} }
if (!$this->sendCommand('Username', base64_encode($username), 33 4)) { if (!$this->sendCommand('Username', base64_encode($username), 33 4)) {
return false; return false;
} }
if (!$this->sendCommand('Password', base64_encode($password), 23 5)) { if (!$this->sendCommand('Password', base64_encode($password), 23 5)) {
return false; return false;
} }
break; break;
case 'CRAM-MD5': case 'CRAM-MD5':
// Start authentication //Start authentication
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
return false; return false;
} }
// Get the challenge //Get the challenge
$challenge = base64_decode(substr($this->last_reply, 4)); $challenge = base64_decode(substr($this->last_reply, 4));
// Build the response //Build the response
$response = $username . ' ' . $this->hmac($challenge, $password) ; $response = $username . ' ' . $this->hmac($challenge, $password) ;
// send encoded credentials //send encoded credentials
return $this->sendCommand('Username', base64_encode($response), 235); return $this->sendCommand('Username', base64_encode($response), 235);
case 'XOAUTH2': case 'XOAUTH2':
//The OAuth instance must be set up prior to requesting auth. //The OAuth instance must be set up prior to requesting auth.
if (null === $OAuth) { if (null === $OAuth) {
return false; return false;
} }
$oauth = $OAuth->getOauth64(); $oauth = $OAuth->getOauth64();
// Start authentication //Start authentication
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) { if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
return false; return false;
} }
break; break;
default: default:
$this->setError("Authentication method \"$authtype\" is not supp orted"); $this->setError("Authentication method \"$authtype\" is not supp orted");
return false; return false;
} }
skipping to change at line 615 skipping to change at line 627
* @param string $key The key to hash with * @param string $key The key to hash with
* *
* @return string * @return string
*/ */
protected function hmac($data, $key) protected function hmac($data, $key)
{ {
if (function_exists('hash_hmac')) { if (function_exists('hash_hmac')) {
return hash_hmac('md5', $data, $key); return hash_hmac('md5', $data, $key);
} }
// The following borrowed from //The following borrowed from
// http://php.net/manual/en/function.mhash.php#27225 //http://php.net/manual/en/function.mhash.php#27225
// RFC 2104 HMAC implementation for php. //RFC 2104 HMAC implementation for php.
// Creates an md5 HMAC. //Creates an md5 HMAC.
// Eliminates the need to install mhash to compute a HMAC //Eliminates the need to install mhash to compute a HMAC
// by Lance Rushing //by Lance Rushing
$bytelen = 64; // byte length for md5 $bytelen = 64; //byte length for md5
if (strlen($key) > $bytelen) { if (strlen($key) > $bytelen) {
$key = pack('H*', md5($key)); $key = pack('H*', md5($key));
} }
$key = str_pad($key, $bytelen, chr(0x00)); $key = str_pad($key, $bytelen, chr(0x00));
$ipad = str_pad('', $bytelen, chr(0x36)); $ipad = str_pad('', $bytelen, chr(0x36));
$opad = str_pad('', $bytelen, chr(0x5c)); $opad = str_pad('', $bytelen, chr(0x5c));
$k_ipad = $key ^ $ipad; $k_ipad = $key ^ $ipad;
$k_opad = $key ^ $opad; $k_opad = $key ^ $opad;
return md5($k_opad . pack('H*', md5($k_ipad . $data))); return md5($k_opad . pack('H*', md5($k_ipad . $data)));
skipping to change at line 646 skipping to change at line 658
/** /**
* Check connection state. * Check connection state.
* *
* @return bool True if connected * @return bool True if connected
*/ */
public function connected() public function connected()
{ {
if (is_resource($this->smtp_conn)) { if (is_resource($this->smtp_conn)) {
$sock_status = stream_get_meta_data($this->smtp_conn); $sock_status = stream_get_meta_data($this->smtp_conn);
if ($sock_status['eof']) { if ($sock_status['eof']) {
// The socket is valid but we are not connected //The socket is valid but we are not connected
$this->edebug( $this->edebug(
'SMTP NOTICE: EOF caught while checking if connected', 'SMTP NOTICE: EOF caught while checking if connected',
self::DEBUG_CLIENT self::DEBUG_CLIENT
); );
$this->close(); $this->close();
return false; return false;
} }
return true; // everything looks good return true; //everything looks good
} }
return false; return false;
} }
/** /**
* Close the socket and clean up the state of the class. * Close the socket and clean up the state of the class.
* Don't use this function without first trying to use QUIT. * Don't use this function without first trying to use QUIT.
* *
* @see quit() * @see quit()
*/ */
public function close() public function close()
{ {
$this->setError(''); $this->setError('');
$this->server_caps = null; $this->server_caps = null;
$this->helo_rply = null; $this->helo_rply = null;
if (is_resource($this->smtp_conn)) { if (is_resource($this->smtp_conn)) {
// close the connection and cleanup //Close the connection and cleanup
fclose($this->smtp_conn); fclose($this->smtp_conn);
$this->smtp_conn = null; //Makes for cleaner serialization $this->smtp_conn = null; //Makes for cleaner serialization
$this->edebug('Connection: closed', self::DEBUG_CONNECTION); $this->edebug('Connection: closed', self::DEBUG_CONNECTION);
} }
} }
/** /**
* Send an SMTP DATA command. * Send an SMTP DATA command.
* Issues a data command and sends the msg_data to the server, * Issues a data command and sends the msg_data to the server,
* finializing the mail transaction. $msg_data is the message * finializing the mail transaction. $msg_data is the message
skipping to change at line 709 skipping to change at line 721
} }
/* The server is ready to accept data! /* The server is ready to accept data!
* According to rfc821 we should not send more than 1000 characters on a single line (including the LE) * According to rfc821 we should not send more than 1000 characters on a single line (including the LE)
* so we will break the data up into lines by \r and/or \n then if neede d we will break each of those into * so we will break the data up into lines by \r and/or \n then if neede d we will break each of those into
* smaller lines to fit within the limit. * smaller lines to fit within the limit.
* We will also look for lines that start with a '.' and prepend an addi tional '.'. * We will also look for lines that start with a '.' and prepend an addi tional '.'.
* NOTE: this does not count towards line-length limit. * NOTE: this does not count towards line-length limit.
*/ */
// Normalize line breaks before exploding //Normalize line breaks before exploding
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data)); $lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
* of the first line (':' separated) does not contain a space then it _s hould_ be a header and we will * of the first line (':' separated) does not contain a space then it _s hould_ be a header and we will
* process all lines before a blank line as headers. * process all lines before a blank line as headers.
*/ */
$field = substr($lines[0], 0, strpos($lines[0], ':')); $field = substr($lines[0], 0, strpos($lines[0], ':'));
$in_headers = false; $in_headers = false;
if (!empty($field) && strpos($field, ' ') === false) { if (!empty($field) && strpos($field, ' ') === false) {
skipping to change at line 755 skipping to change at line 767
} }
//If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1 //If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
if ($in_headers) { if ($in_headers) {
$line = "\t" . $line; $line = "\t" . $line;
} }
} }
$lines_out[] = $line; $lines_out[] = $line;
//Send the lines to the server //Send the lines to the server
foreach ($lines_out as $line_out) { foreach ($lines_out as $line_out) {
//RFC2821 section 4.5.2 //Dot-stuffing as per RFC5321 section 4.5.2
//https://tools.ietf.org/html/rfc5321#section-4.5.2
if (!empty($line_out) && $line_out[0] === '.') { if (!empty($line_out) && $line_out[0] === '.') {
$line_out = '.' . $line_out; $line_out = '.' . $line_out;
} }
$this->client_send($line_out . static::LE, 'DATA'); $this->client_send($line_out . static::LE, 'DATA');
} }
} }
//Message data has been sent, complete the command //Message data has been sent, complete the command
//Increase timelimit for end of DATA command //Increase timelimit for end of DATA command
$savetimelimit = $this->Timelimit; $savetimelimit = $this->Timelimit;
skipping to change at line 789 skipping to change at line 802
* Implements RFC 821: HELO <SP> <domain> <CRLF> * Implements RFC 821: HELO <SP> <domain> <CRLF>
* and RFC 2821 EHLO. * and RFC 2821 EHLO.
* *
* @param string $host The host name or IP to connect to * @param string $host The host name or IP to connect to
* *
* @return bool * @return bool
*/ */
public function hello($host = '') public function hello($host = '')
{ {
//Try extended hello first (RFC 2821) //Try extended hello first (RFC 2821)
return $this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host if ($this->sendHello('EHLO', $host)) {
); return true;
}
//Some servers shut down the SMTP service here (RFC 5321)
if (substr($this->helo_rply, 0, 3) == '421') {
return false;
}
return $this->sendHello('HELO', $host);
} }
/** /**
* Send an SMTP HELO or EHLO command. * Send an SMTP HELO or EHLO command.
* Low-level implementation used by hello(). * Low-level implementation used by hello().
* *
* @param string $hello The HELO string * @param string $hello The HELO string
* @param string $host The hostname to say we are * @param string $host The hostname to say we are
* *
* @return bool * @return bool
skipping to change at line 979 skipping to change at line 1001
} }
//Reject line breaks in all commands //Reject line breaks in all commands
if ((strpos($commandstring, "\n") !== false) || (strpos($commandstring, "\r") !== false)) { if ((strpos($commandstring, "\n") !== false) || (strpos($commandstring, "\r") !== false)) {
$this->setError("Command '$command' contained line breaks"); $this->setError("Command '$command' contained line breaks");
return false; return false;
} }
$this->client_send($commandstring . static::LE, $command); $this->client_send($commandstring . static::LE, $command);
$this->last_reply = $this->get_lines(); $this->last_reply = $this->get_lines();
// Fetch SMTP code and possible error code explanation //Fetch SMTP code and possible error code explanation
$matches = []; $matches = [];
if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this- >last_reply, $matches)) { if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this- >last_reply, $matches)) {
$code = (int) $matches[1]; $code = (int) $matches[1];
$code_ex = (count($matches) > 2 ? $matches[2] : null); $code_ex = (count($matches) > 2 ? $matches[2] : null);
// Cut off error code from each response line //Cut off error code from each response line
$detail = preg_replace( $detail = preg_replace(
"/{$code}[ -]" . "/{$code}[ -]" .
($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m' , ($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m' ,
'', '',
$this->last_reply $this->last_reply
); );
} else { } else {
// Fall back to simple parsing if regex fails //Fall back to simple parsing if regex fails
$code = (int) substr($this->last_reply, 0, 3); $code = (int) substr($this->last_reply, 0, 3);
$code_ex = null; $code_ex = null;
$detail = substr($this->last_reply, 4); $detail = substr($this->last_reply, 4);
} }
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERV ER); $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERV ER);
if (!in_array($code, (array) $expect, true)) { if (!in_array($code, (array) $expect, true)) {
$this->setError( $this->setError(
"$command command failed", "$command command failed",
skipping to change at line 1187 skipping to change at line 1209
* Read the SMTP server's response. * Read the SMTP server's response.
* Either before eof or socket timeout occurs on the operation. * Either before eof or socket timeout occurs on the operation.
* With SMTP we can tell if we have more lines to read if the * With SMTP we can tell if we have more lines to read if the
* 4th character is '-' symbol. If it is a space then we don't * 4th character is '-' symbol. If it is a space then we don't
* need to read anything else. * need to read anything else.
* *
* @return string * @return string
*/ */
protected function get_lines() protected function get_lines()
{ {
// If the connection is bad, give up straight away //If the connection is bad, give up straight away
if (!is_resource($this->smtp_conn)) { if (!is_resource($this->smtp_conn)) {
return ''; return '';
} }
$data = ''; $data = '';
$endtime = 0; $endtime = 0;
stream_set_timeout($this->smtp_conn, $this->Timeout); stream_set_timeout($this->smtp_conn, $this->Timeout);
if ($this->Timelimit > 0) { if ($this->Timelimit > 0) {
$endtime = time() + $this->Timelimit; $endtime = time() + $this->Timelimit;
} }
$selR = [$this->smtp_conn]; $selR = [$this->smtp_conn];
skipping to change at line 1240 skipping to change at line 1262
'SMTP -> get_lines(): select timed-out in (' . $this->Timeli mit . ' sec)', 'SMTP -> get_lines(): select timed-out in (' . $this->Timeli mit . ' sec)',
self::DEBUG_LOWLEVEL self::DEBUG_LOWLEVEL
); );
break; break;
} }
//Deliberate noise suppression - errors are handled afterwards //Deliberate noise suppression - errors are handled afterwards
$str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH); $str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH);
$this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWL EVEL); $this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWL EVEL);
$data .= $str; $data .= $str;
// If response is only 3 chars (not valid, but RFC5321 S4.2 says it //If response is only 3 chars (not valid, but RFC5321 S4.2 says it m
must be handled), ust be handled),
// or 4th character is a space or a line break char, we are done rea //or 4th character is a space or a line break char, we are done read
ding, break the loop. ing, break the loop.
// String array access is a significant micro-optimisation over strl //String array access is a significant micro-optimisation over strle
en n
if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3 ] === "\n") { if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3 ] === "\n") {
break; break;
} }
// Timed-out? Log and break //Timed-out? Log and break
$info = stream_get_meta_data($this->smtp_conn); $info = stream_get_meta_data($this->smtp_conn);
if ($info['timed_out']) { if ($info['timed_out']) {
$this->edebug( $this->edebug(
'SMTP -> get_lines(): stream timed-out (' . $this->Timeout . ' sec)', 'SMTP -> get_lines(): stream timed-out (' . $this->Timeout . ' sec)',
self::DEBUG_LOWLEVEL self::DEBUG_LOWLEVEL
); );
break; break;
} }
// Now check if reads took too long //Now check if reads took too long
if ($endtime && time() > $endtime) { if ($endtime && time() > $endtime) {
$this->edebug( $this->edebug(
'SMTP -> get_lines(): timelimit reached (' . 'SMTP -> get_lines(): timelimit reached (' .
$this->Timelimit . ' sec)', $this->Timelimit . ' sec)',
self::DEBUG_LOWLEVEL self::DEBUG_LOWLEVEL
); );
break; break;
} }
} }
 End of changes. 37 change blocks. 
52 lines changed or deleted 76 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)