PopBeforeSmtpPlugin.php 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * Makes sure a connection to a POP3 host has been established prior to connecting to SMTP.
  11. *
  12. * @package Swift
  13. * @subpackage Plugins
  14. * @author Chris Corbyn
  15. */
  16. class Swift_Plugins_PopBeforeSmtpPlugin implements Swift_Events_TransportChangeListener, Swift_Plugins_Pop_Pop3Connection
  17. {
  18. /** A delegate connection to use (mostly a test hook) */
  19. private $_connection;
  20. /** Hostname of the POP3 server */
  21. private $_host;
  22. /** Port number to connect on */
  23. private $_port;
  24. /** Encryption type to use (if any) */
  25. private $_crypto;
  26. /** Username to use (if any) */
  27. private $_username;
  28. /** Password to use (if any) */
  29. private $_password;
  30. /** Established connection via TCP socket */
  31. private $_socket;
  32. /** Connect timeout in seconds */
  33. private $_timeout = 10;
  34. /** SMTP Transport to bind to */
  35. private $_transport;
  36. /**
  37. * Create a new PopBeforeSmtpPlugin for $host and $port.
  38. *
  39. * @param string $host
  40. * @param integer $port
  41. * @param string $crypto as "tls" or "ssl"
  42. */
  43. public function __construct($host, $port = 110, $crypto = null)
  44. {
  45. $this->_host = $host;
  46. $this->_port = $port;
  47. $this->_crypto = $crypto;
  48. }
  49. /**
  50. * Create a new PopBeforeSmtpPlugin for $host and $port.
  51. *
  52. * @param string $host
  53. * @param integer $port
  54. * @param string $crypto as "tls" or "ssl"
  55. *
  56. * @return Swift_Plugins_PopBeforeSmtpPlugin
  57. */
  58. public static function newInstance($host, $port = 110, $crypto = null)
  59. {
  60. return new self($host, $port, $crypto);
  61. }
  62. /**
  63. * Set a Pop3Connection to delegate to instead of connecting directly.
  64. *
  65. * @param Swift_Plugins_Pop_Pop3Connection $connection
  66. *
  67. * @return Swift_Plugins_PopBeforeSmtpPlugin
  68. */
  69. public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection)
  70. {
  71. $this->_connection = $connection;
  72. return $this;
  73. }
  74. /**
  75. * Bind this plugin to a specific SMTP transport instance.
  76. *
  77. * @param Swift_Transport
  78. */
  79. public function bindSmtp(Swift_Transport $smtp)
  80. {
  81. $this->_transport = $smtp;
  82. }
  83. /**
  84. * Set the connection timeout in seconds (default 10).
  85. *
  86. * @param integer $timeout
  87. *
  88. * @return Swift_Plugins_PopBeforeSmtpPlugin
  89. */
  90. public function setTimeout($timeout)
  91. {
  92. $this->_timeout = (int) $timeout;
  93. return $this;
  94. }
  95. /**
  96. * Set the username to use when connecting (if needed).
  97. *
  98. * @param string $username
  99. *
  100. * @return Swift_Plugins_PopBeforeSmtpPlugin
  101. */
  102. public function setUsername($username)
  103. {
  104. $this->_username = $username;
  105. return $this;
  106. }
  107. /**
  108. * Set the password to use when connecting (if needed).
  109. *
  110. * @param string $password
  111. *
  112. * @return Swift_Plugins_PopBeforeSmtpPlugin
  113. */
  114. public function setPassword($password)
  115. {
  116. $this->_password = $password;
  117. return $this;
  118. }
  119. /**
  120. * Connect to the POP3 host and authenticate.
  121. *
  122. * @throws Swift_Plugins_Pop_Pop3Exception if connection fails
  123. */
  124. public function connect()
  125. {
  126. if (isset($this->_connection)) {
  127. $this->_connection->connect();
  128. } else {
  129. if (!isset($this->_socket)) {
  130. if (!$socket = fsockopen(
  131. $this->_getHostString(), $this->_port, $errno, $errstr, $this->_timeout))
  132. {
  133. throw new Swift_Plugins_Pop_Pop3Exception(
  134. sprintf('Failed to connect to POP3 host [%s]: %s', $this->_host, $errstr)
  135. );
  136. }
  137. $this->_socket = $socket;
  138. if (false === $greeting = fgets($this->_socket)) {
  139. throw new Swift_Plugins_Pop_Pop3Exception(
  140. sprintf('Failed to connect to POP3 host [%s]', trim($greeting))
  141. );
  142. }
  143. $this->_assertOk($greeting);
  144. if ($this->_username) {
  145. $this->_command(sprintf("USER %s\r\n", $this->_username));
  146. $this->_command(sprintf("PASS %s\r\n", $this->_password));
  147. }
  148. }
  149. }
  150. }
  151. /**
  152. * Disconnect from the POP3 host.
  153. */
  154. public function disconnect()
  155. {
  156. if (isset($this->_connection)) {
  157. $this->_connection->disconnect();
  158. } else {
  159. $this->_command("QUIT\r\n");
  160. if (!fclose($this->_socket)) {
  161. throw new Swift_Plugins_Pop_Pop3Exception(
  162. sprintf('POP3 host [%s] connection could not be stopped', $this->_host)
  163. );
  164. }
  165. $this->_socket = null;
  166. }
  167. }
  168. /**
  169. * Invoked just before a Transport is started.
  170. *
  171. * @param Swift_Events_TransportChangeEvent $evt
  172. */
  173. public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt)
  174. {
  175. if (isset($this->_transport)) {
  176. if ($this->_transport !== $evt->getTransport()) {
  177. return;
  178. }
  179. }
  180. $this->connect();
  181. $this->disconnect();
  182. }
  183. /**
  184. * Not used.
  185. */
  186. public function transportStarted(Swift_Events_TransportChangeEvent $evt)
  187. {
  188. }
  189. /**
  190. * Not used.
  191. */
  192. public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt)
  193. {
  194. }
  195. /**
  196. * Not used.
  197. */
  198. public function transportStopped(Swift_Events_TransportChangeEvent $evt)
  199. {
  200. }
  201. // -- Private Methods
  202. private function _command($command)
  203. {
  204. if (!fwrite($this->_socket, $command)) {
  205. throw new Swift_Plugins_Pop_Pop3Exception(
  206. sprintf('Failed to write command [%s] to POP3 host', trim($command))
  207. );
  208. }
  209. if (false === $response = fgets($this->_socket)) {
  210. throw new Swift_Plugins_Pop_Pop3Exception(
  211. sprintf('Failed to read from POP3 host after command [%s]', trim($command))
  212. );
  213. }
  214. $this->_assertOk($response);
  215. return $response;
  216. }
  217. private function _assertOk($response)
  218. {
  219. if (substr($response, 0, 3) != '+OK') {
  220. throw new Swift_Plugins_Pop_Pop3Exception(
  221. sprintf('POP3 command failed [%s]', trim($response))
  222. );
  223. }
  224. }
  225. private function _getHostString()
  226. {
  227. $host = $this->_host;
  228. switch (strtolower($this->_crypto)) {
  229. case 'ssl':
  230. $host = 'ssl://' . $host;
  231. break;
  232. case 'tls':
  233. $host = 'tls://' . $host;
  234. break;
  235. }
  236. return $host;
  237. }
  238. }