Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php// +-----------------------------------------------------------------------+// | Copyright (c) 2002, Richard Heyes |// | All rights reserved. |// | |// | Redistribution and use in source and binary forms, with or without |// | modification, are permitted provided that the following conditions |// | are met: |// | |// | o Redistributions of source code must retain the above copyright |// | notice, this list of conditions and the following disclaimer. |// | o Redistributions in binary form must reproduce the above copyright |// | notice, this list of conditions and the following disclaimer in the |// | documentation and/or other materials provided with the distribution.|// | o The names of the authors may not be used to endorse or promote |// | products derived from this software without specific prior written |// | permission. |// | |// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |// | |// +-----------------------------------------------------------------------+// | Author: Richard Heyes <richard@phpguru.org> |// | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar> |// +-----------------------------------------------------------------------+//// $Id: POP3.php 295243 2010-02-18 22:05:20Z clockwerx $require_once 'Net/Socket.php';/*** +----------------------------- IMPORTANT ------------------------------+* | Usage of this class compared to native php extensions such as IMAP |* | is slow and may be feature deficient. If available you are STRONGLY |* | recommended to use the php extensions. |* +----------------------------------------------------------------------+** POP3 Access Class** For usage see the example script*/define('NET_POP3_STATE_DISCONNECTED', 1, true);define('NET_POP3_STATE_AUTHORISATION', 2, true);define('NET_POP3_STATE_TRANSACTION', 4, true);class Net_POP3{/*** Some basic information about the mail drop* garnered from the STAT command** @var array*/var $_maildrop;/*** Used for APOP to store the timestamp** @var string*/var $_timestamp;/*** Timeout that is passed to the socket object** @var integer*/var $_timeout;/*** Socket object** @var object*/var $_socket;/*** Current state of the connection. Used with the* constants defined above.** @var integer*/var $_state;/*** Hostname to connect to** @var string*/var $_host;/*** Port to connect to** @var integer*/var $_port;/*** To allow class debuging* @var boolean*/var $_debug = false;/*** The auth methods this class support* @var array*///var $supportedAuthMethods=array('DIGEST-MD5', 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER');//Disabling DIGEST-MD5 for nowvar $supportedAuthMethods=array( 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER');//var $supportedAuthMethods=array( 'CRAM-MD5', 'PLAIN' , 'LOGIN');//var $supportedAuthMethods=array( 'PLAIN' , 'LOGIN');/*** The auth methods this class support* @var array*/var $supportedSASLAuthMethods=array('DIGEST-MD5', 'CRAM-MD5');/*** The capability response* @var array*/var $_capability;/*** Constructor. Sets up the object variables, and instantiates* the socket object.**/function Net_POP3(){$this->_timestamp = ''; // Used for APOP$this->_maildrop = array();$this->_timeout = 3;$this->_state = NET_POP3_STATE_DISCONNECTED;$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_once 'Auth/SASL.php';if (!class_exists('Auth_SASL')) {if ($this->_debug){echo "AUTH_SASL NOT PRESENT!\n";}foreach ($this->supportedSASLAuthMethods as $SASLMethod) {$pos = array_search($SASLMethod, $this->supportedAuthMethods);if ($this->_debug) {echo "DISABLING METHOD $SASLMethod\n";}unset($this->supportedAuthMethods[$pos]);}}}/*** Handles the errors the class can find* on the server** @access private* @return PEAR_Error*/function _raiseError($msg, $code =-1){include_once 'PEAR.php';return PEAR::raiseError($msg, $code);}/*** Connects to the given host on the given port.* Also looks for the timestamp in the greeting* needed for APOP authentication** @param string $host Hostname/IP address to connect to* @param string $port Port to use to connect to on host* @return bool Success/Failure*/function connect($host = 'localhost', $port = 110){$this->_host = $host;$this->_port = $port;$result = $this->_socket->connect($host, $port, false, $this->_timeout);if ($result === true) {$data = $this->_recvLn();if( $this->_checkResponse($data) ){// if the response begins with '+OK' ...// if (@substr(strtoupper($data), 0, 3) == '+OK') {// Check for string matching apop timestampif (preg_match('/<.+@.+>/U', $data, $matches)) {$this->_timestamp = $matches[0];}$this->_maildrop = array();$this->_state = NET_POP3_STATE_AUTHORISATION;return true;}}$this->_socket->disconnect();return false;}/*** Disconnect function. Sends the QUIT command* and closes the socket.** @return bool Success/Failure*/function disconnect(){return $this->_cmdQuit();}/*** Performs the login procedure. If there is a timestamp* stored, APOP will be tried first, then basic USER/PASS.** @param string $user Username to use* @param string $pass Password to use* @param mixed $apop Whether to try APOP first, if used as string you can select the auth methd to use ( $pop3->login('validlogin', 'validpass', "CRAM-MD5");* Valid methods are: 'DIGEST-MD5','CRAM-MD5','LOGIN','PLAIN','APOP','USER'* @return mixed true on Success/ PEAR_ERROR on error*/function login($user, $pass, $apop = true){if ($this->_state == NET_POP3_STATE_AUTHORISATION) {if (PEAR::isError($ret= $this->_cmdAuthenticate($user, $pass, $apop))){return $ret;}if (!PEAR::isError($ret)) {$this->_state = NET_POP3_STATE_TRANSACTION;return true;}}return $this->_raiseError('Generic login error' , 1);}/*** Parses the response from the capability command. Stores* the result in $this->_capability** @access private*/function _parseCapability(){if(!PEAR::isError($data = $this->_sendCmd('CAPA'))){$data = $this->_getMultiline();}else {// CAPA command not supported, reset data var// to avoid Notice errors of preg_split on an object$data = '';}$data = preg_split('/\r?\n/', $data, -1, PREG_SPLIT_NO_EMPTY);for ($i = 0; $i < count($data); $i++) {$capa='';if (preg_match('/^([a-z,\-]+)( ((.*))|$)$/i', $data[$i], $matches)) {$capa=strtolower($matches[1]);switch ($capa) {case 'implementation':$this->_capability['implementation'] = $matches[3];break;case 'sasl':$this->_capability['sasl'] = preg_split('/\s+/', $matches[3]);break;default :$this->_capability[$capa] = $matches[2];break;}}}}/*** Returns the name of the best authentication method that the server* has advertised.** @param string if !=null,authenticate with this method ($userMethod).** @return mixed Returns a string containing the name of the best* supported authentication method or a PEAR_Error object* if a failure condition is encountered.* @access private* @since 1.0*/function _getBestAuthMethod($userMethod = null){/*return 'USER';return 'APOP';return 'DIGEST-MD5';return 'CRAM-MD5';*/$this->_parseCapability();//unset($this->_capability['sasl']);if (isset($this->_capability['sasl']) ){$serverMethods=$this->_capability['sasl'];} else {$serverMethods=array('USER');// Check for timestamp before attempting APOPif ($this->_timestamp != null){$serverMethods[] = 'APOP';}}if ($userMethod !== null && $userMethod !== true) {$methods = array();$methods[] = $userMethod;return $userMethod;} else {$methods = $this->supportedAuthMethods;}if (($methods != null) && ($serverMethods != null)) {foreach ($methods as $method ) {if (in_array($method, $serverMethods)) {return $method;}}$serverMethods=implode(',' , $serverMethods );$myMethods=implode(',' ,$this->supportedAuthMethods);return $this->_raiseError("$method NOT supported authentication method!. This server " ."supports these methods: $serverMethods, but I support $myMethods");} else {return $this->_raiseError("This server don't support any Auth methods");}}/*** Handles the authentication using any known method** @param string The userid to authenticate as.* @param string The password to authenticate with.* @param string The method to use ( if $usermethod == '' then the class chooses the best method (the stronger is the best ) )** @return mixed string or PEAR_Error* @access private* @since 1.0*/function _cmdAuthenticate($uid , $pwd , $userMethod = null ){if (PEAR::isError($method = $this->_getBestAuthMethod($userMethod))) {return $method;}if (!in_array($userMethod, $this->supportedAuthMethods)) {return $this->_raiseError('Authentication method "' . $userMethod . '" is not supported.');}switch ($method) {case 'DIGEST-MD5':$result = $this->_authDigest_MD5( $uid , $pwd );break;case 'CRAM-MD5':$result = $this->_authCRAM_MD5( $uid , $pwd );break;case 'LOGIN':$result = $this->_authLOGIN( $uid , $pwd );break;case 'PLAIN':$result = $this->_authPLAIN( $uid , $pwd );break;case 'APOP':$result = $this->_cmdApop( $uid , $pwd );// if APOP fails fallback to USER authif (PEAR::isError($result)){//echo "APOP FAILED!!!\n";$result=$this->_authUSER( $uid , $pwd );}break;case 'USER':$result = $this->_authUSER( $uid , $pwd );break;default :$result = $this->_raiseError( "$method is not a supported authentication method" );break;}return $result;}/*** Authenticates the user using the USER-PASS method.** @param string The userid to authenticate as.* @param string The password to authenticate with.** @return mixed true on success or PEAR_Error on failure** @access private* @since 1.0*/function _authUSER($user, $pass ){if ( PEAR::isError($ret=$this->_cmdUser($user) ) ){return $ret;}if ( PEAR::isError($ret=$this->_cmdPass($pass) ) ){return $ret;}return true;}/*** Authenticates the user using the PLAIN method.** @param string The userid to authenticate as.* @param string The password to authenticate with.** @return array Returns an array containing the response** @access private* @since 1.0*/function _authPLAIN($user, $pass ){$cmd=sprintf('AUTH PLAIN %s', base64_encode( chr(0) . $user . chr(0) . $pass ) );if ( PEAR::isError( $ret = $this->_send($cmd) ) ) {return $ret;}if ( PEAR::isError( $challenge = $this->_recvLn() ) ){return $challenge;}if( PEAR::isError($ret=$this->_checkResponse($challenge) )){return $ret;}return true;}/*** Authenticates the user using the PLAIN method.** @param string The userid to authenticate as.* @param string The password to authenticate with.** @return array Returns an array containing the response** @access private* @since 1.0*/function _authLOGIN($user, $pass ){$this->_send('AUTH LOGIN');if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {return $challenge;}if( PEAR::isError($ret=$this->_checkResponse($challenge) )){return $ret;}if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($user))) ) ) {return $ret;}if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {return $challenge;}if( PEAR::isError($ret=$this->_checkResponse($challenge) )){return $ret;}if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($pass))) ) ) {return $ret;}if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {return $challenge;}return $this->_checkResponse($challenge);}/*** Authenticates the user using the CRAM-MD5 method.** @param string The userid to authenticate as.* @param string The password to authenticate with.** @return array Returns an array containing the response** @access private* @since 1.0*/function _authCRAM_MD5($uid, $pwd ){if (PEAR::isError($ret = $this->_send('AUTH CRAM-MD5'))) {return $ret;}if (PEAR::isError($challenge = $this->_recvLn())) {return $challenge;}if (PEAR::isError($ret=$this->_checkResponse($challenge))) {return $ret;}// remove '+ '$challenge=substr($challenge,2);$challenge = base64_decode($challenge);$cram = &Auth_SASL::factory('crammd5');$auth_str = base64_encode($cram->getResponse($uid , $pwd , $challenge));if (PEAR::isError($error = $this->_send($auth_str))) {return $error;}if (PEAR::isError($ret = $this->_recvLn())) {return $ret;}//echo "RET:$ret\n";return $this->_checkResponse($ret);}/*** Authenticates the user using the DIGEST-MD5 method.** @param string The userid to authenticate as.* @param string The password to authenticate with.* @param string The efective user** @return array Returns an array containing the response** @access private* @since 1.0*/function _authDigest_MD5($uid, $pwd){if ( PEAR::isError( $ret = $this->_send( 'AUTH DIGEST-MD5' ) ) ) {return $ret;}if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {return $challenge;}if( PEAR::isError($ret=$this->_checkResponse($challenge) )){return $ret;}// remove '+ '$challenge=substr($challenge,2);$challenge = base64_decode( $challenge );$digest = &Auth_SASL::factory('digestmd5');$auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, "localhost", "pop3" ));if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) {return $error;}if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {return $challenge;}if( PEAR::isError($ret=$this->_checkResponse($challenge) )){return $ret;}/** We don't use the protocol's third step because POP3 doesn't allow* subsequent authentication, so we just silently ignore it.*/if ( PEAR::isError( $challenge = $this->_send("\r\n") ) ) {return $challenge ;}if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {return $challenge;}return $this->_checkResponse($challenge);}/*** Sends the APOP command** @param $user Username to send* @param $pass Password to send* @return bool Success/Failure*/function _cmdApop($user, $pass){if ($this->_state == NET_POP3_STATE_AUTHORISATION) {if (!empty($this->_timestamp)) {if(PEAR::isError($data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)) ) ){return $data;}$this->_state = NET_POP3_STATE_TRANSACTION;return true;}}return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State1');}/*** Returns the raw headers of the specified message.** @param integer $msg_id Message number* @return mixed Either raw headers or false on error*/function getRawHeaders($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {return $this->_cmdTop($msg_id, 0);}return false;}/*** Returns the headers of the specified message in an* associative array. Array keys are the header names, array* values are the header values. In the case of multiple headers* having the same names, eg Received:, the array value will be* an indexed array of all the header values.** @param integer $msg_id Message number* @return mixed Either array of headers or false on error*/function getParsedHeaders($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {$raw_headers = rtrim($this->getRawHeaders($msg_id));$raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers$raw_headers = explode("\r\n", $raw_headers);foreach ($raw_headers as $value) {$name = substr($value, 0, $pos = strpos($value, ':'));$value = ltrim(substr($value, $pos + 1));if (isset($headers[$name]) AND is_array($headers[$name])) {$headers[$name][] = $value;} elseif (isset($headers[$name])) {$headers[$name] = array($headers[$name], $value);} else {$headers[$name] = $value;}}return $headers;}return false;}/*** Returns the body of the message with given message number.** @param integer $msg_id Message number* @return mixed Either message body or false on error*/function getBody($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {$msg = $this->_cmdRetr($msg_id);return substr($msg, strpos($msg, "\r\n\r\n")+4);}return false;}/*** Returns the entire message with given message number.** @param integer $msg_id Message number* @return mixed Either entire message or false on error*/function getMsg($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {return $this->_cmdRetr($msg_id);}return false;}/*** Returns the size of the maildrop** @return mixed Either size of maildrop or false on error*/function getSize(){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if (isset($this->_maildrop['size'])) {return $this->_maildrop['size'];} else {list(, $size) = $this->_cmdStat();return $size;}}return false;}/*** Returns number of messages in this maildrop** @return mixed Either number of messages or false on error*/function numMsg(){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if (isset($this->_maildrop['num_msg'])) {return $this->_maildrop['num_msg'];} else {list($num_msg, ) = $this->_cmdStat();return $num_msg;}}return false;}/*** Marks a message for deletion. Only will be deleted if the* disconnect() method is called.** @param integer $msg_id Message to delete* @return bool Success/Failure*/function deleteMsg($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {return $this->_cmdDele($msg_id);}return false;}/*** Combination of LIST/UIDL commands, returns an array* of data** @param integer $msg_id Optional message number* @return mixed Array of data or false on error*/function getListing($msg_id = null){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if (!isset($msg_id)){$list=array();if ($list = $this->_cmdList()) {if ($uidl = $this->_cmdUidl()) {foreach ($uidl as $i => $value) {$list[$i]['uidl'] = $value['uidl'];}}return $list;}else{return array();}} else {if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) {return array_merge($list, $uidl);}}}return false;}/*** Sends the USER command** @param string $user Username to send* @return bool Success/Failure*/function _cmdUser($user){if ($this->_state == NET_POP3_STATE_AUTHORISATION) {return $this->_sendCmd('USER ' . $user);}return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State');}/*** Sends the PASS command** @param string $pass Password to send* @return bool Success/Failure*/function _cmdPass($pass){if ($this->_state == NET_POP3_STATE_AUTHORISATION) {return $this->_sendCmd('PASS ' . $pass);}return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State');}/*** Sends the STAT command** @return mixed Indexed array of number of messages and* maildrop size, or false on error.*/function _cmdStat(){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if(!PEAR::isError($data = $this->_sendCmd('STAT'))){sscanf($data, '+OK %d %d', $msg_num, $size);$this->_maildrop['num_msg'] = $msg_num;$this->_maildrop['size'] = $size;return array($msg_num, $size);}}return false;}/*** Sends the LIST command** @param integer $msg_id Optional message number* @return mixed Indexed array of msg_id/msg size or* false on error*/function _cmdList($msg_id = null){$return=array();if ($this->_state == NET_POP3_STATE_TRANSACTION) {if (!isset($msg_id)) {if(!PEAR::isError($data = $this->_sendCmd('LIST') )){$data = $this->_getMultiline();$data = explode("\r\n", $data);foreach ($data as $line) {if($line !=''){sscanf($line, '%s %s', $msg_id, $size);$return[] = array('msg_id' => $msg_id, 'size' => $size);}}return $return;}} else {if(!PEAR::isError($data = $this->_sendCmd('LIST ' . $msg_id))){if($data!=''){sscanf($data, '+OK %d %d', $msg_id, $size);return array('msg_id' => $msg_id, 'size' => $size);}return array();}}}return false;}/*** Sends the RETR command** @param integer $msg_id The message number to retrieve* @return mixed The message or false on error*/function _cmdRetr($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if(!PEAR::isError($data = $this->_sendCmd('RETR ' . $msg_id) )){$data = $this->_getMultiline();return $data;}}return false;}/*** Sends the DELE command** @param integer $msg_id Message number to mark as deleted* @return bool Success/Failure*/function _cmdDele($msg_id){if ($this->_state == NET_POP3_STATE_TRANSACTION) {return $this->_sendCmd('DELE ' . $msg_id);}return false;}/*** Sends the NOOP command** @return bool Success/Failure*/function _cmdNoop(){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if(!PEAR::isError($data = $this->_sendCmd('NOOP'))){return true;}}return false;}/*** Sends the RSET command** @return bool Success/Failure*/function _cmdRset(){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if(!PEAR::isError($data = $this->_sendCmd('RSET'))){return true;}}return false;}/*** Sends the QUIT command** @return bool Success/Failure*/function _cmdQuit(){$data = $this->_sendCmd('QUIT');$this->_state = NET_POP3_STATE_DISCONNECTED;$this->_socket->disconnect();return (bool)$data;}/*** Sends the TOP command** @param integer $msg_id Message number* @param integer $num_lines Number of lines to retrieve* @return mixed Message data or false on error*/function _cmdTop($msg_id, $num_lines){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if(!PEAR::isError($data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines))){return $this->_getMultiline();}}return false;}/*** Sends the UIDL command** @param integer $msg_id Message number* @return mixed indexed array of msg_id/uidl or false on error*/function _cmdUidl($msg_id = null){if ($this->_state == NET_POP3_STATE_TRANSACTION) {if (!isset($msg_id)) {if(!PEAR::isError($data = $this->_sendCmd('UIDL') )){$data = $this->_getMultiline();$data = explode("\r\n", $data);foreach ($data as $line) {sscanf($line, '%d %s', $msg_id, $uidl);$return[] = array('msg_id' => $msg_id, 'uidl' => $uidl);}return $return;}} else {$data = $this->_sendCmd('UIDL ' . $msg_id);sscanf($data, '+OK %d %s', $msg_id, $uidl);return array('msg_id' => $msg_id, 'uidl' => $uidl);}}return false;}/*** Sends a command, checks the reponse, and* if good returns the reponse, other wise* returns false.** @param string $cmd Command to send (\r\n will be appended)* @return mixed First line of response if successful, otherwise false*/function _sendCmd($cmd){if (PEAR::isError($result = $this->_send($cmd) )){return $result ;}if (PEAR::isError($data = $this->_recvLn() )){return $data;}if ( strtoupper(substr($data, 0, 3)) == '+OK') {return $data;}return $this->_raiseError($data);}/*** Reads a multiline reponse and returns the data** @return string The reponse.*/function _getMultiline(){$data = '';while(!PEAR::isError($tmp = $this->_recvLn() ) ) {if($tmp == '.' || $tmp == "\n."){return substr($data, 0, -2);}if (substr($tmp, 0, 2) == '..') {$tmp = substr($tmp, 1);}$data .= $tmp . "\r\n";}return substr($data, 0, -2);}/*** Sets the bebug state** @param bool $debug* @access public* @return void*/function setDebug($debug=true){$this->_debug=$debug;}/*** Send the given string of data to the server.** @param string $data The string of data to send.** @return mixed True on success or a PEAR_Error object on failure.** @access private* @since 1.0*/function _send($data){if ($this->_debug) {echo "C: $data\n";}if (PEAR::isError($error = $this->_socket->writeLine($data))) {return $this->_raiseError('Failed to write to socket: ' . $error->getMessage());}return true;}/*** Receive the given string of data from the server.** @return mixed a line of response on success or a PEAR_Error object on failure.** @access private* @since 1.0*/function _recvLn(){if (PEAR::isError($lastline = $this->_socket->readLine(8192))) {return $this->_raiseError('Failed to read from socket: ' . $this->lastline->getMessage());}if ($this->_debug) {// S: means this data was sent by the POP3 Serverecho "S:$lastline\n" ;}return $lastline;}/*** Checks de server Response** @param string $response the response* @return mixed true on success or a PEAR_Error object on failure.** @access private* @since 1.3.3*/function _checkResponse($response){if (@substr(strtoupper($response), 0, 3) == '+OK') {return true;} else {if (@substr(strtoupper($response), 0, 4) == '-ERR') {return $this->_raiseError($response);} else {if (@substr(strtoupper($response), 0, 2) == '+ ') {return true;}}}return $this->_raiseError("Unknown Response ($response)");}}?>