PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Core/Emails/Network/Pop3Socket.php

http://github.com/infinitas/infinitas
PHP | 273 lines | 142 code | 44 blank | 87 comment | 23 complexity | 46aaba8e037000d5b8bca29c83992e6a MD5 | raw file
  1. <?php
  2. App::uses('EmailSocket', 'Emails.Network');
  3. /**
  4. * A pop3 driver for the email socket to recive emails without the php-imap extention
  5. *
  6. * This class implements the methods of the pop3 protocol using the EmailSocket
  7. * class to do the communication between the servers. See the links for more
  8. * information about the pop3 protocol
  9. *
  10. * @link http://www.networksorcery.com/enp/protocol/pop.htm
  11. * @link http://tools.ietf.org/html/rfc1939
  12. * @link http://techhelp.santovec.us/pop3telnet.htm
  13. */
  14. class Pop3Socket extends EmailSocket {
  15. /**
  16. * The pop3 class constructor
  17. *
  18. * You can set connection details in a number of ways. First being passing
  19. * an array of connection details to the constructor. The other method
  20. * is using Pop3Socket::set(), finally you can set the properties through
  21. * Pop3Socket::__set() by doing $Pop3Socket->{$name} = $value
  22. *
  23. * If parent is not called the connection to the server will not be set
  24. * up automagically.
  25. *
  26. * @param array $connection the connection details
  27. *
  28. * @return void
  29. */
  30. public function __construct($connection = array()) {
  31. parent::__construct($connection);
  32. if (!empty($connection) && is_array($connection)) {
  33. $this->set($connection);
  34. }
  35. }
  36. /**
  37. * @copydoc EmailSocket::login()
  38. */
  39. public function login() {
  40. if (!parent::login()) {
  41. return false;
  42. }
  43. if (!$this->write(sprintf('USER %s', $this->config['username']), 'isOk')) {
  44. $this->error(sprintf('There seems to be a problem with the username (%s)', $this->config['username']));
  45. return false;
  46. }
  47. if (!$this->write(sprintf('PASS %s', $this->config['password']), 'isOk')) {
  48. $this->error(sprintf('The password seems invalid for this user (%s)', $this->config['username']));
  49. return false;
  50. }
  51. $this->_getStats();
  52. $this->_getList();
  53. return true;
  54. }
  55. /**
  56. * @copydoc EmailSocket::logout()
  57. */
  58. public function logout() {
  59. if (!$this->Socket->isConnected()) {
  60. $this->_errors[] = 'Can not logout, no connection';
  61. return true;
  62. }
  63. $quit = $this->write('QUIT', 'isOk');
  64. if (!$quit) {
  65. $this->_errors[] = 'Could not log out';
  66. }
  67. return $quit;
  68. }
  69. /**
  70. * @copydoc EmailSocket::_getStats()
  71. */
  72. protected function _getStats() {
  73. $stats = $this->write('STAT', 'cleanData');
  74. $stats = explode(' ', current(array_keys($stats)));
  75. if ($stats[0] != '+OK') {
  76. $this->_errors[] = 'Could not get stats';
  77. }
  78. if (isset($stats[1])) {
  79. $this->mailStats['totalCount'] = $stats[1];
  80. }
  81. if (isset($stats[2])) {
  82. $this->mailStats['totalSize'] = $stats[2];
  83. }
  84. unset($stats);
  85. if ($this->mailStats['totalSize'] > 0) {
  86. $this->mailStats['totalSizeReadable'] = convert($this->mailStats['totalSize']);
  87. }
  88. return true;
  89. }
  90. /**
  91. * @copydoc EmailSocket::_getList()
  92. */
  93. protected function _getList() {
  94. $list = $this->write('LIST ', 'cleanData', 1024);
  95. /**
  96. * @todo getting big lists causes problems
  97. *
  98. $mailSize = parent::_getSize($list) || parent::_isOk($list);
  99. if (!$mailSize) {
  100. unset($list);
  101. return array();
  102. }
  103. $mailSize = is_int($mailSize) ? $mailSize : 1024;
  104. $list = $list . $this->write('LIST ', null, $mailSize);
  105. */
  106. if (!$list || empty($list)) {
  107. return false;
  108. }
  109. $uids = $this->_getUid();
  110. $this->mailList = array();
  111. foreach ($list[current(array_keys($list))] as $item) {
  112. $parts = explode(' ', $item);
  113. if (count($parts) == 2 && $parts[0] > 0 && !empty($parts[1])) {
  114. $uuid = (isset($uids[$parts[0]])) ? $uids[$parts[0]] : null;
  115. $listItem = array(
  116. 'id' => null,
  117. 'message_number' => $parts[0],
  118. 'size' => $parts[1],
  119. 'sizeReadable' => convert($parts[1]),
  120. 'uid' => $uuid
  121. );
  122. $listItem['id'] = sha1(serialize($listItem));
  123. $this->mailList[$parts[0]] = $listItem;
  124. }
  125. }
  126. unset($list, $parts);
  127. return true;
  128. }
  129. protected function _getUid($messageId = null) {
  130. $return = array();
  131. $data = $this->write('UIDL');
  132. if ($this->_isOk($data)) {
  133. $data = current($this->_cleanData($data));
  134. foreach ($data as $_data) {
  135. $_data = explode(' ', $_data);
  136. $return[$_data[0]] = $_data[1];
  137. }
  138. }
  139. unset($data, $_data);
  140. return $return;
  141. }
  142. /**
  143. * @copydoc EmailSocket::_getCapabilities()
  144. *
  145. * This is a list of the capabilities for a pop3 mail server. This data
  146. * is used to determin how the communication will be done.
  147. */
  148. protected function _getCapabilities() {
  149. $cache = $this->readCache('capabilities');
  150. if ($cache) {
  151. $this->_capabilities = $cache;
  152. return true;
  153. }
  154. $capabilities = $this->write('CAPA', 'cleanData');
  155. if (empty($capabilities)) {
  156. return false;
  157. }
  158. foreach (current($capabilities) as $capability) {
  159. $parts = explode(' ', $capability, 2);
  160. switch($capability) {
  161. // The TOP capability indicates the optional TOP command is available.
  162. case 'TOP':
  163. // The USER capability indicates that the USER and PASS commands are supported,
  164. // although they may not be available to all users.
  165. case 'USER':
  166. // The SASL capability indicates that the AUTH command is available and that it
  167. // supports an optional base64 encoded second argument for an initial client
  168. // response as described in the SASL specification.
  169. case 'SASL':
  170. // any response text that begins with [ is an extended response code
  171. case 'RESP-CODES':
  172. // The PIPELINING capability indicates the server is capable of accepting multiple
  173. // commands at a time; the client does not have to wait for the response to a command
  174. // before issuing a subsequent command.
  175. case 'PIPELINING':
  176. // The UIDL capability indicates that the optional UIDL command is supported.
  177. case 'UIDL':
  178. case 'STLS':
  179. $this->_capabilities[$parts[0]] = 1;
  180. break;
  181. // time to pass before re logging on
  182. case 'LOGIN-DELAY':
  183. // The argument to the EXPIRE capability indicates the minimum server retention period,
  184. // in days, for messages on the server. EXPIRE 0 means you can not store on the server.
  185. // EXPIRE NEVER asserts that the server does not delete messages.
  186. case 'EXPIRE':
  187. // It is often useful to identify an implementation of a particular server
  188. case 'IMPLEMENTATION':
  189. $this->_capabilities[$parts[0]] = isset($parts[1]) && !empty($parts[1]) ? $parts[1] : 1;
  190. break;
  191. }
  192. }
  193. return $this->writeCache('capabilities', $this->_capabilities);
  194. }
  195. /**
  196. * @copydoc EmailSocket::noop()
  197. */
  198. public function noop() {
  199. return $this->write('NOOP', 'isOk');
  200. }
  201. /**
  202. * @copydoc EmailSocket::undoDeletes()
  203. */
  204. public function undoDeletes() {
  205. return $this->write('RSET', 'isOk');
  206. }
  207. public function getMail($id) {
  208. $mail = $this->write('RETR ' . $id, null, $this->mailList[$id]['size']);
  209. if (!parent::_isOk($mail)) {
  210. unset($mail);
  211. return array();
  212. }
  213. $mail = array_merge($this->mailList[$id], $this->ParseMail->parse($mail));
  214. return $mail;
  215. }
  216. /**
  217. * @copydoc EmailSocket::_getMailboxes()
  218. *
  219. * pop3 does not have "mailboxes" like IMAP so just return null
  220. */
  221. protected function _getMailboxes($ref = '', $wildcard = '*') {
  222. return null;
  223. }
  224. }