|
eZ Publish
[4.0]
|
00001 <?php 00002 /*************************************** 00003 ** Filename.......: class.smtp.inc 00004 ** Project........: SMTP Class 00005 ** Version........: 1.0.5 00006 ** Last Modified..: 21 December 2001 00007 ***************************************/ 00008 00009 class smtp 00010 { 00011 const STATUS_NOT_CONNECTED = 1; 00012 const STATUS_CONNECTED = 2; 00013 const CRLF = "\r\n"; 00014 00015 public $authenticated; 00016 public $connection; 00017 public $recipients; 00018 public $CcRecipients; 00019 public $BccRecipients; 00020 public $headers; 00021 public $timeout; 00022 public $errors; 00023 public $status; 00024 public $body; 00025 public $from; 00026 public $host; 00027 public $port; 00028 public $helo; 00029 public $auth; 00030 public $user; 00031 public $pass; 00032 00033 /*************************************** 00034 ** Constructor function. Arguments: 00035 ** $params - An assoc array of parameters: 00036 ** 00037 ** host - The hostname of the smtp server Default: localhost 00038 ** port - The port the smtp server runs on Default: 25 00039 ** helo - What to send as the HELO command Default: localhost 00040 ** (typically the hostname of the 00041 ** machine this script runs on) 00042 ** auth - Whether to use basic authentication Default: FALSE 00043 ** user - Username for authentication Default: <blank> 00044 ** pass - Password for authentication Default: <blank> 00045 ** timeout - The timeout in seconds for the call Default: 5 00046 ** to fsockopen() 00047 ***************************************/ 00048 00049 function smtp( $params = array() ) 00050 { 00051 $this->authenticated = FALSE; 00052 $this->timeout = 5; 00053 $this->status = smtp::STATUS_NOT_CONNECTED; 00054 $this->host = 'localhost'; 00055 $this->port = 25; 00056 $this->helo = 'localhost'; 00057 $this->auth = FALSE; 00058 $this->user = ''; 00059 $this->pass = ''; 00060 $this->errors = array(); 00061 00062 foreach ( $params as $key => $value ) 00063 { 00064 $this->$key = $value; 00065 } 00066 } 00067 00068 /*************************************** 00069 ** Connect function. 00070 ** It will connect to the server and send 00071 ** the HELO command. 00072 ***************************************/ 00073 00074 function connect($params = array()) 00075 { 00076 $this->connection = fsockopen( $this->host, $this->port, $errno, $errstr, $this->timeout ); 00077 if ( function_exists( 'socket_set_timeout' ) ) 00078 { 00079 @socket_set_timeout( $this->connection, 5, 0 ); 00080 } 00081 00082 $greeting = $this->get_data(); 00083 if ( is_resource( $this->connection ) ) 00084 { 00085 $result = $this->auth ? $this->ehlo() : $this->helo(); 00086 if ( $result ) 00087 { 00088 $this->status = smtp::STATUS_CONNECTED; 00089 } 00090 return $result; 00091 } 00092 else 00093 { 00094 $this->errors[] = 'Failed to connect to server: ' . $errstr; 00095 return FALSE; 00096 } 00097 } 00098 00099 /*************************************** 00100 ** Function which handles sending the mail. 00101 ** Arguments: 00102 ** $params - Optional assoc array of parameters. 00103 ** Can contain: 00104 ** recipients - Indexed array of recipients 00105 ** from - The from address. (used in MAIL FROM:), 00106 ** this will be the return path 00107 ** headers - Indexed array of headers, one header per array entry 00108 ** body - The body of the email 00109 ** It can also contain any of the parameters from the connect() 00110 ** function 00111 ***************************************/ 00112 00113 function send( $params = array() ) 00114 { 00115 foreach ( $params as $key => $value ) 00116 { 00117 $this->set( $key, $value ); 00118 } 00119 00120 if ( $this->is_connected() ) 00121 { 00122 // Do we auth or not? Note the distinction between the auth variable and auth() function 00123 if ( $this->auth AND !$this->authenticated ) 00124 { 00125 if ( !$this->auth() ) 00126 return FALSE; 00127 } 00128 $this->mail( $this->from ); 00129 if ( is_array( $this->recipients ) ) 00130 foreach ( $this->recipients as $value ) 00131 $this->rcpt( $value ); 00132 else 00133 $this->rcpt( $this->recipients ); 00134 00135 if ( is_array( $this->CcRecipients ) ) 00136 foreach( $this->CcRecipients as $value ) 00137 $this->rcpt( $value ); 00138 else 00139 $this->rcpt( $this->CcRecipients ); 00140 00141 if ( is_array( $this->BccRecipients ) ) 00142 foreach ( $this->BccRecipients as $value ) 00143 $this->rcpt( $value ); 00144 else 00145 $this->rcpt( $this->BccRecipients ); 00146 00147 if ( !$this->data() ) 00148 return FALSE; 00149 00150 // Transparency 00151 $headers = str_replace( smtp::CRLF.'.', smtp::CRLF.'..', trim( implode( smtp::CRLF, $this->headers ) ) ); 00152 $body = str_replace( smtp::CRLF.'.', smtp::CRLF.'..', $this->body ); 00153 $body = $body[0] == '.' ? '.'.$body : $body; 00154 00155 $this->send_data( $headers ); 00156 $this->send_data( '' ); 00157 $this->send_data( $body ); 00158 $this->send_data( '.' ); 00159 00160 $result = ( substr( trim( $this->get_data() ), 0, 3) === '250' ); 00161 return $result; 00162 } 00163 else 00164 { 00165 $this->errors[] = 'Not connected!'; 00166 return FALSE; 00167 } 00168 } 00169 00170 /*************************************** 00171 ** Function to implement HELO cmd 00172 ***************************************/ 00173 00174 function helo() 00175 { 00176 return( $this->send_cmd( 'HELO ' . $this->helo, '250' ) ); 00177 } 00178 00179 00180 /*************************************** 00181 ** Function to implement EHLO cmd 00182 ***************************************/ 00183 00184 function ehlo() 00185 { 00186 /* return the result of the EHLO command */ 00187 return ( $this->send_cmd( 'EHLO ' . $this->helo, '250' ) ); 00188 } 00189 00190 /*************************************** 00191 ** Function to implement RSET cmd 00192 ***************************************/ 00193 00194 function rset() 00195 { 00196 /* return the result of the RSET command */ 00197 return ( $this->send_cmd( 'RSET', '250' ) ); 00198 } 00199 00200 /*************************************** 00201 ** Function to implement QUIT cmd 00202 ***************************************/ 00203 00204 function quit() 00205 { 00206 /* if QUIT OK */ 00207 if ( $this->send_cmd( 'QUIT', '221' ) ) 00208 { 00209 /* unset the connection flag and return TRUE */ 00210 $this->status = smtp::STATUS_NOT_CONNECTED; 00211 return TRUE; 00212 } 00213 /* in other case return FALSE */ 00214 return FALSE; 00215 } 00216 00217 /*************************************** 00218 ** Function to implement AUTH cmd 00219 ***************************************/ 00220 00221 function auth() 00222 { 00223 /* if the connection is made */ 00224 if ( $this->send_cmd('AUTH LOGIN', '334' ) ) 00225 { 00226 /* if sending username ok */ 00227 if ( $this->send_cmd( base64_encode( $this->user ), '334' ) ) 00228 { 00229 /* if sending password ok */ 00230 if ( $this->send_cmd( base64_encode( $this->pass ), '235' ) ) 00231 { 00232 /* set the authenticated flag and return TRUE */ 00233 $this->authenticated = TRUE; 00234 return TRUE; 00235 } 00236 } 00237 } 00238 /* in other case return FALSE */ 00239 return FALSE; 00240 } 00241 00242 /*************************************** 00243 ** Function that handles the MAIL FROM: cmd 00244 ***************************************/ 00245 00246 function mail( $from ) 00247 { 00248 /* normalize the from field */ 00249 if ( !preg_match( "/<.+>/", $from ) ) 00250 $from = '<' . $from .'>'; 00251 00252 /* return the result of the MAIL FROM command */ 00253 return ( $this->send_cmd('MAIL FROM:' . $from . '', '250' ) ); 00254 } 00255 00256 /*************************************** 00257 ** Function that handles the RCPT TO: cmd 00258 ***************************************/ 00259 00260 function rcpt( $to ) 00261 { 00262 /* normalize the to field */ 00263 if ( !preg_match( "/<.+>/", $to ) ) 00264 $to = '<' . $to .'>'; 00265 00266 /* return the result of the RCPT TO command */ 00267 return ( $this->send_cmd( 'RCPT TO:' . $to . '', '250' ) ); 00268 } 00269 00270 00271 /*************************************** 00272 ** Function that sends the DATA cmd 00273 ***************************************/ 00274 00275 function data() 00276 { 00277 /* return the result of the RCPT TO command */ 00278 return ( $this->send_cmd('DATA', '354' ) ); 00279 } 00280 00281 /*************************************** 00282 ** Function to determine if this object 00283 ** is connected to the server or not. 00284 ***************************************/ 00285 00286 function is_connected() 00287 { 00288 return ( is_resource( $this->connection ) AND ( $this->status === smtp::STATUS_CONNECTED ) ); 00289 } 00290 00291 /*************************************** 00292 ** Function to send a bit of data 00293 ***************************************/ 00294 00295 function send_data( $data ) 00296 { 00297 if ( is_resource( $this->connection ) ) 00298 { 00299 return fwrite( $this->connection, $data.smtp::CRLF, strlen( $data ) + 2 ); 00300 } 00301 else 00302 return FALSE; 00303 } 00304 00305 /*************************************** 00306 ** Function to get data. 00307 ***************************************/ 00308 00309 function get_data() 00310 { 00311 $return = ''; 00312 $line = ''; 00313 $loops = 0; 00314 00315 if ( is_resource( $this->connection ) ) 00316 { 00317 while ( ( strpos( $return, smtp::CRLF ) === FALSE OR substr( $line, 3, 1 ) !== ' ' ) AND $loops < 100 ) 00318 { 00319 $line = fgets( $this->connection, 512 ); 00320 $return .= $line; 00321 $loops++; 00322 } 00323 return $return; 00324 } 00325 else 00326 return FALSE; 00327 } 00328 00329 /*************************************** 00330 ** Sets a variable 00331 ***************************************/ 00332 00333 function set( $var, $value ) 00334 { 00335 $this->$var = $value; 00336 return TRUE; 00337 } 00338 00339 /******************************************************** 00340 ** Function to simply send a command to the smtp socket 00341 *********************************************************/ 00342 function send_cmd( $msg, $answer ) 00343 { 00344 /* if the connection is made */ 00345 if ( $error = is_resource( $this->connection ) ) 00346 { 00347 /* if sending DATA ok */ 00348 if ( $error = $this->send_data( $msg ) ) 00349 { 00350 /* Wait for server answer */ 00351 $error = $this->get_data(); 00352 00353 /* return TRUE if the server answered the expected tag */ 00354 if( substr( trim( $error ), 0, 3 ) === $answer ) 00355 { 00356 return TRUE; 00357 } 00358 } 00359 } 00360 /* else return FALSE and set an error */ 00361 $this->errors[] = $msg . ' command failed, output: ' . $error; 00362 return FALSE; 00363 } 00364 00365 } // End of class 00366 ?>