| 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 |