Saturday, January 13, 2007 12:26:11 |
C:\Ezpublish\ezpublish-3.8.6\lib\ezutils\classes\ezsmtp.php | C:\Ezpublish\ezpublish39\lib\ezutils\classes\ezsmtp.php |
1 | 1 | <?php |
2 | 2 | /*************************************** |
3 | 3 | ** Filename.......: class.smtp.inc |
4 | 4 | ** Project........: SMTP Class |
5 | 5 | ** Version........: 1.0.5 |
6 | 6 | ** Last Modified..: 21 December 2001 |
7 | 7 | ***************************************/ |
8 | 8 | |
9 | 9 | define('SMTP_STATUS_NOT_CONNECTED', 1, TRUE); |
10 | 10 | define('SMTP_STATUS_CONNECTED', 2, TRUE); |
11 | 11 |
12 | class smtp{ | 12 | class smtp |
13 | { |
13 | 14 | |
14 | 15 | var $authenticated; |
15 | 16 | var $connection; |
16 | 17 | var $recipients; |
17 | 18 | var $CcRecipients; |
18 | 19 | var $BccRecipients; |
19 | 20 | var $headers; |
20 | 21 | var $timeout; |
21 | 22 | var $errors; |
22 | 23 | var $status; |
23 | 24 | var $body; |
24 | 25 | var $from; |
25 | 26 | var $host; |
26 | 27 | var $port; |
27 | 28 | var $helo; |
28 | 29 | var $auth; |
29 | 30 | var $user; |
30 | 31 | var $pass; |
31 | 32 | |
32 | 33 | /*************************************** |
33 | 34 | ** Constructor function. Arguments: |
34 | 35 | ** $params - An assoc array of parameters: |
35 | 36 | ** |
36 | 37 | ** host - The hostname of the smtp server Default: localhost |
37 | 38 | ** port - The port the smtp server runs on Default: 25 |
38 | 39 | ** helo - What to send as the HELO command Default: localhost |
39 | 40 | ** (typically the hostname of the |
40 | 41 | ** machine this script runs on) |
41 | 42 | ** auth - Whether to use basic authentication Default: FALSE |
42 | 43 | ** user - Username for authentication Default: <blank> |
43 | 44 | ** pass - Password for authentication Default: <blank> |
44 | 45 | ** timeout - The timeout in seconds for the call Default: 5 |
45 | 46 | ** to fsockopen() |
46 | 47 | ***************************************/ |
47 | 48 |
48 | function smtp($params = array()){ | 49 | function smtp( $params = array() ) |
49 | 50 | { |
50 | 51 | if(!defined('CRLF')) |
51 | 52 | define('CRLF', "\r\n", TRUE); |
52 | 53 | |
53 | 54 | $this->authenticated = FALSE; |
54 | 55 | $this->timeout = 5; |
55 | 56 | $this->status = SMTP_STATUS_NOT_CONNECTED; |
56 | 57 | $this->host = 'localhost'; |
57 | 58 | $this->port = 25; |
58 | 59 | $this->helo = 'localhost'; |
59 | 60 | $this->auth = FALSE; |
60 | 61 | $this->user = ''; |
61 | 62 | $this->pass = ''; |
62 | 63 | $this->errors = array(); |
63 | 64 |
64 | foreach($params as $key => $value){ | 65 | foreach ( $params as $key => $value ) |
66 | { |
65 | 67 | $this->$key = $value; |
66 | 68 | } |
67 | 69 | } |
68 | 70 | |
69 | 71 | /*************************************** |
70 | 72 | ** Connect function. This will, when called |
71 | 73 | ** statically, create a new smtp object, |
72 | 74 | ** call the connect function (ie this function) |
73 | 75 | ** and return it. When not called statically, |
74 | 76 | ** it will connect to the server and send |
75 | 77 | ** the HELO command. |
76 | 78 | ***************************************/ |
77 | 79 |
78 | function connect($params = array()){ | 80 | function connect($params = array()) |
79 | 81 | { | |
80 | if(!isset($this->status)){ | 82 | if ( !isset( $this->status ) ) |
83 | { |
81 | 84 | $obj = new smtp($params); |
82 | if($obj->connect()){ | 85 | if( $obj->connect() ) |
86 | { |
83 | 87 | $obj->status = SMTP_STATUS_CONNECTED; |
84 | 88 | } |
85 |
86 | 89 | return $obj; |
87 | 90 | } | |
88 | }else{ | 91 | else |
92 | { |
89 | 93 | $this->connection = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); |
90 | if(function_exists('socket_set_timeout')){ | 94 | if ( function_exists( 'socket_set_timeout' ) ) |
95 | { |
91 | 96 | @socket_set_timeout($this->connection, 5, 0); |
92 | 97 | } |
93 | 98 | |
94 | 99 | $greeting = $this->get_data(); |
95 | if(is_resource($this->connection)){ | 100 | if ( is_resource( $this->connection ) ) |
101 | { |
96 | 102 | return $this->auth ? $this->ehlo() : $this->helo(); |
97 | }else{ | 103 | } |
104 | else | ||
105 | { |
98 | 106 | $this->errors[] = 'Failed to connect to server: '.$errstr; |
99 | 107 | return FALSE; |
100 | 108 | } |
101 | 109 | } |
102 | 110 | } |
103 | 111 | |
104 | 112 | /*************************************** |
105 | 113 | ** Function which handles sending the mail. |
106 | 114 | ** Arguments: |
107 | 115 | ** $params - Optional assoc array of parameters. |
108 | 116 | ** Can contain: |
109 | 117 | ** recipients - Indexed array of recipients |
110 | 118 | ** from - The from address. (used in MAIL FROM:), |
111 | 119 | ** this will be the return path |
112 | 120 | ** headers - Indexed array of headers, one header per array entry |
113 | 121 | ** body - The body of the email |
114 | 122 | ** It can also contain any of the parameters from the connect() |
115 | 123 | ** function |
116 | 124 | ***************************************/ |
117 | 125 |
118 | function send($params = array()){ | 126 | function send( $params = array() ) |
119 | 127 | { | |
120 | foreach($params as $key => $value){ | 128 | foreach ( $params as $key => $value ) |
129 | { |
121 | 130 | $this->set($key, $value); |
122 | 131 | } |
123 | 132 |
124 | if($this->is_connected()){ | 133 | if ( $this->is_connected() ) |
125 | 134 | { |
126 | 135 | // Do we auth or not? Note the distinction between the auth variable and auth() function |
127 | if($this->auth AND !$this->authenticated){ | 136 | if ( $this->auth AND !$this->authenticated ) |
137 | { |
128 | 138 | if(!$this->auth()) |
129 | 139 | return FALSE; |
130 | 140 | } |
131 | 141 | $this->mail($this->from); |
132 | 142 | if(is_array($this->recipients)) |
133 | 143 | foreach($this->recipients as $value) |
134 | 144 | $this->rcpt($value); |
135 | 145 | else |
136 | 146 | $this->rcpt($this->recipients); |
137 | 147 | |
138 | 148 | if(is_array($this->CcRecipients)) |
139 | 149 | foreach($this->CcRecipients as $value) |
140 | 150 | $this->rcpt($value); |
141 | 151 | else |
142 | 152 | $this->rcpt($this->CcRecipients); |
143 | 153 | |
144 | 154 | if(is_array($this->BccRecipients)) |
145 | 155 | foreach($this->BccRecipients as $value) |
146 | 156 | $this->rcpt($value); |
147 | 157 | else |
148 | 158 | $this->rcpt($this->BccRecipients); |
149 | 159 | |
150 | 160 | if(!$this->data()) |
151 | 161 | return FALSE; |
152 | 162 | |
153 | 163 | // Transparency |
154 | 164 | $headers = str_replace(CRLF.'.', CRLF.'..', trim(implode(CRLF, $this->headers))); |
155 | 165 | $body = str_replace(CRLF.'.', CRLF.'..', $this->body); |
156 | 166 | $body = $body[0] == '.' ? '.'.$body : $body; |
157 | 167 | |
158 | 168 | $this->send_data($headers); |
159 | 169 | $this->send_data(''); |
160 | 170 | $this->send_data($body); |
161 | 171 | $this->send_data('.'); |
162 | 172 | |
163 | 173 | $result = (substr(trim($this->get_data()), 0, 3) === '250'); |
164 | //$this->rset(); |
165 | 174 | return $result; |
166 | }else{ | 175 | } |
176 | else | ||
177 | { |
167 | 178 | $this->errors[] = 'Not connected!'; |
168 | 179 | return FALSE; |
169 | 180 | } |
170 | 181 | } |
171 | 182 | |
172 | 183 | /*************************************** |
173 | 184 | ** Function to implement HELO cmd |
174 | 185 | ***************************************/ |
175 | 186 |
176 | function helo(){ | 187 | function helo() |
188 | { | ||
189 | $error = $this->get_data(); |
177 | if(is_resource($this->connection) | 190 | if ( is_resource( $this->connection ) and |
178 | AND $this->send_data('HELO '.$this->helo) | 191 | $this->send_data( 'HELO ' . $this->helo ) and |
179 | AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){ | 192 | substr( trim( $error ), 0, 3 ) === '250' ) |
180 | 193 | { |
181 | 194 | return TRUE; |
182 | 195 | } | |
183 | }else{ | 196 | else |
197 | { |
184 | 198 | $this->errors[] = 'HELO command failed, output: ' . trim(substr(trim($error),3)); |
185 | 199 | return FALSE; |
186 | 200 | } |
187 | 201 | } |
188 | 202 | |
189 | 203 | /*************************************** |
190 | 204 | ** Function to implement EHLO cmd |
191 | 205 | ***************************************/ |
192 | 206 |
193 | function ehlo(){ | 207 | function ehlo() |
208 | { | ||
209 | $error = $this->get_data(); |
194 | if(is_resource($this->connection) | 210 | if ( is_resource( $this->connection ) and |
195 | AND $this->send_data('EHLO '.$this->helo) | 211 | $this->send_data( 'EHLO ' . $this->helo ) and |
196 | AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){ | 212 | substr( trim( ), 0, 3 ) === '250' ) |
197 | 213 | { |
198 | 214 | return TRUE; |
199 | 215 | } | |
200 | }else{ | 216 | else |
217 | { |
201 | 218 | $this->errors[] = 'EHLO command failed, output: ' . trim(substr(trim($error),3)); |
202 | 219 | return FALSE; |
203 | 220 | } |
204 | 221 | } |
205 | 222 | |
206 | 223 | /*************************************** |
207 | 224 | ** Function to implement RSET cmd |
208 | 225 | ***************************************/ |
209 | 226 |
210 | function rset(){ | 227 | function rset() |
228 | { | ||
229 | $error = $this->get_data(); |
211 | if(is_resource($this->connection) | 230 | if ( is_resource( $this->connection ) and |
212 | AND $this->send_data('RSET') | 231 | $this->send_data( 'RSET' ) and |
213 | AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){ | 232 | substr( trim( $error ), 0, 3 ) === '250' ) |
214 | 233 | { |
215 | 234 | return TRUE; |
216 | 235 | } | |
217 | }else{ | 236 | else |
237 | { |
218 | 238 | $this->errors[] = 'RSET command failed, output: ' . trim(substr(trim($error),3)); |
219 | 239 | return FALSE; |
220 | 240 | } |
221 | 241 | } |
222 | 242 | |
223 | 243 | /*************************************** |
224 | 244 | ** Function to implement QUIT cmd |
225 | 245 | ***************************************/ |
226 | 246 |
227 | function quit(){ | 247 | function quit() |
248 | { | ||
249 | $error = $this->get_data(); |
228 | if(is_resource($this->connection) | 250 | if ( is_resource( $this->connection ) and |
229 | AND $this->send_data('QUIT') | 251 | $this->send_data( 'QUIT' ) and |
230 | AND substr(trim($error = $this->get_data()), 0, 3) === '221' ){ | 252 | substr( trim( $error ), 0, 3 ) === '221' ) |
231 | 253 | { |
232 | 254 | fclose($this->connection); |
233 | 255 | $this->status = SMTP_STATUS_NOT_CONNECTED; |
234 | 256 | return TRUE; |
235 | 257 | } | |
236 | }else{ | 258 | else |
259 | { |
237 | 260 | $this->errors[] = 'QUIT command failed, output: ' . trim(substr(trim($error),3)); |
238 | 261 | return FALSE; |
239 | 262 | } |
240 | 263 | } |
241 | 264 | |
242 | 265 | /*************************************** |
243 | 266 | ** Function to implement AUTH cmd |
244 | 267 | ***************************************/ |
245 | 268 |
246 | function auth(){ | 269 | function auth() |
247 | if(is_resource($this->connection) | 270 | { |
248 | AND $this->send_data('AUTH LOGIN') | 271 | $error = $this->get_data(); |
249 | AND substr(trim($error = $this->get_data()), 0, 3) === '334' | 272 | if ( is_resource( $this->connection ) and |
250 | AND $this->send_data(base64_encode($this->user)) // Send username | 273 | $this->send_data( 'AUTH LOGIN' ) and |
251 | AND substr(trim($error = $this->get_data()),0,3) === '334' | 274 | substr( trim( $error ), 0, 3) === '334' and |
252 | AND $this->send_data(base64_encode($this->pass)) // Send password | 275 | $this->send_data( base64_encode( $this->user ) ) and // Send username |
253 | AND substr(trim($error = $this->get_data()),0,3) === '235' ){ | 276 | substr( trim( $error ), 0, 3 ) === '334' and |
254 | 277 | $this->send_data( base64_encode( $this->pass ) ) and // Send password |
278 | substr( trim( $error ), 0, 3 ) === '235' ) | ||
279 | { |
255 | 280 | $this->authenticated = TRUE; |
256 | 281 | return TRUE; |
257 | 282 | } | |
258 | }else{ | 283 | else |
284 | { |
259 | 285 | $this->errors[] = 'AUTH command failed: ' . trim(substr(trim($error),3)); |
260 | 286 | return FALSE; |
261 | 287 | } |
262 | 288 | } |
263 | 289 | |
264 | 290 | /*************************************** |
265 | 291 | ** Function that handles the MAIL FROM: cmd |
266 | 292 | ***************************************/ |
267 | 293 | |
268 | 294 | function mail($from) |
269 | 295 | { |
270 | 296 | if ( !preg_match( "/<.+>/", $from ) ) |
271 | 297 | $from = '<' . $from .'>'; |
272 | if($this->is_connected() | 298 | if ( $this->is_connected() and |
273 | AND $this->send_data('MAIL FROM:'.$from.'') | 299 | $this->send_data( 'MAIL FROM:' . $from . '' ) and |
274 | AND substr(trim($this->get_data()), 0, 3) === '250' ) | 300 | substr( trim( $this->get_data() ), 0, 3 ) === '250' ) |
275 | 301 | { |
276 | 302 | return TRUE; |
277 | 303 | } | |
278 | }else | 304 | else |
279 | 305 | { |
280 | 306 | return FALSE; |
281 | 307 | } |
282 | 308 | } |
283 | 309 | |
284 | 310 | /*************************************** |
285 | 311 | ** Function that handles the RCPT TO: cmd |
286 | 312 | ***************************************/ |
287 | 313 | |
288 | 314 | function rcpt($to) |
289 | 315 | { |
290 | 316 | if ( !preg_match( "/<.+>/", $to ) ) |
291 | 317 | $to = '<' . $to .'>'; |
318 | |||
319 | $error = $this->get_data(); |
292 | if($this->is_connected() | 320 | if ( $this->is_connected() and |
293 | AND $this->send_data('RCPT TO:'.$to.'' ) | 321 | $this->send_data( 'RCPT TO:' . $to . '' ) and |
294 | AND substr(trim($error = $this->get_data()), 0, 3) === '250' ) | 322 | substr( trim( $error ), 0, 3 ) === '250' ) |
295 | 323 | { |
296 | 324 | return TRUE; |
297 | 325 | } | |
298 | }else | 326 | else |
299 | 327 | { |
300 | 328 | $this->errors[] = trim(substr(trim($error), 3 ) ); |
301 | 329 | return FALSE; |
302 | 330 | } |
303 | 331 | } |
304 | 332 | |
305 | 333 | /*************************************** |
306 | 334 | ** Function that sends the DATA cmd |
307 | 335 | ***************************************/ |
308 | 336 |
309 | function data(){ | 337 | function data() |
310 | 338 | { |
339 | $error = $this->get_data(); |
311 | if($this->is_connected() | 340 | if( $this->is_connected() and |
312 | AND $this->send_data('DATA') | 341 | $this->send_data( 'DATA' ) and |
313 | AND substr(trim($error = $this->get_data()), 0, 3) === '354' ){ | 342 | substr( trim( $error ), 0, 3 ) === '354' ) |
343 | { |
314 | 344 | return TRUE; |
315 | 345 | } | |
316 | }else{ | 346 | else |
347 | { |
317 | 348 | $this->errors[] = trim(substr(trim($error), 3)); |
318 | 349 | return FALSE; |
319 | 350 | } |
320 | 351 | } |
321 | 352 | |
322 | 353 | /*************************************** |
323 | 354 | ** Function to determine if this object |
324 | 355 | ** is connected to the server or not. |
325 | 356 | ***************************************/ |
326 | 357 |
327 | function is_connected(){ | 358 | function is_connected() |
328 | 359 | { |
329 | 360 | return (is_resource($this->connection) AND ($this->status === SMTP_STATUS_CONNECTED)); |
330 | 361 | } |
331 | 362 | |
332 | 363 | /*************************************** |
333 | 364 | ** Function to send a bit of data |
334 | 365 | ***************************************/ |
335 | 366 |
336 | function send_data($data){ | 367 | function send_data( $data ) |
368 | { |
337 | if(is_resource($this->connection)){ | 369 | if ( is_resource( $this->connection ) ) |
370 | { |
338 | 371 | return fwrite($this->connection, $data.CRLF, strlen($data)+2); |
339 | 372 | } | |
340 | }else | 373 | else |
341 | 374 | return FALSE; |
342 | 375 | } |
343 | 376 | |
344 | 377 | /*************************************** |
345 | 378 | ** Function to get data. |
346 | 379 | ***************************************/ |
347 | 380 |
348 | function &get_data(){ | 381 | function get_data() |
349 | 382 | { |
350 | 383 | $return = ''; |
351 | 384 | $line = ''; |
352 | 385 | $loops = 0; |
353 | 386 |
354 | if(is_resource($this->connection)){ | 387 | if ( is_resource( $this->connection ) ) |
388 | { |
355 | while((strpos($return, CRLF) === FALSE OR substr($line,3,1) !== ' ') AND $loops < 100){ | 389 | while ( ( strpos( $return, CRLF ) === FALSE OR substr( $line, 3, 1 ) !== ' ' ) AND $loops < 100 ) |
390 | { |
356 | 391 | $line = fgets($this->connection, 512); |
357 | 392 | $return .= $line; |
358 | 393 | $loops++; |
359 | 394 | } |
360 | 395 | return $return; |
361 | 396 | } | |
362 | }else | 397 | else |
363 | 398 | return FALSE; |
364 | 399 | } |
365 | 400 | |
366 | 401 | /*************************************** |
367 | 402 | ** Sets a variable |
368 | 403 | ***************************************/ |
369 | 404 |
370 | function set($var, $value){ | 405 | function set( $var, $value ) |
371 | 406 | { |
372 | 407 | $this->$var = $value; |
373 | 408 | return TRUE; |
374 | 409 | } |
375 | 410 | |
376 | 411 | } // End of class |
377 | 412 | ?> |
378 | 413 |