POP3.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. <?php
  2. /**
  3. * PHPMailer POP-Before-SMTP Authentication Class.
  4. * PHP Version 5
  5. * @package PHPMailer
  6. * @link https://github.com/PHPMailer/PHPMailer/
  7. * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  8. * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
  9. * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  10. * @author Brent R. Matzelle (original founder)
  11. * @copyright 2012 - 2014 Marcus Bointon
  12. * @copyright 2010 - 2012 Jim Jagielski
  13. * @copyright 2004 - 2009 Andy Prevost
  14. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  15. * @note This program is distributed in the hope that it will be useful - WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17. * FITNESS FOR A PARTICULAR PURPOSE.
  18. */
  19. /**
  20. * PHPMailer POP-Before-SMTP Authentication Class.
  21. * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
  22. * Does not support APOP.
  23. * @package PHPMailer
  24. * @author Richard Davey (original author) <rich@corephp.co.uk>
  25. * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  26. * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
  27. * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  28. */
  29. namespace Xmail;
  30. class POP3
  31. {
  32. /**
  33. * The POP3 PHPMailer Version number.
  34. * @var string
  35. * @access public
  36. */
  37. public $Version = '5.2.13';
  38. /**
  39. * Default POP3 port number.
  40. * @var integer
  41. * @access public
  42. */
  43. public $POP3_PORT = 110;
  44. /**
  45. * Default timeout in seconds.
  46. * @var integer
  47. * @access public
  48. */
  49. public $POP3_TIMEOUT = 30;
  50. /**
  51. * POP3 Carriage Return + Line Feed.
  52. * @var string
  53. * @access public
  54. * @deprecated Use the constant instead
  55. */
  56. public $CRLF = "\r\n";
  57. /**
  58. * Debug display level.
  59. * Options: 0 = no, 1+ = yes
  60. * @var integer
  61. * @access public
  62. */
  63. public $do_debug = 0;
  64. /**
  65. * POP3 mail server hostname.
  66. * @var string
  67. * @access public
  68. */
  69. public $host;
  70. /**
  71. * POP3 port number.
  72. * @var integer
  73. * @access public
  74. */
  75. public $port;
  76. /**
  77. * POP3 Timeout Value in seconds.
  78. * @var integer
  79. * @access public
  80. */
  81. public $tval;
  82. /**
  83. * POP3 username
  84. * @var string
  85. * @access public
  86. */
  87. public $username;
  88. /**
  89. * POP3 password.
  90. * @var string
  91. * @access public
  92. */
  93. public $password;
  94. /**
  95. * Resource handle for the POP3 connection socket.
  96. * @var resource
  97. * @access protected
  98. */
  99. protected $pop_conn;
  100. /**
  101. * Are we connected?
  102. * @var boolean
  103. * @access protected
  104. */
  105. protected $connected = false;
  106. /**
  107. * Error container.
  108. * @var array
  109. * @access protected
  110. */
  111. protected $errors = array();
  112. /**
  113. * Line break constant
  114. */
  115. const CRLF = "\r\n";
  116. /**
  117. * Simple static wrapper for all-in-one POP before SMTP
  118. * @param $host
  119. * @param integer|boolean $port The port number to connect to
  120. * @param integer|boolean $timeout The timeout value
  121. * @param string $username
  122. * @param string $password
  123. * @param integer $debug_level
  124. * @return boolean
  125. */
  126. public static function popBeforeSmtp(
  127. $host,
  128. $port = false,
  129. $timeout = false,
  130. $username = '',
  131. $password = '',
  132. $debug_level = 0
  133. ) {
  134. $pop = new POP3;
  135. return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
  136. }
  137. /**
  138. * Authenticate with a POP3 server.
  139. * A connect, login, disconnect sequence
  140. * appropriate for POP-before SMTP authorisation.
  141. * @access public
  142. * @param string $host The hostname to connect to
  143. * @param integer|boolean $port The port number to connect to
  144. * @param integer|boolean $timeout The timeout value
  145. * @param string $username
  146. * @param string $password
  147. * @param integer $debug_level
  148. * @return boolean
  149. */
  150. public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
  151. {
  152. $this->host = $host;
  153. // If no port value provided, use default
  154. if (false === $port) {
  155. $this->port = $this->POP3_PORT;
  156. } else {
  157. $this->port = (integer)$port;
  158. }
  159. // If no timeout value provided, use default
  160. if (false === $timeout) {
  161. $this->tval = $this->POP3_TIMEOUT;
  162. } else {
  163. $this->tval = (integer)$timeout;
  164. }
  165. $this->do_debug = $debug_level;
  166. $this->username = $username;
  167. $this->password = $password;
  168. // Reset the error log
  169. $this->errors = array();
  170. // connect
  171. $result = $this->connect($this->host, $this->port, $this->tval);
  172. if ($result) {
  173. $login_result = $this->login($this->username, $this->password);
  174. if ($login_result) {
  175. $this->disconnect();
  176. return true;
  177. }
  178. }
  179. // We need to disconnect regardless of whether the login succeeded
  180. $this->disconnect();
  181. return false;
  182. }
  183. /**
  184. * Connect to a POP3 server.
  185. * @access public
  186. * @param string $host
  187. * @param integer|boolean $port
  188. * @param integer $tval
  189. * @return boolean
  190. */
  191. public function connect($host, $port = false, $tval = 30)
  192. {
  193. // Are we already connected?
  194. if ($this->connected) {
  195. return true;
  196. }
  197. //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
  198. //Rather than suppress it with @fsockopen, capture it cleanly instead
  199. set_error_handler(array($this, 'catchWarning'));
  200. if (false === $port) {
  201. $port = $this->POP3_PORT;
  202. }
  203. // connect to the POP3 server
  204. $this->pop_conn = fsockopen(
  205. $host, // POP3 Host
  206. $port, // Port #
  207. $errno, // Error Number
  208. $errstr, // Error Message
  209. $tval
  210. ); // Timeout (seconds)
  211. // Restore the error handler
  212. restore_error_handler();
  213. // Did we connect?
  214. if (false === $this->pop_conn) {
  215. // It would appear not...
  216. $this->setError(array(
  217. 'error' => "Failed to connect to server $host on port $port",
  218. 'errno' => $errno,
  219. 'errstr' => $errstr
  220. ));
  221. return false;
  222. }
  223. // Increase the stream time-out
  224. stream_set_timeout($this->pop_conn, $tval, 0);
  225. // Get the POP3 server response
  226. $pop3_response = $this->getResponse();
  227. // Check for the +OK
  228. if ($this->checkResponse($pop3_response)) {
  229. // The connection is established and the POP3 server is talking
  230. $this->connected = true;
  231. return true;
  232. }
  233. return false;
  234. }
  235. /**
  236. * Log in to the POP3 server.
  237. * Does not support APOP (RFC 2828, 4949).
  238. * @access public
  239. * @param string $username
  240. * @param string $password
  241. * @return boolean
  242. */
  243. public function login($username = '', $password = '')
  244. {
  245. if (!$this->connected) {
  246. $this->setError('Not connected to POP3 server');
  247. }
  248. if (empty($username)) {
  249. $username = $this->username;
  250. }
  251. if (empty($password)) {
  252. $password = $this->password;
  253. }
  254. // Send the Username
  255. $this->sendString("USER $username" . self::CRLF);
  256. $pop3_response = $this->getResponse();
  257. if ($this->checkResponse($pop3_response)) {
  258. // Send the Password
  259. $this->sendString("PASS $password" . self::CRLF);
  260. $pop3_response = $this->getResponse();
  261. if ($this->checkResponse($pop3_response)) {
  262. return true;
  263. }
  264. }
  265. return false;
  266. }
  267. /**
  268. * Disconnect from the POP3 server.
  269. * @access public
  270. */
  271. public function disconnect()
  272. {
  273. $this->sendString('QUIT');
  274. //The QUIT command may cause the daemon to exit, which will kill our connection
  275. //So ignore errors here
  276. try {
  277. @fclose($this->pop_conn);
  278. } catch (Exception $e) {
  279. //Do nothing
  280. };
  281. }
  282. /**
  283. * Get a response from the POP3 server.
  284. * $size is the maximum number of bytes to retrieve
  285. * @param integer $size
  286. * @return string
  287. * @access protected
  288. */
  289. protected function getResponse($size = 128)
  290. {
  291. $response = fgets($this->pop_conn, $size);
  292. if ($this->do_debug >= 1) {
  293. echo "Server -> Client: $response";
  294. }
  295. return $response;
  296. }
  297. /**
  298. * Send raw data to the POP3 server.
  299. * @param string $string
  300. * @return integer
  301. * @access protected
  302. */
  303. protected function sendString($string)
  304. {
  305. if ($this->pop_conn) {
  306. if ($this->do_debug >= 2) { //Show client messages when debug >= 2
  307. echo "Client -> Server: $string";
  308. }
  309. return fwrite($this->pop_conn, $string, strlen($string));
  310. }
  311. return 0;
  312. }
  313. /**
  314. * Checks the POP3 server response.
  315. * Looks for for +OK or -ERR.
  316. * @param string $string
  317. * @return boolean
  318. * @access protected
  319. */
  320. protected function checkResponse($string)
  321. {
  322. if (substr($string, 0, 3) !== '+OK') {
  323. $this->setError(array(
  324. 'error' => "Server reported an error: $string",
  325. 'errno' => 0,
  326. 'errstr' => ''
  327. ));
  328. return false;
  329. } else {
  330. return true;
  331. }
  332. }
  333. /**
  334. * Add an error to the internal error store.
  335. * Also display debug output if it's enabled.
  336. * @param $error
  337. * @access protected
  338. */
  339. protected function setError($error)
  340. {
  341. $this->errors[] = $error;
  342. if ($this->do_debug >= 1) {
  343. echo '<pre>';
  344. foreach ($this->errors as $error) {
  345. print_r($error);
  346. }
  347. echo '</pre>';
  348. }
  349. }
  350. /**
  351. * Get an array of error messages, if any.
  352. * @return array
  353. */
  354. public function getErrors()
  355. {
  356. return $this->errors;
  357. }
  358. /**
  359. * POP3 connection error handler.
  360. * @param integer $errno
  361. * @param string $errstr
  362. * @param string $errfile
  363. * @param integer $errline
  364. * @access protected
  365. */
  366. protected function catchWarning($errno, $errstr, $errfile, $errline)
  367. {
  368. $this->setError(array(
  369. 'error' => "Connecting to the POP3 server raised a PHP warning: ",
  370. 'errno' => $errno,
  371. 'errstr' => $errstr,
  372. 'errfile' => $errfile,
  373. 'errline' => $errline
  374. ));
  375. }
  376. }