Net_POP3

The MailPoet Newsletters Net POP3 class.

Defined (1)

The class is defined in the following location(s).

/inc/pear/pop3.php  
  1. class Net_POP3 { 
  2.  
  3. /** 
  4. * Some basic information about the mail drop 
  5. * garnered from the STAT command 
  6. * @var array 
  7. */ 
  8. var $_maildrop; 
  9.  
  10. /** 
  11. * Used for APOP to store the timestamp 
  12. * @var string 
  13. */ 
  14. var $_timestamp; 
  15.  
  16. /** 
  17. * Timeout that is passed to the socket object 
  18. * @var integer 
  19. */ 
  20. var $_timeout = 0; 
  21.  
  22. /** 
  23. * Socket object 
  24. * @var object 
  25. */ 
  26. var $_socket; 
  27.  
  28. /** 
  29. * Current state of the connection. Used with the 
  30. * constants defined above. 
  31. * @var integer 
  32. */ 
  33. var $_state; 
  34.  
  35. /** 
  36. * Hostname to connect to 
  37. * @var string 
  38. */ 
  39. var $_host; 
  40.  
  41. /** 
  42. * Port to connect to 
  43. * @var integer 
  44. */ 
  45. var $_port; 
  46.  
  47. /** 
  48. * To allow class debuging 
  49. * @var boolean 
  50. */ 
  51. var $_debug = false; 
  52.  
  53.  
  54. /** 
  55. * The auth methods this class support 
  56. * @var array 
  57. */ 
  58. //var $supportedAuthMethods=array('DIGEST-MD5', 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER'); 
  59. //Disabling DIGEST-MD5 for now 
  60. var $supportedAuthMethods=array( 'CRAM-MD5', 'APOP' , 'PLAIN' , 'LOGIN', 'USER'); 
  61. //var $supportedAuthMethods=array( 'CRAM-MD5', 'PLAIN' , 'LOGIN'); 
  62. //var $supportedAuthMethods=array( 'PLAIN' , 'LOGIN'); 
  63.  
  64.  
  65. /** 
  66. * The auth methods this class support 
  67. * @var array 
  68. */ 
  69. var $supportedSASLAuthMethods=array('DIGEST-MD5', 'CRAM-MD5'); 
  70.  
  71.  
  72. /** 
  73. * The capability response 
  74. * @var array 
  75. */ 
  76. var $_capability; 
  77.  
  78. /** 
  79. * Constructor. Sets up the object variables, and instantiates 
  80. * the socket object. 
  81. */ 
  82.  
  83. function __construct() 
  84. $this->_timestamp = ''; // Used for APOP 
  85. $this->_maildrop = array(); 
  86. //$this->_timeout = 3; 
  87. $this->_state = NET_POP3_STATE_DISCONNECTED; 
  88. $this->_socket = new Net_Socket(); 
  89. /** 
  90. * Include the Auth_SASL package. If the package is not available,  
  91. * we disable the authentication methods that depend upon it. 
  92. */ 
  93. if($this->_debug) { 
  94. echo "AUTH_SASL NOT PRESENT!\n"; 
  95. foreach($this->supportedSASLAuthMethods as $SASLMethod) { 
  96. $pos = array_search( $SASLMethod, $this->supportedAuthMethods ); 
  97. if($this->_debug) { 
  98. echo "DISABLING METHOD $SASLMethod\n"; 
  99. unset($this->supportedAuthMethods[$pos]); 
  100. $this->PEAR = new PEAR(); 
  101.  
  102.  
  103. function setTimeOut($timeOut) { 
  104. $this->_timeout = $timeOut; 
  105.  
  106.  
  107. /** 
  108. * Handles the errors the class can find 
  109. * on the server 
  110. * @access private 
  111. * @return PEAR_Error 
  112. */ 
  113.  
  114. function _raiseError($msg, $code =-1) 
  115. return $this->PEAR->raiseError($msg, $code); 
  116.  
  117.  
  118.  
  119. /** 
  120. * Connects to the given host on the given port. 
  121. * Also looks for the timestamp in the greeting 
  122. * needed for APOP authentication 
  123. * @param string $host Hostname/IP address to connect to 
  124. * @param string $port Port to use to connect to on host 
  125. * @return bool Success/Failure 
  126. */ 
  127. function connect($host = 'localhost', $port = 110) 
  128. $this->_host = $host; 
  129. $this->_port = $port; 
  130.  
  131. $result = $this->_socket->connect($host, $port, false, $this->_timeout); 
  132. if ($result === true) { 
  133. $data = $this->_recvLn(); 
  134.  
  135. if( $this->_checkResponse($data) ) { 
  136. // if the response begins with '+OK' ... 
  137. // if (@substr(strtoupper($data), 0, 3) == '+OK') { 
  138. // Check for string matching apop timestamp 
  139. if (preg_match('/<.+@.+>/U', $data, $matches)) { 
  140. $this->_timestamp = $matches[0]; 
  141. $this->_maildrop = array(); 
  142. $this->_state = NET_POP3_STATE_AUTHORISATION; 
  143.  
  144. return true; 
  145.  
  146. $this->_socket->disconnect(); 
  147. return false; 
  148.  
  149. /** 
  150. * Disconnect function. Sends the QUIT command 
  151. * and closes the socket. 
  152. * @return bool Success/Failure 
  153. */ 
  154. function disconnect() 
  155. return $this->_cmdQuit(); 
  156.  
  157. /** 
  158. * Performs the login procedure. If there is a timestamp 
  159. * stored, APOP will be tried first, then basic USER/PASS. 
  160. * @param string $user Username to use 
  161. * @param string $pass Password to use 
  162. * @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"); 
  163. * Valid methods are: 'DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN', 'APOP', 'USER' 
  164. * @return mixed true on Success/ PEAR_ERROR on error 
  165. */ 
  166. function login($user, $pass, $apop = true) 
  167. if ($this->_state == NET_POP3_STATE_AUTHORISATION) { 
  168.  
  169. if($this->PEAR->isError($ret= $this->_cmdAuthenticate($user , $pass , $apop ) ) ) { 
  170. return $ret; 
  171. if( ! $this->PEAR->isError($ret)) { 
  172. $this->_state = NET_POP3_STATE_TRANSACTION; 
  173. return true; 
  174.  
  175. return $this->_raiseError('Generic login error' , 1); 
  176.  
  177.  
  178.  
  179. /** 
  180. * Parses the response from the capability command. Stores 
  181. * the result in $this->_capability 
  182. * @access private 
  183. */ 
  184. function _parseCapability() 
  185.  
  186. if($this->_sendCmd('CAPA')) { 
  187. $data = $this->_getMultiline(); 
  188. }else { 
  189. // CAPA command not supported, reset data var 
  190. // to avoid Notice errors of preg_split on an object 
  191. $data = ''; 
  192. $data = preg_split('/\r?\n/', $data, -1, PREG_SPLIT_NO_EMPTY); 
  193.  
  194. for ($i = 0; $i < count($data); $i++) { 
  195.  
  196. $capa=''; 
  197. if (preg_match('/^([a-z, \-]+)( ((.*))|$)$/i', $data[$i], $matches)) { 
  198.  
  199. $capa=strtolower($matches[1]); 
  200. switch ($capa) { 
  201. case 'implementation': 
  202. $this->_capability['implementation'] = $matches[3]; 
  203. break; 
  204. case 'sasl': 
  205. $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); 
  206. break; 
  207. default : 
  208. $this->_capability[$capa] = $matches[2]; 
  209. break; 
  210.  
  211.  
  212.  
  213.  
  214. /** 
  215. * Returns the name of the best authentication method that the server 
  216. * has advertised. 
  217. * @param string if !=null, authenticate with this method ($userMethod). 
  218. * @return mixed Returns a string containing the name of the best 
  219. * supported authentication method or a PEAR_Error object 
  220. * if a failure condition is encountered. 
  221. * @access private 
  222. * @since 1.0 
  223. */ 
  224. function _getBestAuthMethod($userMethod = null) 
  225.  
  226. /** 
  227. return 'USER'; 
  228. return 'APOP'; 
  229. return 'DIGEST-MD5'; 
  230. return 'CRAM-MD5'; 
  231. */ 
  232.  
  233.  
  234. $this->_parseCapability(); 
  235.  
  236. //unset($this->_capability['sasl']); 
  237.  
  238. if( isset($this->_capability['sasl']) ) { 
  239. $serverMethods=$this->_capability['sasl']; 
  240. }else{ 
  241. $serverMethods=array('USER'); 
  242. // Check for timestamp before attempting APOP 
  243. if ($this->_timestamp != null) 
  244. $serverMethods[] = 'APOP'; 
  245.  
  246. if($userMethod !== null && $userMethod !== true ) { 
  247. $methods = array(); 
  248. $methods[] = $userMethod; 
  249. return $userMethod; 
  250. }else{ 
  251. $methods = $this->supportedAuthMethods; 
  252.  
  253. if( ($methods != null) && ($serverMethods != null)) { 
  254.  
  255. foreach ( $methods as $method ) { 
  256.  
  257. if ( in_array( $method , $serverMethods ) ) { 
  258. return $method; 
  259. $serverMethods=implode(', ' , $serverMethods ); 
  260. $myMethods=implode(', ' , $this->supportedAuthMethods); 
  261. return $this->_raiseError("$method NOT supported authentication method!. This server " . 
  262. "supports these methods: $serverMethods, but I support $myMethods"); 
  263. }else{ 
  264. return $this->_raiseError("This server don't support any Auth methods"); 
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271. /** Handles the authentication using any known method 
  272. * @param string The userid to authenticate as. 
  273. * @param string The password to authenticate with. 
  274. * @param string The method to use ( if $usermethod == '' then the class chooses the best method (the stronger is the best ) ) 
  275. * @return mixed string or PEAR_Error 
  276. * @access private 
  277. * @since 1.0 
  278. */ 
  279. function _cmdAuthenticate($uid , $pwd , $userMethod = null ) 
  280.  
  281.  
  282. if ( $this->PEAR->isError( $method = $this->_getBestAuthMethod($userMethod) ) ) { 
  283. return $method; 
  284.  
  285. switch ($method) { 
  286. case 'DIGEST-MD5': 
  287. $result = $this->_authDigest_MD5( $uid , $pwd ); 
  288. break; 
  289. case 'CRAM-MD5': 
  290. $result = $this->_authCRAM_MD5( $uid , $pwd ); 
  291. break; 
  292. case 'LOGIN': 
  293. $result = $this->_authLOGIN( $uid , $pwd ); 
  294. break; 
  295. case 'PLAIN': 
  296. $result = $this->_authPLAIN( $uid , $pwd ); 
  297. break; 
  298. case 'APOP': 
  299. $result = $this->_cmdApop( $uid , $pwd ); 
  300. // if APOP fails fallback to USER auth 
  301. if( $this->PEAR->isError( $result ) ) { 
  302. //echo "APOP FAILED!!!\n"; 
  303. $result=$this->_authUSER( $uid , $pwd ); 
  304. break; 
  305. case 'USER': 
  306. $result = $this->_authUSER( $uid , $pwd ); 
  307. break; 
  308.  
  309.  
  310. default : 
  311. $result = $this->_raiseError( "$method is not a supported authentication method" ); 
  312. break; 
  313. return $result; 
  314.  
  315.  
  316.  
  317.  
  318. /** Authenticates the user using the USER-PASS method. 
  319. * @param string The userid to authenticate as. 
  320. * @param string The password to authenticate with. 
  321. * @return mixed true on success or PEAR_Error on failure 
  322. * @access private 
  323. * @since 1.0 
  324. */ 
  325. function _authUSER($user, $pass ) 
  326. if ( $this->PEAR->isError($ret=$this->_cmdUser($user) ) ) { 
  327. return $ret; 
  328. if ( $this->PEAR->isError($ret=$this->_cmdPass($pass) ) ) { 
  329. return $ret; 
  330. return true; 
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339. /** Authenticates the user using the PLAIN method. 
  340. * @param string The userid to authenticate as. 
  341. * @param string The password to authenticate with. 
  342. * @return array Returns an array containing the response 
  343. * @access private 
  344. * @since 1.0 
  345. */ 
  346. function _authPLAIN($user, $pass ) 
  347. $cmd=sprintf('AUTH PLAIN %s', base64_encode( chr(0) . $user . chr(0) . $pass ) ); 
  348.  
  349. if ( $this->PEAR->isError( $ret = $this->_send($cmd) ) ) { 
  350. return $ret; 
  351. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  352. return $challenge; 
  353. if( $this->PEAR->isError($ret=$this->_checkResponse($challenge) )) { 
  354. return $ret; 
  355.  
  356. return true; 
  357.  
  358.  
  359.  
  360. /** Authenticates the user using the PLAIN method. 
  361. * @param string The userid to authenticate as. 
  362. * @param string The password to authenticate with. 
  363. * @return array Returns an array containing the response 
  364. * @access private 
  365. * @since 1.0 
  366. */ 
  367. function _authLOGIN($user, $pass ) 
  368. $this->_send('AUTH LOGIN'); 
  369.  
  370. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  371. return $challenge; 
  372. if( $this->PEAR->isError($ret=$this->_checkResponse($challenge) )) { 
  373. return $ret; 
  374.  
  375.  
  376. if ( $this->PEAR->isError( $ret = $this->_send(sprintf('%s', base64_encode($user))) ) ) { 
  377. return $ret; 
  378.  
  379. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  380. return $challenge; 
  381. if( $this->PEAR->isError($ret=$this->_checkResponse($challenge) )) { 
  382. return $ret; 
  383.  
  384. if ( $this->PEAR->isError( $ret = $this->_send(sprintf('%s', base64_encode($pass))) ) ) { 
  385. return $ret; 
  386.  
  387. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  388. return $challenge; 
  389. return $this->_checkResponse($challenge); 
  390.  
  391.  
  392.  
  393.  
  394.  
  395. /** Authenticates the user using the CRAM-MD5 method. 
  396. * @param string The userid to authenticate as. 
  397. * @param string The password to authenticate with. 
  398. * @return array Returns an array containing the response 
  399. * @access private 
  400. * @since 1.0 
  401. */ 
  402. function _authCRAM_MD5($uid, $pwd ) 
  403. if ( $this->PEAR->isError( $ret = $this->_send( 'AUTH CRAM-MD5' ) ) ) { 
  404. return $ret; 
  405.  
  406. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  407. return $challenge; 
  408. if( $this->PEAR->isError($ret=$this->_checkResponse($challenge) )) { 
  409. return $ret; 
  410.  
  411. // remove '+ ' 
  412.  
  413. $challenge=substr($challenge, 2); 
  414.  
  415. $challenge = base64_decode( $challenge ); 
  416.  
  417. $cram = &Auth_SASL::factory('crammd5'); 
  418. $auth_str = base64_encode( $cram->getResponse( $uid , $pwd , $challenge ) ); 
  419.  
  420.  
  421. if ( $this->PEAR->isError($error = $this->_send( $auth_str ) ) ) { 
  422. return $error; 
  423. if ( $this->PEAR->isError( $ret = $this->_recvLn() ) ) { 
  424. return $ret; 
  425. //echo "RET:$ret\n"; 
  426. return $this->_checkResponse($ret); 
  427.  
  428.  
  429.  
  430. /** Authenticates the user using the DIGEST-MD5 method. 
  431. * @param string The userid to authenticate as. 
  432. * @param string The password to authenticate with. 
  433. * @param string The efective user 
  434. * @return array Returns an array containing the response 
  435. * @access private 
  436. * @since 1.0 
  437. */ 
  438. function _authDigest_MD5($uid, $pwd) 
  439. if ( $this->PEAR->isError( $ret = $this->_send( 'AUTH DIGEST-MD5' ) ) ) { 
  440. return $ret; 
  441.  
  442. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  443. return $challenge; 
  444. if( $this->PEAR->isError($ret=$this->_checkResponse($challenge) )) { 
  445. return $ret; 
  446.  
  447. // remove '+ ' 
  448. $challenge=substr($challenge, 2); 
  449.  
  450. $challenge = base64_decode( $challenge ); 
  451. $digest = &Auth_SASL::factory('digestmd5'); 
  452. $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, "localhost", "pop3" )); 
  453.  
  454. if ( $this->PEAR->isError($error = $this->_send( $auth_str ) ) ) { 
  455. return $error; 
  456.  
  457. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  458. return $challenge; 
  459. if( $this->PEAR->isError($ret=$this->_checkResponse($challenge) )) { 
  460. return $ret; 
  461. /** 
  462. * We don't use the protocol's third step because POP3 doesn't allow 
  463. * subsequent authentication, so we just silently ignore it. 
  464. */ 
  465.  
  466. if ( $this->PEAR->isError( $challenge = $this->_send("\r\n") ) ) { 
  467. return $challenge ; 
  468.  
  469. if ( $this->PEAR->isError( $challenge = $this->_recvLn() ) ) { 
  470. return $challenge; 
  471.  
  472. return $this->_checkResponse($challenge); 
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485. /** 
  486. * Sends the APOP command 
  487. * @param $user Username to send 
  488. * @param $pass Password to send 
  489. * @return bool Success/Failure 
  490. */ 
  491. function _cmdApop($user, $pass) 
  492. if ($this->_state == NET_POP3_STATE_AUTHORISATION) { 
  493.  
  494. if (!empty($this->_timestamp)) { 
  495. if($this->PEAR->isError($data = $this->_sendCmd('APOP ' . $user . ' ' . md5($this->_timestamp . $pass)) ) ) { 
  496. return $data; 
  497. $this->_state = NET_POP3_STATE_TRANSACTION; 
  498. return true; 
  499. return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State1'); 
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515. /** 
  516. * Returns the raw headers of the specified message. 
  517. * @param integer $msg_id Message number 
  518. * @return mixed Either raw headers or false on error 
  519. */ 
  520. function getRawHeaders($msg_id) 
  521. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  522. return $this->_cmdTop($msg_id, 0); 
  523.  
  524. return false; 
  525.  
  526. /** 
  527. * Returns the headers of the specified message in an 
  528. * associative array. Array keys are the header names, array 
  529. * values are the header values. In the case of multiple headers 
  530. * having the same names, eg Received:, the array value will be 
  531. * an indexed array of all the header values. 
  532. * @param integer $msg_id Message number 
  533. * @return mixed Either array of headers or false on error 
  534. */ 
  535. function getParsedHeaders($msg_id) 
  536. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  537.  
  538. $raw_headers = rtrim($this->getRawHeaders($msg_id)); 
  539.  
  540. $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers 
  541. $raw_headers = explode("\r\n", $raw_headers); 
  542. foreach ($raw_headers as $value) { 
  543. $name = strtolower(substr($value, 0, $pos = strpos($value, ':'))); 
  544. $value = ltrim(substr($value, $pos + 1)); 
  545. if (isset($headers[$name]) AND is_array($headers[$name])) { 
  546. $headers[$name][] = $value; 
  547. } elseif (isset($headers[$name])) { 
  548. $headers[$name] = array($headers[$name], $value); 
  549. } else { 
  550. $headers[$name] = $value; 
  551.  
  552. return $headers; 
  553.  
  554. return false; 
  555.  
  556. /** 
  557. * Returns the body of the message with given message number. 
  558. * @param integer $msg_id Message number 
  559. * @return mixed Either message body or false on error 
  560. */ 
  561. function getBody($msg_id) 
  562. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  563. $msg = $this->_cmdRetr($msg_id); 
  564. return substr($msg, strpos($msg, "\r\n\r\n")+4); 
  565.  
  566. return false; 
  567.  
  568. /** 
  569. * Returns the entire message with given message number. 
  570. * @param integer $msg_id Message number 
  571. * @return mixed Either entire message or false on error 
  572. */ 
  573. function getMsg($msg_id) 
  574. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  575. return $this->_cmdRetr($msg_id); 
  576.  
  577. return false; 
  578.  
  579. /** 
  580. * Returns the size of the maildrop 
  581. * @return mixed Either size of maildrop or false on error 
  582. */ 
  583. function getSize() 
  584. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  585. if (isset($this->_maildrop['size'])) { 
  586. return $this->_maildrop['size']; 
  587. } else { 
  588. list(, $size) = $this->_cmdStat(); 
  589. return $size; 
  590.  
  591. return false; 
  592.  
  593. /** 
  594. * Returns number of messages in this maildrop 
  595. * @return mixed Either number of messages or false on error 
  596. */ 
  597. function numMsg() 
  598. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  599. if (isset($this->_maildrop['num_msg'])) { 
  600. return $this->_maildrop['num_msg']; 
  601. } else { 
  602. list($num_msg, ) = $this->_cmdStat(); 
  603. return $num_msg; 
  604.  
  605. return false; 
  606.  
  607. /** 
  608. * Marks a message for deletion. Only will be deleted if the 
  609. * disconnect() method is called. 
  610. * @param integer $msg_id Message to delete 
  611. * @return bool Success/Failure 
  612. */ 
  613. function deleteMsg($msg_id) 
  614. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  615. return $this->_cmdDele($msg_id); 
  616.  
  617. return false; 
  618.  
  619. /** 
  620. * Combination of LIST/UIDL commands, returns an array 
  621. * of data 
  622. * @param integer $msg_id Optional message number 
  623. * @return mixed Array of data or false on error 
  624. */ 
  625. function getListing($msg_id = null) 
  626.  
  627. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  628. if (!isset($msg_id)) { 
  629.  
  630. $list=array(); 
  631. if ($list = $this->_cmdList()) { 
  632. if ($uidl = $this->_cmdUidl()) { 
  633. foreach ($uidl as $i => $value) { 
  634. $list[$i]['uidl'] = $value['uidl']; 
  635. return $list; 
  636. }else{ 
  637. return array(); 
  638. } else { 
  639. if ($list = $this->_cmdList($msg_id) AND $uidl = $this->_cmdUidl($msg_id)) { 
  640. return array_merge($list, $uidl); 
  641.  
  642. return false; 
  643.  
  644. /** 
  645. * Sends the USER command 
  646. * @param string $user Username to send 
  647. * @return bool Success/Failure 
  648. */ 
  649. function _cmdUser($user) 
  650. if ($this->_state == NET_POP3_STATE_AUTHORISATION) { 
  651. return $this->_sendCmd('USER ' . $user); 
  652. return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State'); 
  653.  
  654.  
  655. /** 
  656. * Sends the PASS command 
  657. * @param string $pass Password to send 
  658. * @return bool Success/Failure 
  659. */ 
  660. function _cmdPass($pass) 
  661. if ($this->_state == NET_POP3_STATE_AUTHORISATION) { 
  662. return $this->_sendCmd('PASS ' . $pass); 
  663. return $this->_raiseError('Not In NET_POP3_STATE_AUTHORISATION State'); 
  664.  
  665.  
  666. /** 
  667. * Sends the STAT command 
  668. * @return mixed Indexed array of number of messages and 
  669. * maildrop size, or false on error. 
  670. */ 
  671. function _cmdStat() 
  672. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  673. if(!$this->PEAR->isError($data = $this->_sendCmd('STAT'))) { 
  674. sscanf($data, '+OK %d %d', $msg_num, $size); 
  675. $this->_maildrop['num_msg'] = $msg_num; 
  676. $this->_maildrop['size'] = $size; 
  677.  
  678. return array($msg_num, $size); 
  679. return false; 
  680.  
  681.  
  682. /** 
  683. * Sends the LIST command 
  684. * @param integer $msg_id Optional message number 
  685. * @return mixed Indexed array of msg_id/msg size or 
  686. * false on error 
  687. */ 
  688. function _cmdList($msg_id = null) 
  689. $return=array(); 
  690. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  691. if (!isset($msg_id)) { 
  692. if(!$this->PEAR->isError($data = $this->_sendCmd('LIST') )) { 
  693. $data = $this->_getMultiline(); 
  694. $data = explode("\r\n", $data); 
  695. foreach ($data as $line) { 
  696. if($line !='') { 
  697. sscanf($line, '%s %s', $msg_id, $size); 
  698. $return[] = array('msg_id' => $msg_id, 'size' => $size); 
  699. return $return; 
  700. } else { 
  701. if(!$this->PEAR->isError($data = $this->_sendCmd('LIST ' . $msg_id))) { 
  702. if($data!='') { 
  703. sscanf($data, '+OK %d %d', $msg_id, $size); 
  704. return array('msg_id' => $msg_id, 'size' => $size); 
  705. return array(); 
  706.  
  707.  
  708. return false; 
  709.  
  710.  
  711. /** 
  712. * Sends the RETR command 
  713. * @param integer $msg_id The message number to retrieve 
  714. * @return mixed The message or false on error 
  715. */ 
  716. function _cmdRetr($msg_id) 
  717. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  718. if(!$this->PEAR->isError($data = $this->_sendCmd('RETR ' . $msg_id) )) { 
  719. $data = $this->_getMultiline(); 
  720. return $data; 
  721.  
  722. return false; 
  723.  
  724.  
  725. /** 
  726. * Sends the DELE command 
  727. * @param integer $msg_id Message number to mark as deleted 
  728. * @return bool Success/Failure 
  729. */ 
  730. function _cmdDele($msg_id) 
  731. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  732. return $this->_sendCmd('DELE ' . $msg_id); 
  733.  
  734. return false; 
  735.  
  736.  
  737. /** 
  738. * Sends the NOOP command 
  739. * @return bool Success/Failure 
  740. */ 
  741. function _cmdNoop() 
  742. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  743. if(!$this->PEAR->isError($data = $this->_sendCmd('NOOP'))) { 
  744. return true; 
  745.  
  746. return false; 
  747.  
  748. /** 
  749. * Sends the RSET command 
  750. * @return bool Success/Failure 
  751. */ 
  752. function _cmdRset() 
  753. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  754. if(!$this->PEAR->isError($data = $this->_sendCmd('RSET'))) { 
  755. return true; 
  756.  
  757. return false; 
  758.  
  759. /** 
  760. * Sends the QUIT command 
  761. * @return bool Success/Failure 
  762. */ 
  763. function _cmdQuit() 
  764. $data = $this->_sendCmd('QUIT'); 
  765. $this->_state = NET_POP3_STATE_DISCONNECTED; 
  766. $this->_socket->disconnect(); 
  767.  
  768. return (bool)$data; 
  769.  
  770.  
  771. /** 
  772. * Sends the TOP command 
  773. * @param integer $msg_id Message number 
  774. * @param integer $num_lines Number of lines to retrieve 
  775. * @return mixed Message data or false on error 
  776. */ 
  777. function _cmdTop($msg_id, $num_lines) 
  778. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  779.  
  780. if(!$this->PEAR->isError($data = $this->_sendCmd('TOP ' . $msg_id . ' ' . $num_lines))) { 
  781. return $this->_getMultiline(); 
  782.  
  783. return false; 
  784.  
  785. /** 
  786. * Sends the UIDL command 
  787. * @param integer $msg_id Message number 
  788. * @return mixed indexed array of msg_id/uidl or false on error 
  789. */ 
  790. function _cmdUidl($msg_id = null) 
  791. if ($this->_state == NET_POP3_STATE_TRANSACTION) { 
  792.  
  793. if (!isset($msg_id)) { 
  794. if(!$this->PEAR->isError($data = $this->_sendCmd('UIDL') )) { 
  795. $data = $this->_getMultiline(); 
  796. $data = explode("\r\n", $data); 
  797. foreach ($data as $line) { 
  798. sscanf($line, '%d %s', $msg_id, $uidl); 
  799. $return[] = array('msg_id' => $msg_id, 'uidl' => $uidl); 
  800.  
  801. return $return; 
  802. } else { 
  803.  
  804. $data = $this->_sendCmd('UIDL ' . $msg_id); 
  805. sscanf($data, '+OK %d %s', $msg_id, $uidl); 
  806. return array('msg_id' => $msg_id, 'uidl' => $uidl); 
  807.  
  808. return false; 
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818. /** 
  819. * Sends a command, checks the reponse, and 
  820. * if good returns the reponse, other wise 
  821. * returns false. 
  822. * @param string $cmd Command to send (\r\n will be appended) 
  823. * @return mixed First line of response if successful, otherwise false 
  824. */ 
  825. function _sendCmd($cmd) 
  826. if ($this->PEAR->isError($result = $this->_send($cmd) )) { 
  827. return $result ; 
  828.  
  829. if ($this->PEAR->isError($data = $this->_recvLn() )) { 
  830. return $data; 
  831.  
  832. if ( strtoupper(substr($data, 0, 3)) == '+OK') { 
  833. return $data; 
  834.  
  835. if($cmd == 'CAPA') { 
  836. if($this->_debug) { 
  837. echo $data.' FROM request : CAPA'; 
  838. return false; 
  839.  
  840. return $this->_raiseError($data); 
  841.  
  842. /** 
  843. * Reads a multiline reponse and returns the data 
  844. * @return string The reponse. 
  845. */ 
  846. function _getMultiline() 
  847. $data = ''; 
  848. while(!$this->PEAR->isError($tmp = $this->_recvLn() ) ) { 
  849. if($tmp == '.') { 
  850. return substr($data, 0, -2); 
  851. if (substr($tmp, 0, 2) == '..') { 
  852. $tmp = substr($tmp, 1); 
  853. $data .= $tmp . "\r\n"; 
  854. return substr($data, 0, -2); 
  855.  
  856.  
  857. /** 
  858. * Sets the bebug state 
  859. * @param bool $debug 
  860. * @access public 
  861. * @return void 
  862. */ 
  863. function setDebug($debug=true) 
  864. $this->_debug=$debug; 
  865.  
  866.  
  867.  
  868.  
  869.  
  870. /** 
  871. * Send the given string of data to the server. 
  872. * @param string $data The string of data to send. 
  873. * @return mixed True on success or a PEAR_Error object on failure. 
  874. * @access private 
  875. * @since 1.0 
  876. */ 
  877. function _send($data) 
  878. if ($this->_debug) { 
  879. echo "C: $data\n"; 
  880.  
  881. if ($this->PEAR->isError($error = $this->_socket->writeLine($data))) { 
  882. return $this->_raiseError('Failed to write to socket: ' . $error->getMessage()); 
  883. return true; 
  884.  
  885.  
  886.  
  887. /** 
  888. * Receive the given string of data from the server. 
  889. * @return mixed a line of response on success or a PEAR_Error object on failure. 
  890. * @access private 
  891. * @since 1.0 
  892. */ 
  893. function _recvLn() 
  894. if ($this->PEAR->isError( $lastline = $this->_socket->readLine( 8192 ) ) ) { 
  895. return $this->_raiseError('Failed to write to socket: ' . $this->lastline->getMessage() ); 
  896. if($this->_debug) { 
  897. // S: means this data was sent by the POP3 Server 
  898. echo "S:$lastline\n" ; 
  899. return $lastline; 
  900.  
  901. /** 
  902. * Checks de server Response 
  903. * @param string $response the response 
  904. * @return mixed true on success or a PEAR_Error object on failure. 
  905. * @access private 
  906. * @since 1.3.3 
  907. */ 
  908.  
  909. function _checkResponse($response) 
  910. if (@substr(strtoupper($response), 0, 3) == '+OK') { 
  911. return true; 
  912. }else{ 
  913. if (@substr(strtoupper($response), 0, 4) == '-ERR') { 
  914. return $this->_raiseError($response); 
  915. }else{ 
  916. if (@substr(strtoupper($response), 0, 2) == '+ ') { 
  917. return true; 
  918.  
  919. return $this->_raiseError("Unknown Response ($response)"); 
  920.  
  921.  
  922.