00001 <?php
00031 class Zend_Mail_Protocol_Pop3
00032 {
00036 const TIMEOUT_CONNECTION = 30;
00037
00042 public $hasTop = null;
00043
00048 protected $_socket;
00049
00054 protected $_timestamp;
00055
00056
00065 public function __construct($host = '', $port = null, $ssl = false)
00066 {
00067 if ($host) {
00068 $this->connect($host, $port, $ssl);
00069 }
00070 }
00071
00072
00076 public function __destruct()
00077 {
00078 $this->logout();
00079 }
00080
00081
00091 public function connect($host, $port = null, $ssl = false)
00092 {
00093 if ($ssl == 'SSL') {
00094 $host = 'ssl://' . $host;
00095 }
00096
00097 if ($port === null) {
00098 $port = $ssl == 'SSL' ? 995 : 110;
00099 }
00100
00101 $errno = 0;
00102 $errstr = '';
00103 $this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
00104 if (!$this->_socket) {
00108 require_once 'Zend/Mail/Protocol/Exception.php';
00109 throw new Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
00110 ' (errno = ' . $errno . ' )');
00111 }
00112
00113 $welcome = $this->readResponse();
00114
00115 strtok($welcome, '<');
00116 $this->_timestamp = strtok('>');
00117 if (!strpos($this->_timestamp, '@')) {
00118 $this->_timestamp = null;
00119 } else {
00120 $this->_timestamp = '<' . $this->_timestamp . '>';
00121 }
00122
00123 if ($ssl === 'TLS') {
00124 $this->request('STLS');
00125 $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
00126 if (!$result) {
00130 require_once 'Zend/Mail/Protocol/Exception.php';
00131 throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
00132 }
00133 }
00134
00135 return $welcome;
00136 }
00137
00138
00146 public function sendRequest($request)
00147 {
00148 $result = @fputs($this->_socket, $request . "\r\n");
00149 if (!$result) {
00153 require_once 'Zend/Mail/Protocol/Exception.php';
00154 throw new Zend_Mail_Protocol_Exception('send failed - connection closed?');
00155 }
00156 }
00157
00158
00166 public function readResponse($multiline = false)
00167 {
00168 $result = @fgets($this->_socket);
00169 if (!is_string($result)) {
00173 require_once 'Zend/Mail/Protocol/Exception.php';
00174 throw new Zend_Mail_Protocol_Exception('read failed - connection closed?');
00175 }
00176
00177 $result = trim($result);
00178 if (strpos($result, ' ')) {
00179 list($status, $message) = explode(' ', $result, 2);
00180 } else {
00181 $status = $result;
00182 $message = '';
00183 }
00184
00185 if ($status != '+OK') {
00189 require_once 'Zend/Mail/Protocol/Exception.php';
00190 throw new Zend_Mail_Protocol_Exception('last request failed');
00191 }
00192
00193 if ($multiline) {
00194 $message = '';
00195 $line = fgets($this->_socket);
00196 while ($line && rtrim($line, "\r\n") != '.') {
00197 if ($line[0] == '.') {
00198 $line = substr($line, 1);
00199 }
00200 $message .= $line;
00201 $line = fgets($this->_socket);
00202 };
00203 }
00204
00205 return $message;
00206 }
00207
00208
00219 public function request($request, $multiline = false)
00220 {
00221 $this->sendRequest($request);
00222 return $this->readResponse($multiline);
00223 }
00224
00225
00231 public function logout()
00232 {
00233 if (!$this->_socket) {
00234 return;
00235 }
00236
00237 try {
00238 $this->request('QUIT');
00239 } catch (Zend_Mail_Protocol_Exception $e) {
00240
00241 }
00242
00243 fclose($this->_socket);
00244 $this->_socket = null;
00245 }
00246
00247
00254 public function capa()
00255 {
00256 $result = $this->request('CAPA', true);
00257 return explode("\n", $result);
00258 }
00259
00260
00270 public function login($user, $password, $tryApop = true)
00271 {
00272 if ($tryApop && $this->_timestamp) {
00273 try {
00274 $this->request("APOP $user " . md5($this->_timestamp . $password));
00275 return;
00276 } catch (Zend_Mail_Protocol_Exception $e) {
00277
00278 }
00279 }
00280
00281 $result = $this->request("USER $user");
00282 $result = $this->request("PASS $password");
00283 }
00284
00285
00294 public function status(&$messages, &$octets)
00295 {
00296 $messages = 0;
00297 $octets = 0;
00298 $result = $this->request('STAT');
00299
00300 list($messages, $octets) = explode(' ', $result);
00301 }
00302
00303
00311 public function getList($msgno = null)
00312 {
00313 if ($msgno !== null) {
00314 $result = $this->request("LIST $msgno");
00315
00316 list(, $result) = explode(' ', $result);
00317 return (int)$result;
00318 }
00319
00320 $result = $this->request('LIST', true);
00321 $messages = array();
00322 $line = strtok($result, "\n");
00323 while ($line) {
00324 list($no, $size) = explode(' ', trim($line));
00325 $messages[(int)$no] = (int)$size;
00326 $line = strtok("\n");
00327 }
00328
00329 return $messages;
00330 }
00331
00332
00340 public function uniqueid($msgno = null)
00341 {
00342 if ($msgno !== null) {
00343 $result = $this->request("UIDL $msgno");
00344
00345 list(, $result) = explode(' ', $result);
00346 return $result;
00347 }
00348
00349 $result = $this->request('UIDL', true);
00350
00351 $result = explode("\n", $result);
00352 $messages = array();
00353 foreach ($result as $line) {
00354 if (!$line) {
00355 continue;
00356 }
00357 list($no, $id) = explode(' ', trim($line), 2);
00358 $messages[(int)$no] = $id;
00359 }
00360
00361 return $messages;
00362
00363 }
00364
00365
00379 public function top($msgno, $lines = 0, $fallback = false)
00380 {
00381 if ($this->hasTop === false) {
00382 if ($fallback) {
00383 return $this->retrieve($msgno);
00384 } else {
00388 require_once 'Zend/Mail/Protocol/Exception.php';
00389 throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
00390 }
00391 }
00392 $this->hasTop = true;
00393
00394 $lines = (!$lines || $lines < 1) ? 0 : (int)$lines;
00395
00396 try {
00397 $result = $this->request("TOP $msgno $lines", true);
00398 } catch (Zend_Mail_Protocol_Exception $e) {
00399 $this->hasTop = false;
00400 if ($fallback) {
00401 $result = $this->retrieve($msgno);
00402 } else {
00403 throw $e;
00404 }
00405 }
00406
00407 return $result;
00408 }
00409
00410
00419 public function retrive($msgno)
00420 {
00421 return $this->retrieve($msgno);
00422 }
00423
00424
00432 public function retrieve($msgno)
00433 {
00434 $result = $this->request("RETR $msgno", true);
00435 return $result;
00436 }
00437
00444 public function noop()
00445 {
00446 $this->request('NOOP');
00447 }
00448
00449
00456 public function delete($msgno)
00457 {
00458 $this->request("DELE $msgno");
00459 }
00460
00461
00468 public function undelete()
00469 {
00470 $this->request('RSET');
00471 }
00472 }