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