PageRenderTime 46ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/concrete/libraries/3rdparty/Zend/Mail/Protocol/Pop3.php

https://bitbucket.org/seanom/concrete5
PHP | 472 lines | 213 code | 65 blank | 194 comment | 35 complexity | efeff3bbd8e9a20aa29a4ed085a2484a MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Mail
  17. * @subpackage Protocol
  18. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Pop3.php 23775 2011-03-01 17:25:24Z ralph $
  21. */
  22. /**
  23. * @category Zend
  24. * @package Zend_Mail
  25. * @subpackage Protocol
  26. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  27. * @license http://framework.zend.com/license/new-bsd New BSD License
  28. */
  29. class Zend_Mail_Protocol_Pop3
  30. {
  31. /**
  32. * Default timeout in seconds for initiating session
  33. */
  34. const TIMEOUT_CONNECTION = 30;
  35. /**
  36. * saves if server supports top
  37. * @var null|bool
  38. */
  39. public $hasTop = null;
  40. /**
  41. * socket to pop3
  42. * @var null|resource
  43. */
  44. protected $_socket;
  45. /**
  46. * greeting timestamp for apop
  47. * @var null|string
  48. */
  49. protected $_timestamp;
  50. /**
  51. * Public constructor
  52. *
  53. * @param string $host hostname or IP address of POP3 server, if given connect() is called
  54. * @param int|null $port port of POP3 server, null for default (110 or 995 for ssl)
  55. * @param bool|string $ssl use ssl? 'SSL', 'TLS' or false
  56. * @throws Zend_Mail_Protocol_Exception
  57. */
  58. public function __construct($host = '', $port = null, $ssl = false)
  59. {
  60. if ($host) {
  61. $this->connect($host, $port, $ssl);
  62. }
  63. }
  64. /**
  65. * Public destructor
  66. */
  67. public function __destruct()
  68. {
  69. $this->logout();
  70. }
  71. /**
  72. * Open connection to POP3 server
  73. *
  74. * @param string $host hostname or IP address of POP3 server
  75. * @param int|null $port of POP3 server, default is 110 (995 for ssl)
  76. * @param string|bool $ssl use 'SSL', 'TLS' or false
  77. * @return string welcome message
  78. * @throws Zend_Mail_Protocol_Exception
  79. */
  80. public function connect($host, $port = null, $ssl = false)
  81. {
  82. if ($ssl == 'SSL') {
  83. $host = 'ssl://' . $host;
  84. }
  85. if ($port === null) {
  86. $port = $ssl == 'SSL' ? 995 : 110;
  87. }
  88. $errno = 0;
  89. $errstr = '';
  90. $this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
  91. if (!$this->_socket) {
  92. /**
  93. * @see Zend_Mail_Protocol_Exception
  94. */
  95. require_once 'Zend/Mail/Protocol/Exception.php';
  96. throw new Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
  97. ' (errno = ' . $errno . ' )');
  98. }
  99. $welcome = $this->readResponse();
  100. strtok($welcome, '<');
  101. $this->_timestamp = strtok('>');
  102. if (!strpos($this->_timestamp, '@')) {
  103. $this->_timestamp = null;
  104. } else {
  105. $this->_timestamp = '<' . $this->_timestamp . '>';
  106. }
  107. if ($ssl === 'TLS') {
  108. $this->request('STLS');
  109. $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
  110. if (!$result) {
  111. /**
  112. * @see Zend_Mail_Protocol_Exception
  113. */
  114. require_once 'Zend/Mail/Protocol/Exception.php';
  115. throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
  116. }
  117. }
  118. return $welcome;
  119. }
  120. /**
  121. * Send a request
  122. *
  123. * @param string $request your request without newline
  124. * @return null
  125. * @throws Zend_Mail_Protocol_Exception
  126. */
  127. public function sendRequest($request)
  128. {
  129. $result = @fputs($this->_socket, $request . "\r\n");
  130. if (!$result) {
  131. /**
  132. * @see Zend_Mail_Protocol_Exception
  133. */
  134. require_once 'Zend/Mail/Protocol/Exception.php';
  135. throw new Zend_Mail_Protocol_Exception('send failed - connection closed?');
  136. }
  137. }
  138. /**
  139. * read a response
  140. *
  141. * @param boolean $multiline response has multiple lines and should be read until "<nl>.<nl>"
  142. * @return string response
  143. * @throws Zend_Mail_Protocol_Exception
  144. */
  145. public function readResponse($multiline = false)
  146. {
  147. $result = @fgets($this->_socket);
  148. if (!is_string($result)) {
  149. /**
  150. * @see Zend_Mail_Protocol_Exception
  151. */
  152. require_once 'Zend/Mail/Protocol/Exception.php';
  153. throw new Zend_Mail_Protocol_Exception('read failed - connection closed?');
  154. }
  155. $result = trim($result);
  156. if (strpos($result, ' ')) {
  157. list($status, $message) = explode(' ', $result, 2);
  158. } else {
  159. $status = $result;
  160. $message = '';
  161. }
  162. if ($status != '+OK') {
  163. /**
  164. * @see Zend_Mail_Protocol_Exception
  165. */
  166. require_once 'Zend/Mail/Protocol/Exception.php';
  167. throw new Zend_Mail_Protocol_Exception('last request failed');
  168. }
  169. if ($multiline) {
  170. $message = '';
  171. $line = fgets($this->_socket);
  172. while ($line && rtrim($line, "\r\n") != '.') {
  173. if ($line[0] == '.') {
  174. $line = substr($line, 1);
  175. }
  176. $message .= $line;
  177. $line = fgets($this->_socket);
  178. };
  179. }
  180. return $message;
  181. }
  182. /**
  183. * Send request and get resposne
  184. *
  185. * @see sendRequest(), readResponse()
  186. *
  187. * @param string $request request
  188. * @param bool $multiline multiline response?
  189. * @return string result from readResponse()
  190. * @throws Zend_Mail_Protocol_Exception
  191. */
  192. public function request($request, $multiline = false)
  193. {
  194. $this->sendRequest($request);
  195. return $this->readResponse($multiline);
  196. }
  197. /**
  198. * End communication with POP3 server (also closes socket)
  199. *
  200. * @return null
  201. */
  202. public function logout()
  203. {
  204. if (!$this->_socket) {
  205. return;
  206. }
  207. try {
  208. $this->request('QUIT');
  209. } catch (Zend_Mail_Protocol_Exception $e) {
  210. // ignore error - we're closing the socket anyway
  211. }
  212. fclose($this->_socket);
  213. $this->_socket = null;
  214. }
  215. /**
  216. * Get capabilities from POP3 server
  217. *
  218. * @return array list of capabilities
  219. * @throws Zend_Mail_Protocol_Exception
  220. */
  221. public function capa()
  222. {
  223. $result = $this->request('CAPA', true);
  224. return explode("\n", $result);
  225. }
  226. /**
  227. * Login to POP3 server. Can use APOP
  228. *
  229. * @param string $user username
  230. * @param string $password password
  231. * @param bool $try_apop should APOP be tried?
  232. * @return void
  233. * @throws Zend_Mail_Protocol_Exception
  234. */
  235. public function login($user, $password, $tryApop = true)
  236. {
  237. if ($tryApop && $this->_timestamp) {
  238. try {
  239. $this->request("APOP $user " . md5($this->_timestamp . $password));
  240. return;
  241. } catch (Zend_Mail_Protocol_Exception $e) {
  242. // ignore
  243. }
  244. }
  245. $result = $this->request("USER $user");
  246. $result = $this->request("PASS $password");
  247. }
  248. /**
  249. * Make STAT call for message count and size sum
  250. *
  251. * @param int $messages out parameter with count of messages
  252. * @param int $octets out parameter with size in octects of messages
  253. * @return void
  254. * @throws Zend_Mail_Protocol_Exception
  255. */
  256. public function status(&$messages, &$octets)
  257. {
  258. $messages = 0;
  259. $octets = 0;
  260. $result = $this->request('STAT');
  261. list($messages, $octets) = explode(' ', $result);
  262. }
  263. /**
  264. * Make LIST call for size of message(s)
  265. *
  266. * @param int|null $msgno number of message, null for all
  267. * @return int|array size of given message or list with array(num => size)
  268. * @throws Zend_Mail_Protocol_Exception
  269. */
  270. public function getList($msgno = null)
  271. {
  272. if ($msgno !== null) {
  273. $result = $this->request("LIST $msgno");
  274. list(, $result) = explode(' ', $result);
  275. return (int)$result;
  276. }
  277. $result = $this->request('LIST', true);
  278. $messages = array();
  279. $line = strtok($result, "\n");
  280. while ($line) {
  281. list($no, $size) = explode(' ', trim($line));
  282. $messages[(int)$no] = (int)$size;
  283. $line = strtok("\n");
  284. }
  285. return $messages;
  286. }
  287. /**
  288. * Make UIDL call for getting a uniqueid
  289. *
  290. * @param int|null $msgno number of message, null for all
  291. * @return string|array uniqueid of message or list with array(num => uniqueid)
  292. * @throws Zend_Mail_Protocol_Exception
  293. */
  294. public function uniqueid($msgno = null)
  295. {
  296. if ($msgno !== null) {
  297. $result = $this->request("UIDL $msgno");
  298. list(, $result) = explode(' ', $result);
  299. return $result;
  300. }
  301. $result = $this->request('UIDL', true);
  302. $result = explode("\n", $result);
  303. $messages = array();
  304. foreach ($result as $line) {
  305. if (!$line) {
  306. continue;
  307. }
  308. list($no, $id) = explode(' ', trim($line), 2);
  309. $messages[(int)$no] = $id;
  310. }
  311. return $messages;
  312. }
  313. /**
  314. * Make TOP call for getting headers and maybe some body lines
  315. * This method also sets hasTop - before it it's not known if top is supported
  316. *
  317. * The fallback makes normale RETR call, which retrieves the whole message. Additional
  318. * lines are not removed.
  319. *
  320. * @param int $msgno number of message
  321. * @param int $lines number of wanted body lines (empty line is inserted after header lines)
  322. * @param bool $fallback fallback with full retrieve if top is not supported
  323. * @return string message headers with wanted body lines
  324. * @throws Zend_Mail_Protocol_Exception
  325. */
  326. public function top($msgno, $lines = 0, $fallback = false)
  327. {
  328. if ($this->hasTop === false) {
  329. if ($fallback) {
  330. return $this->retrieve($msgno);
  331. } else {
  332. /**
  333. * @see Zend_Mail_Protocol_Exception
  334. */
  335. require_once 'Zend/Mail/Protocol/Exception.php';
  336. throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
  337. }
  338. }
  339. $this->hasTop = true;
  340. $lines = (!$lines || $lines < 1) ? 0 : (int)$lines;
  341. try {
  342. $result = $this->request("TOP $msgno $lines", true);
  343. } catch (Zend_Mail_Protocol_Exception $e) {
  344. $this->hasTop = false;
  345. if ($fallback) {
  346. $result = $this->retrieve($msgno);
  347. } else {
  348. throw $e;
  349. }
  350. }
  351. return $result;
  352. }
  353. /**
  354. * Make a RETR call for retrieving a full message with headers and body
  355. *
  356. * @deprecated since 1.1.0; this method has a typo - please use retrieve()
  357. * @param int $msgno message number
  358. * @return string message
  359. * @throws Zend_Mail_Protocol_Exception
  360. */
  361. public function retrive($msgno)
  362. {
  363. return $this->retrieve($msgno);
  364. }
  365. /**
  366. * Make a RETR call for retrieving a full message with headers and body
  367. *
  368. * @param int $msgno message number
  369. * @return string message
  370. * @throws Zend_Mail_Protocol_Exception
  371. */
  372. public function retrieve($msgno)
  373. {
  374. $result = $this->request("RETR $msgno", true);
  375. return $result;
  376. }
  377. /**
  378. * Make a NOOP call, maybe needed for keeping the server happy
  379. *
  380. * @return null
  381. * @throws Zend_Mail_Protocol_Exception
  382. */
  383. public function noop()
  384. {
  385. $this->request('NOOP');
  386. }
  387. /**
  388. * Make a DELE count to remove a message
  389. *
  390. * @return null
  391. * @throws Zend_Mail_Protocol_Exception
  392. */
  393. public function delete($msgno)
  394. {
  395. $this->request("DELE $msgno");
  396. }
  397. /**
  398. * Make RSET call, which rollbacks delete requests
  399. *
  400. * @return null
  401. * @throws Zend_Mail_Protocol_Exception
  402. */
  403. public function undelete()
  404. {
  405. $this->request('RSET');
  406. }
  407. }