diff options
Diffstat (limited to 'program/lib/Net')
-rw-r--r-- | program/lib/Net/SMTP.php | 144 |
1 files changed, 96 insertions, 48 deletions
diff --git a/program/lib/Net/SMTP.php b/program/lib/Net/SMTP.php index 6e1bb0330..550383eef 100644 --- a/program/lib/Net/SMTP.php +++ b/program/lib/Net/SMTP.php @@ -65,6 +65,26 @@ class Net_SMTP var $auth_methods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN'); /** + * Use SMTP command pipelining (specified in RFC 2920) if the SMTP + * server supports it. + * + * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(), + * somlFrom() and samlFrom() do not wait for a response from the + * SMTP server but return immediately. + * + * @var bool + * @access public + */ + var $pipelining = false; + + /** + * Number of pipelined commands. + * @var int + * @access private + */ + var $_pipelined_commands = 0; + + /** * Should debugging output be enabled? * @var boolean * @access private @@ -113,22 +133,29 @@ class Net_SMTP * @param string $host The server to connect to. * @param integer $port The port to connect to. * @param string $localhost The value to give when sending EHLO or HELO. + * @param boolean $pipeling Use SMTP command pipelining * * @access public * @since 1.0 */ - function Net_SMTP($host = null, $port = null, $localhost = null) + function Net_SMTP($host = null, $port = null, $localhost = null, $pipelining = false) { - if (isset($host)) $this->host = $host; - if (isset($port)) $this->port = $port; - if (isset($localhost)) $this->localhost = $localhost; + if (isset($host)) { + $this->host = $host; + } + if (isset($port)) { + $this->port = $port; + } + if (isset($localhost)) { + $this->localhost = $localhost; + } + $this->pipelining = $pipelining; $this->_socket = new Net_Socket(); - /* - * Include the Auth_SASL package. If the package is not available, - * we disable the authentication methods that depend upon it. - */ + /* Include the Auth_SASL package. If the package is not + * available, we disable the authentication methods that + * depend upon it. */ if ((@include_once 'Auth/SASL.php') === false) { $pos = array_search('DIGEST-MD5', $this->auth_methods); unset($this->auth_methods[$pos]); @@ -211,6 +238,9 @@ class Net_SMTP * @param mixed $valid The set of valid response codes. These * may be specified as an array of integer * values or as a single integer value. + * @param bool $later Do not parse the response now, but wait + * until the last command in the pipelined + * command group * * @return mixed True if the server returned a valid response code or * a PEAR_Error object is an error condition is reached. @@ -220,52 +250,54 @@ class Net_SMTP * * @see getResponse */ - function _parseResponse($valid) + function _parseResponse($valid, $later = false) { $this->_code = -1; $this->_arguments = array(); - while ($line = $this->_socket->readLine()) { - if ($this->_debug) { - echo "DEBUG: Recv: $line\n"; - } + if ($later) { + $this->_pipelined_commands++; + return true; + } - /* If we receive an empty line, the connection has been closed. */ - if (empty($line)) { - $this->disconnect(); - return PEAR::raiseError('Connection was unexpectedly closed'); - } + for ($i = 0; $i <= $this->_pipelined_commands; $i++) { + while ($line = $this->_socket->readLine()) { + if ($this->_debug) { + echo "DEBUG: Recv: $line\n"; + } - /* Read the code and store the rest in the arguments array. */ - $code = substr($line, 0, 3); - $this->_arguments[] = trim(substr($line, 4)); + /* If we receive an empty line, the connection has been closed. */ + if (empty($line)) { + $this->disconnect(); + return PEAR::raiseError('Connection was unexpectedly closed'); + } - /* Check the syntax of the response code. */ - if (is_numeric($code)) { - $this->_code = (int)$code; - } else { - $this->_code = -1; - break; - } + /* Read the code and store the rest in the arguments array. */ + $code = substr($line, 0, 3); + $this->_arguments[] = trim(substr($line, 4)); + + /* Check the syntax of the response code. */ + if (is_numeric($code)) { + $this->_code = (int)$code; + } else { + $this->_code = -1; + break; + } - /* If this is not a multiline response, we're done. */ - if (substr($line, 3, 1) != '-') { - break; + /* If this is not a multiline response, we're done. */ + if (substr($line, 3, 1) != '-') { + break; + } } } - /* Compare the server's response code with the valid code. */ + $this->_pipelined_commands = 0; + + /* Compare the server's response code with the valid code/codes. */ if (is_int($valid) && ($this->_code === $valid)) { return true; - } - - /* If we were given an array of valid response codes, check each one. */ - if (is_array($valid)) { - foreach ($valid as $valid_code) { - if ($this->_code === $valid_code) { - return true; - } - } + } elseif (is_array($valid) && in_array($this->_code, $valid, true)) { + return true; } return PEAR::raiseError('Invalid response code received from server', @@ -383,6 +415,10 @@ class Net_SMTP $this->_esmtp[$verb] = $arguments; } + if (!isset($this->_esmtp['PIPELINING'])) { + $this->pipelining = false; + } + return true; } @@ -687,6 +723,18 @@ class Net_SMTP } /** + * Return the list of SMTP service extensions advertised by the server. + * + * @return array The list of SMTP service extensions. + * @access public + * @since 1.3 + */ + function getServiceExtensions() + { + return $this->_esmtp; + } + + /** * Send the MAIL FROM: command. * * @param string $sender The sender (reverse path) to set. @@ -726,7 +774,7 @@ class Net_SMTP if (PEAR::isError($error = $this->_put('MAIL', $args))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } @@ -756,7 +804,7 @@ class Net_SMTP if (PEAR::isError($error = $this->_put('RCPT', $args))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(array(250, 251)))) { + if (PEAR::isError($error = $this->_parseResponse(array(250, 251), $this->pipelining))) { return $error; } @@ -825,7 +873,7 @@ class Net_SMTP if (PEAR::isError($result = $this->_send($data . "\r\n.\r\n"))) { return $result; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } @@ -847,7 +895,7 @@ class Net_SMTP if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } @@ -886,7 +934,7 @@ class Net_SMTP if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } @@ -925,7 +973,7 @@ class Net_SMTP if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } @@ -962,7 +1010,7 @@ class Net_SMTP if (PEAR::isError($error = $this->_put('RSET'))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } |