| | |
| | | * @param string The requested authentication method. If none is |
| | | * specified, the best supported method will be used. |
| | | * @param bool Flag indicating whether or not TLS should be attempted. |
| | | * @param string An optional authorization identifier. If specified, this |
| | | * identifier will be used as the authorization proxy. |
| | | * |
| | | * @return mixed Returns a PEAR_Error with an error message on any |
| | | * kind of failure, or true on success. |
| | | * @access public |
| | | * @since 1.0 |
| | | */ |
| | | function auth($uid, $pwd , $method = '', $tls = true) |
| | | function auth($uid, $pwd , $method = '', $tls = true, $authz = '') |
| | | { |
| | | /* We can only attempt a TLS connection if one has been requested, |
| | | * we're running PHP 5.1.0 or later, have access to the OpenSSL |
| | |
| | | |
| | | switch ($method) { |
| | | case 'DIGEST-MD5': |
| | | $result = $this->_authDigest_MD5($uid, $pwd); |
| | | $result = $this->_authDigest_MD5($uid, $pwd, $authz); |
| | | break; |
| | | |
| | | case 'CRAM-MD5': |
| | |
| | | break; |
| | | |
| | | case 'PLAIN': |
| | | $result = $this->_authPlain($uid, $pwd); |
| | | $result = $this->_authPlain($uid, $pwd, $authz); |
| | | break; |
| | | |
| | | default: |
| | |
| | | * |
| | | * @param string The userid to authenticate as. |
| | | * @param string The password to authenticate with. |
| | | * @param string The optional authorization proxy identifier. |
| | | * |
| | | * @return mixed Returns a PEAR_Error with an error message on any |
| | | * kind of failure, or true on success. |
| | | * @access private |
| | | * @since 1.1.0 |
| | | */ |
| | | function _authDigest_MD5($uid, $pwd) |
| | | function _authDigest_MD5($uid, $pwd, $authz = '') |
| | | { |
| | | if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { |
| | | return $error; |
| | |
| | | $challenge = base64_decode($this->_arguments[0]); |
| | | $digest = &Auth_SASL::factory('digestmd5'); |
| | | $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, |
| | | $this->host, "smtp")); |
| | | $this->host, "smtp", $authz)); |
| | | |
| | | if (PEAR::isError($error = $this->_put($auth_str))) { |
| | | return $error; |
| | |
| | | * |
| | | * @param string The userid to authenticate as. |
| | | * @param string The password to authenticate with. |
| | | * @param string The optional authorization proxy identifier. |
| | | * |
| | | * @return mixed Returns a PEAR_Error with an error message on any |
| | | * kind of failure, or true on success. |
| | | * @access private |
| | | * @since 1.1.0 |
| | | */ |
| | | function _authPlain($uid, $pwd) |
| | | function _authPlain($uid, $pwd, $authz = '') |
| | | { |
| | | if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { |
| | | return $error; |
| | |
| | | return $error; |
| | | } |
| | | |
| | | $auth_str = base64_encode(chr(0) . $uid . chr(0) . $pwd); |
| | | $auth_str = base64_encode($authz . chr(0) . $uid . chr(0) . $pwd); |
| | | |
| | | if (PEAR::isError($error = $this->_put($auth_str))) { |
| | | return $error; |
| | |
| | | return $result; |
| | | } |
| | | } |
| | | |
| | | /* Finally, send the DATA terminator sequence. */ |
| | | if (PEAR::isError($result = $this->_send("\r\n.\r\n"))) { |
| | | return $result; |
| | | } |
| | | } else { |
| | | /* Just send the entire quoted string followed by the DATA |
| | | * terminator. */ |
| | | $this->quotedata($data); |
| | | if (PEAR::isError($result = $this->_send($data . "\r\n.\r\n"))) { |
| | | return $result; |
| | | /* |
| | | * Break up the data by sending one chunk (up to 512k) at a time. |
| | | * This approach reduces our peak memory usage. |
| | | */ |
| | | for ($offset = 0; $offset < $size;) { |
| | | $end = $offset + 512000; |
| | | |
| | | /* |
| | | * Ensure we don't read beyond our data size or span multiple |
| | | * lines. quotedata() can't properly handle character data |
| | | * that's split across two line break boundaries. |
| | | */ |
| | | if ($end >= $size) { |
| | | $end = $size; |
| | | } else { |
| | | for (; $end < $size; $end++) { |
| | | if ($data[$end] != "\n") { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* Extract our chunk and run it through the quoting routine. */ |
| | | $chunk = substr($data, $offset, $end - $offset); |
| | | $this->quotedata($chunk); |
| | | |
| | | /* If we run into a problem along the way, abort. */ |
| | | if (PEAR::isError($result = $this->_send($chunk))) { |
| | | return $result; |
| | | } |
| | | |
| | | /* Advance the offset to the end of this chunk. */ |
| | | $offset = $end; |
| | | } |
| | | } |
| | | |
| | | /* Finally, send the DATA terminator sequence. */ |
| | | if (PEAR::isError($result = $this->_send("\r\n.\r\n"))) { |
| | | return $result; |
| | | } |
| | | |
| | | /* Verify that the data was successfully received by the server. */ |
| | | if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { |
| | | return $error; |