2 // +-----------------------------------------------------------------------+
3 // | Copyright (c) 2002, Richard Heyes |
4 // | All rights reserved. |
6 // | Redistribution and use in source and binary forms, with or without |
7 // | modification, are permitted provided that the following conditions |
10 // | o Redistributions of source code must retain the above copyright |
11 // | notice, this list of conditions and the following disclaimer. |
12 // | o Redistributions in binary form must reproduce the above copyright |
13 // | notice, this list of conditions and the following disclaimer in the |
14 // | documentation and/or other materials provided with the distribution.|
15 // | o The names of the authors may not be used to endorse or promote |
16 // | products derived from this software without specific prior written |
19 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 // +-----------------------------------------------------------------------+
32 // | Author: Richard Heyes <richard@phpguru.org> |
33 // | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar> |
34 // +-----------------------------------------------------------------------+
36 // $Id: POP3.php,v 1.1 2008-05-04 07:04:50 hsur Exp $
38 require_once('Net/Socket.php');
43 * +----------------------------- IMPORTANT ------------------------------+
44 * | Usage of this class compared to native php extensions such as IMAP |
45 * | is slow and may be feature deficient. If available you are STRONGLY |
46 * | recommended to use the php extensions. |
47 * +----------------------------------------------------------------------+
51 * For usage see the example script
54 define('NET_POP3_STATE_DISCONNECTED', 1, true);
55 define('NET_POP3_STATE_AUTHORISATION', 2, true);
56 define('NET_POP3_STATE_TRANSACTION', 4, true);
61 * Some basic information about the mail drop
62 * garnered from the STAT command
69 * Used for APOP to store the timestamp
76 * Timeout that is passed to the socket object
90 * Current state of the connection. Used with the
91 * constants defined above.
98 * Hostname to connect to
112 * To allow class debuging
119 * The auth methods this class support
122 //var $supportedAuthMethods=array('DIGEST-MD5', 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER');
123 //Disabling DIGEST-MD5 for now
124 var $supportedAuthMethods=array( 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER');
125 //var $supportedAuthMethods=array( 'CRAM-MD5', 'PLAIN' , 'LOGIN');
126 //var $supportedAuthMethods=array( 'PLAIN' , 'LOGIN');
130 * The auth methods this class support
133 var $supportedSASLAuthMethods=array('DIGEST-MD5', 'CRAM-MD5');
137 * The capability response
143 * Constructor. Sets up the object variables, and instantiates
151 $this->_timestamp = ''; // Used for APOP
152 $this->_maildrop = array();
154 $this->_state = NET_POP3_STATE_DISCONNECTED;
155 $this->_socket =& new Net_Socket();
157 * Include the Auth_SASL package. If the package is not available,
158 * we disable the authentication methods that depend upon it.
160 if ((@include_once 'Auth/SASL.php') == false) {
162 echo "AUTH_SASL NOT PRESENT!\n";
164 foreach($this->supportedSASLAuthMethods as $SASLMethod){
165 $pos = array_search( $SASLMethod, $this->supportedAuthMethods );
167 echo "DISABLING METHOD $SASLMethod\n";
169 unset($this->supportedAuthMethods[$pos]);
179 * Handles the errors the class can find
186 function _raiseError($msg, $code =-1)
188 include_once 'PEAR.php';
189 return PEAR::raiseError($msg, $code);
195 * Connects to the given host on the given port.
196 * Also looks for the timestamp in the greeting
197 * needed for APOP authentication
199 * @param string $host Hostname/IP address to connect to
200 * @param string $port Port to use to connect to on host
201 * @return bool Success/Failure
203 function connect($host = 'localhost', $port = 110)
205 $this->_host = $host;
206 $this->_port = $port;
208 $result = $this->_socket->connect($host, $port, false, $this->_timeout);
209 if ($result === true) {
210 $data = $this->_recvLn();
212 if( $this->_checkResponse($data) ){
213 // if the response begins with '+OK' ...
214 // if (@substr(strtoupper($data), 0, 3) == '+OK') {
215 // Check for string matching apop timestamp
216 if (preg_match('/<.+@.+>/U', $data, $matches)) {
217 $this->_timestamp = $matches[0];
219 $this->_maildrop = array();
220 $this->_state = NET_POP3_STATE_AUTHORISATION;
226 $this->_socket->disconnect();
231 * Disconnect function. Sends the QUIT command
232 * and closes the socket.
234 * @return bool Success/Failure
236 function disconnect()
238 return $this->_cmdQuit();
242 * Performs the login procedure. If there is a timestamp
243 * stored, APOP will be tried first, then basic USER/PASS.
245 * @param string $user Username to use
246 * @param string $pass Password to use
247 * @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");
248 * Valid methods are: 'DIGEST-MD5','CRAM-MD5','LOGIN','PLAIN','APOP','USER'
249 * @return mixed true on Success/ PEAR_ERROR on error
251 function login($user, $pass, $apop = true)
253 if ($this->_state == NET_POP3_STATE_AUTHORISATION) {
255 if(PEAR::isError($ret= $this->_cmdAuthenticate($user , $pass , $apop ) ) ){
258 if( ! PEAR::isError($ret)){
259 $this->_state = NET_POP3_STATE_TRANSACTION;
264 return $this->_raiseError('Generic login error' , 1);
270 * Parses the response from the capability command. Stores
271 * the result in $this->_capability
275 function _parseCapability()
278 if(!PEAR::isError($data = $this->_sendCmd('CAPA'))){
279 $data = $this->_getMultiline();
281 // CAPA command not supported, reset data var
282 // to avoid Notice errors of preg_split on an object
285 $data = preg_split('/\r?\n/', $data, -1, PREG_SPLIT_NO_EMPTY);
287 for ($i = 0; $i < count($data); $i++) {
290 if (preg_match('/^([a-z,\-]+)( ((.*))|$)$/i', $data[$i], $matches)) {
292 $capa=strtolower($matches[1]);
294 case 'implementation':
295 $this->_capability['implementation'] = $matches[3];
298 $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]);
301 $this->_capability[$capa] = $matches[2];
312 * Returns the name of the best authentication method that the server
315 * @param string if !=null,authenticate with this method ($userMethod).
317 * @return mixed Returns a string containing the name of the best
318 * supported authentication method or a PEAR_Error object
319 * if a failure condition is encountered.
323 function _getBestAuthMethod($userMethod = null)
334 $this->_parseCapability();
336 //unset($this->_capability['sasl']);
338 if( isset($this->_capability['sasl']) ){
339 $serverMethods=$this->_capability['sasl'];
341 $serverMethods=array('USER');
342 // Check for timestamp before attempting APOP
343 if ($this->_timestamp != null)
345 $serverMethods[] = 'APOP';
349 if($userMethod !== null && $userMethod !== true ){
351 $methods[] = $userMethod;
354 $methods = $this->supportedAuthMethods;
357 if( ($methods != null) && ($serverMethods != null)){
359 foreach ( $methods as $method ) {
361 if ( in_array( $method , $serverMethods ) ) {
365 $serverMethods=implode(',' , $serverMethods );
366 $myMethods=implode(',' ,$this->supportedAuthMethods);
367 return $this->_raiseError("$method NOT supported authentication method!. This server " .
368 "supports these methods: $serverMethods, but I support $myMethods");
370 return $this->_raiseError("This server don't support any Auth methods");
379 /* Handles the authentication using any known method
381 * @param string The userid to authenticate as.
382 * @param string The password to authenticate with.
383 * @param string The method to use ( if $usermethod == '' then the class chooses the best method (the stronger is the best ) )
385 * @return mixed string or PEAR_Error
390 function _cmdAuthenticate($uid , $pwd , $userMethod = null )
394 if ( PEAR::isError( $method = $this->_getBestAuthMethod($userMethod) ) ) {
400 $result = $this->_authDigest_MD5( $uid , $pwd );
403 $result = $this->_authCRAM_MD5( $uid , $pwd );
406 $result = $this->_authLOGIN( $uid , $pwd );
409 $result = $this->_authPLAIN( $uid , $pwd );
412 $result = $this->_cmdApop( $uid , $pwd );
413 // if APOP fails fallback to USER auth
414 if( PEAR::isError( $result ) ){
415 //echo "APOP FAILED!!!\n";
416 $result=$this->_authUSER( $uid , $pwd );
420 $result = $this->_authUSER( $uid , $pwd );
425 $result = $this->_raiseError( "$method is not a supported authentication method" );
434 /* Authenticates the user using the USER-PASS method.
436 * @param string The userid to authenticate as.
437 * @param string The password to authenticate with.
439 * @return mixed true on success or PEAR_Error on failure
444 function _authUSER($user, $pass )
446 if ( PEAR::isError($ret=$this->_cmdUser($user) ) ){
449 if ( PEAR::isError($ret=$this->_cmdPass($pass) ) ){
462 /* Authenticates the user using the PLAIN method.
464 * @param string The userid to authenticate as.
465 * @param string The password to authenticate with.
467 * @return array Returns an array containing the response
472 function _authPLAIN($user, $pass )
474 $cmd=sprintf('AUTH PLAIN %s', base64_encode( chr(0) . $user . chr(0) . $pass ) );
476 if ( PEAR::isError( $ret = $this->_send($cmd) ) ) {
479 if ( PEAR::isError( $challenge = $this->_recvLn() ) ){
482 if( PEAR::isError($ret=$this->_checkResponse($challenge) )){
491 /* Authenticates the user using the PLAIN method.
493 * @param string The userid to authenticate as.
494 * @param string The password to authenticate with.
496 * @return array Returns an array containing the response
501 function _authLOGIN($user, $pass )
503 $this->_send('AUTH LOGIN');
505 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
508 if( PEAR::isError($ret=$this->_checkResponse($challenge) )){
513 if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($user))) ) ) {
517 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
520 if( PEAR::isError($ret=$this->_checkResponse($challenge) )){
524 if ( PEAR::isError( $ret = $this->_send(sprintf('%s', base64_encode($pass))) ) ) {
528 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
531 return $this->_checkResponse($challenge);
538 /* Authenticates the user using the CRAM-MD5 method.
540 * @param string The userid to authenticate as.
541 * @param string The password to authenticate with.
543 * @return array Returns an array containing the response
548 function _authCRAM_MD5($uid, $pwd )
550 if ( PEAR::isError( $ret = $this->_send( 'AUTH CRAM-MD5' ) ) ) {
554 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
557 if( PEAR::isError($ret=$this->_checkResponse($challenge) )){
563 $challenge=substr($challenge,2);
565 $challenge = base64_decode( $challenge );
567 $cram = &Auth_SASL::factory('crammd5');
568 $auth_str = base64_encode( $cram->getResponse( $uid , $pwd , $challenge ) );
571 if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) {
574 if ( PEAR::isError( $ret = $this->_recvLn() ) ) {
578 return $this->_checkResponse($ret);
583 /* Authenticates the user using the DIGEST-MD5 method.
585 * @param string The userid to authenticate as.
586 * @param string The password to authenticate with.
587 * @param string The efective user
589 * @return array Returns an array containing the response
594 function _authDigest_MD5($uid, $pwd)
596 if ( PEAR::isError( $ret = $this->_send( 'AUTH DIGEST-MD5' ) ) ) {
600 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
603 if( PEAR::isError($ret=$this->_checkResponse($challenge) )){
608 $challenge=substr($challenge,2);
610 $challenge = base64_decode( $challenge );
611 $digest = &Auth_SASL::factory('digestmd5');
612 $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, "localhost", "pop3" ));
614 if ( PEAR::isError($error = $this->_send( $auth_str ) ) ) {
618 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
621 if( PEAR::isError($ret=$this->_checkResponse($challenge) )){
625 * We don't use the protocol's third step because POP3 doesn't allow
626 * subsequent authentication, so we just silently ignore it.
629 if ( PEAR::isError( $challenge = $this->_send("\r\n") ) ) {
633 if ( PEAR::isError( $challenge = $this->_recvLn() ) ) {
637 return $this->_checkResponse($challenge);
652 * Sends the APOP command
654 * @param $user Username to send
655 * @param $pass Password to send
656 * @return bool Success/Failure
658 function _cmdApop($user, $pass)
660 if ($this->_state == NET_POP3_STATE_AUTHORISATION) {
662 if (!empty($this->_timestamp)) {
663 if(PEAR::isError($data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)) ) ){
666 $this->_state = NET_POP3_STATE_TRANSACTION;
670 return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State1');
688 * Returns the raw headers of the specified message.
690 * @param integer $msg_id Message number
691 * @return mixed Either raw headers or false on error
693 function getRawHeaders($msg_id)
695 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
696 return $this->_cmdTop($msg_id, 0);
703 * Returns the headers of the specified message in an
704 * associative array. Array keys are the header names, array
705 * values are the header values. In the case of multiple headers
706 * having the same names, eg Received:, the array value will be
707 * an indexed array of all the header values.
709 * @param integer $msg_id Message number
710 * @return mixed Either array of headers or false on error
712 function getParsedHeaders($msg_id)
714 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
716 $raw_headers = rtrim($this->getRawHeaders($msg_id));
718 $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers
719 $raw_headers = explode("\r\n", $raw_headers);
720 foreach ($raw_headers as $value) {
721 $name = substr($value, 0, $pos = strpos($value, ':'));
722 $value = ltrim(substr($value, $pos + 1));
723 if (isset($headers[$name]) AND is_array($headers[$name])) {
724 $headers[$name][] = $value;
725 } elseif (isset($headers[$name])) {
726 $headers[$name] = array($headers[$name], $value);
728 $headers[$name] = $value;
739 * Returns the body of the message with given message number.
741 * @param integer $msg_id Message number
742 * @return mixed Either message body or false on error
744 function getBody($msg_id)
746 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
747 $msg = $this->_cmdRetr($msg_id);
748 return substr($msg, strpos($msg, "\r\n\r\n")+4);
755 * Returns the entire message with given message number.
757 * @param integer $msg_id Message number
758 * @return mixed Either entire message or false on error
760 function getMsg($msg_id)
762 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
763 return $this->_cmdRetr($msg_id);
770 * Returns the size of the maildrop
772 * @return mixed Either size of maildrop or false on error
776 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
777 if (isset($this->_maildrop['size'])) {
778 return $this->_maildrop['size'];
780 list(, $size) = $this->_cmdStat();
789 * Returns number of messages in this maildrop
791 * @return mixed Either number of messages or false on error
795 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
796 if (isset($this->_maildrop['num_msg'])) {
797 return $this->_maildrop['num_msg'];
799 list($num_msg, ) = $this->_cmdStat();
808 * Marks a message for deletion. Only will be deleted if the
809 * disconnect() method is called.
811 * @param integer $msg_id Message to delete
812 * @return bool Success/Failure
814 function deleteMsg($msg_id)
816 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
817 return $this->_cmdDele($msg_id);
824 * Combination of LIST/UIDL commands, returns an array
827 * @param integer $msg_id Optional message number
828 * @return mixed Array of data or false on error
830 function getListing($msg_id = null)
833 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
834 if (!isset($msg_id)){
837 if ($list = $this->_cmdList()) {
838 if ($uidl = $this->_cmdUidl()) {
839 foreach ($uidl as $i => $value) {
840 $list[$i]['uidl'] = $value['uidl'];
848 if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) {
849 return array_merge($list, $uidl);
858 * Sends the USER command
860 * @param string $user Username to send
861 * @return bool Success/Failure
863 function _cmdUser($user)
865 if ($this->_state == NET_POP3_STATE_AUTHORISATION) {
866 return $this->_sendCmd('USER ' . $user);
868 return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State');
873 * Sends the PASS command
875 * @param string $pass Password to send
876 * @return bool Success/Failure
878 function _cmdPass($pass)
880 if ($this->_state == NET_POP3_STATE_AUTHORISATION) {
881 return $this->_sendCmd('PASS ' . $pass);
883 return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State');
888 * Sends the STAT command
890 * @return mixed Indexed array of number of messages and
891 * maildrop size, or false on error.
895 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
896 if(!PEAR::isError($data = $this->_sendCmd('STAT'))){
897 sscanf($data, '+OK %d %d', $msg_num, $size);
898 $this->_maildrop['num_msg'] = $msg_num;
899 $this->_maildrop['size'] = $size;
901 return array($msg_num, $size);
909 * Sends the LIST command
911 * @param integer $msg_id Optional message number
912 * @return mixed Indexed array of msg_id/msg size or
915 function _cmdList($msg_id = null)
918 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
919 if (!isset($msg_id)) {
920 if(!PEAR::isError($data = $this->_sendCmd('LIST') )){
921 $data = $this->_getMultiline();
922 $data = explode("\r\n", $data);
923 foreach ($data as $line) {
925 sscanf($line, '%s %s', $msg_id, $size);
926 $return[] = array('msg_id' => $msg_id, 'size' => $size);
932 if(!PEAR::isError($data = $this->_sendCmd('LIST ' . $msg_id))){
934 sscanf($data, '+OK %d %d', $msg_id, $size);
935 return array('msg_id' => $msg_id, 'size' => $size);
948 * Sends the RETR command
950 * @param integer $msg_id The message number to retrieve
951 * @return mixed The message or false on error
953 function _cmdRetr($msg_id)
955 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
956 if(!PEAR::isError($data = $this->_sendCmd('RETR ' . $msg_id) )){
957 $data = $this->_getMultiline();
967 * Sends the DELE command
969 * @param integer $msg_id Message number to mark as deleted
970 * @return bool Success/Failure
972 function _cmdDele($msg_id)
974 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
975 return $this->_sendCmd('DELE ' . $msg_id);
983 * Sends the NOOP command
985 * @return bool Success/Failure
989 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
990 if(!PEAR::isError($data = $this->_sendCmd('NOOP'))){
999 * Sends the RSET command
1001 * @return bool Success/Failure
1005 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
1006 if(!PEAR::isError($data = $this->_sendCmd('RSET'))){
1015 * Sends the QUIT command
1017 * @return bool Success/Failure
1021 $data = $this->_sendCmd('QUIT');
1022 $this->_state = NET_POP3_STATE_DISCONNECTED;
1023 $this->_socket->disconnect();
1030 * Sends the TOP command
1032 * @param integer $msg_id Message number
1033 * @param integer $num_lines Number of lines to retrieve
1034 * @return mixed Message data or false on error
1036 function _cmdTop($msg_id, $num_lines)
1038 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
1040 if(!PEAR::isError($data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines))){
1041 return $this->_getMultiline();
1049 * Sends the UIDL command
1051 * @param integer $msg_id Message number
1052 * @return mixed indexed array of msg_id/uidl or false on error
1054 function _cmdUidl($msg_id = null)
1056 if ($this->_state == NET_POP3_STATE_TRANSACTION) {
1058 if (!isset($msg_id)) {
1059 if(!PEAR::isError($data = $this->_sendCmd('UIDL') )){
1060 $data = $this->_getMultiline();
1061 $data = explode("\r\n", $data);
1062 foreach ($data as $line) {
1063 sscanf($line, '%d %s', $msg_id, $uidl);
1064 $return[] = array('msg_id' => $msg_id, 'uidl' => $uidl);
1071 $data = $this->_sendCmd('UIDL ' . $msg_id);
1072 sscanf($data, '+OK %d %s', $msg_id, $uidl);
1073 return array('msg_id' => $msg_id, 'uidl' => $uidl);
1089 * Sends a command, checks the reponse, and
1090 * if good returns the reponse, other wise
1093 * @param string $cmd Command to send (\r\n will be appended)
1094 * @return mixed First line of response if successful, otherwise false
1096 function _sendCmd($cmd)
1098 if (PEAR::isError($result = $this->_send($cmd) )){
1102 if (PEAR::isError($data = $this->_recvLn() )){
1106 if ( strtoupper(substr($data, 0, 3)) == '+OK') {
1111 return $this->_raiseError($data);
1115 * Reads a multiline reponse and returns the data
1117 * @return string The reponse.
1119 function _getMultiline()
1122 while(!PEAR::isError($tmp = $this->_recvLn() ) ) {
1124 return substr($data, 0, -2);
1126 if (substr($tmp, 0, 2) == '..') {
1127 $tmp = substr($tmp, 1);
1129 $data .= $tmp . "\r\n";
1131 return substr($data, 0, -2);
1136 * Sets the bebug state
1138 * @param bool $debug
1142 function setDebug($debug=true)
1144 $this->_debug=$debug;
1152 * Send the given string of data to the server.
1154 * @param string $data The string of data to send.
1156 * @return mixed True on success or a PEAR_Error object on failure.
1161 function _send($data)
1163 if ($this->_debug) {
1167 if (PEAR::isError($error = $this->_socket->writeLine($data))) {
1168 return $this->_raiseError('Failed to write to socket: ' . $error->getMessage());
1176 * Receive the given string of data from the server.
1178 * @return mixed a line of response on success or a PEAR_Error object on failure.
1185 if (PEAR::isError( $lastline = $this->_socket->readLine( 8192 ) ) ) {
1186 return $this->_raiseError('Failed to write to socket: ' . $this->lastline->getMessage() );
1189 // S: means this data was sent by the POP3 Server
1190 echo "S:$lastline\n" ;
1196 * Checks de server Response
1198 * @param string $response the response
1199 * @return mixed true on success or a PEAR_Error object on failure.
1205 function _checkResponse($response)
1207 if (@substr(strtoupper($response), 0, 3) == '+OK') {
1210 if (@substr(strtoupper($response), 0, 4) == '-ERR') {
1211 return $this->_raiseError($response);
1213 if (@substr(strtoupper($response), 0, 2) == '+ ') {
1219 return $this->_raiseError("Unknown Response ($response)");