00001 <?php
00015 define('SMTP_STATUS_NOT_CONNECTED', 1, true);
00016 define('SMTP_STATUS_CONNECTED', 2, true);
00017
00018 class smtp
00019 {
00020 private $authenticated;
00021 private $connection;
00022 private $recipients;
00023 private $headers;
00024 private $timeout;
00025 private $errors;
00026 private $status;
00027 private $body;
00028 private $from;
00029 private $host;
00030 private $port;
00031 private $helo;
00032 private $auth;
00033 private $user;
00034 private $pass;
00035
00051 public function __construct($params = array())
00052 {
00053
00054 if(!defined('CRLF'))
00055 define('CRLF', "\r\n", TRUE);
00056
00057 $this->authenticated = FALSE;
00058 $this->timeout = 5;
00059 $this->status = SMTP_STATUS_NOT_CONNECTED;
00060 $this->host = 'localhost';
00061 $this->port = 25;
00062 $this->helo = 'localhost';
00063 $this->auth = FALSE;
00064 $this->user = '';
00065 $this->pass = '';
00066 $this->errors = array();
00067
00068 foreach($params as $key => $value){
00069 $this->$key = $value;
00070 }
00071 }
00072
00081 public function connect($params = array())
00082 {
00083 if (!isset($this->status)) {
00084 $obj = new smtp($params);
00085 if($obj->connect()){
00086 $obj->status = SMTP_STATUS_CONNECTED;
00087 }
00088
00089 return $obj;
00090
00091 } else {
00092 $this->connection = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
00093 if (function_exists('socket_set_timeout')) {
00094 @socket_set_timeout($this->connection, 5, 0);
00095 }
00096
00097 $greeting = $this->get_data();
00098 if (is_resource($this->connection)) {
00099 return $this->auth ? $this->ehlo() : $this->helo();
00100 } else {
00101 $this->errors[] = 'Failed to connect to server: '.$errstr;
00102 return FALSE;
00103 }
00104 }
00105 }
00106
00120 public function send($params = array())
00121 {
00122 foreach ($params as $key => $value) {
00123 $this->set($key, $value);
00124 }
00125
00126 if ($this->is_connected()) {
00127
00128
00129 if ($this->auth AND !$this->authenticated) {
00130 if(!$this->auth())
00131 return false;
00132 }
00133
00134 $this->mail($this->from);
00135
00136 if (is_array($this->recipients)) {
00137 foreach ($this->recipients as $value) {
00138 $this->rcpt($value);
00139 }
00140 } else {
00141 $this->rcpt($this->recipients);
00142 }
00143
00144 if (!$this->data()) {
00145 return false;
00146 }
00147
00148
00149 $headers = str_replace(CRLF.'.', CRLF.'..', trim(implode(CRLF, $this->headers)));
00150 $body = str_replace(CRLF.'.', CRLF.'..', $this->body);
00151 $body = substr($body, 0, 1) == '.' ? '.'.$body : $body;
00152
00153 $this->send_data($headers);
00154 $this->send_data('');
00155 $this->send_data($body);
00156 $this->send_data('.');
00157
00158 $result = (substr(trim($this->get_data()), 0, 3) === '250');
00159
00160 return $result;
00161 } else {
00162 $this->errors[] = 'Not connected!';
00163 return FALSE;
00164 }
00165 }
00166
00170 private function helo()
00171 {
00172 if(is_resource($this->connection)
00173 AND $this->send_data('HELO '.$this->helo)
00174 AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){
00175
00176 return true;
00177
00178 } else {
00179 $this->errors[] = 'HELO command failed, output: ' . trim(substr(trim($error),3));
00180 return false;
00181 }
00182 }
00183
00187 private function ehlo()
00188 {
00189 if (is_resource($this->connection)
00190 AND $this->send_data('EHLO '.$this->helo)
00191 AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){
00192
00193 return true;
00194
00195 } else {
00196 $this->errors[] = 'EHLO command failed, output: ' . trim(substr(trim($error),3));
00197 return false;
00198 }
00199 }
00200
00204 private function rset()
00205 {
00206 if (is_resource($this->connection)
00207 AND $this->send_data('RSET')
00208 AND substr(trim($error = $this->get_data()), 0, 3) === '250' ){
00209
00210 return true;
00211
00212 } else {
00213 $this->errors[] = 'RSET command failed, output: ' . trim(substr(trim($error),3));
00214 return false;
00215 }
00216 }
00217
00221 private function quit()
00222 {
00223 if(is_resource($this->connection)
00224 AND $this->send_data('QUIT')
00225 AND substr(trim($error = $this->get_data()), 0, 3) === '221' ){
00226
00227 fclose($this->connection);
00228 $this->status = SMTP_STATUS_NOT_CONNECTED;
00229 return true;
00230
00231 } else {
00232 $this->errors[] = 'QUIT command failed, output: ' . trim(substr(trim($error),3));
00233 return false;
00234 }
00235 }
00236
00240 private function auth()
00241 {
00242 if (is_resource($this->connection)
00243 AND $this->send_data('AUTH LOGIN')
00244 AND substr(trim($error = $this->get_data()), 0, 3) === '334'
00245 AND $this->send_data(base64_encode($this->user))
00246 AND substr(trim($error = $this->get_data()),0,3) === '334'
00247 AND $this->send_data(base64_encode($this->pass))
00248 AND substr(trim($error = $this->get_data()),0,3) === '235' ){
00249
00250 $this->authenticated = true;
00251 return true;
00252
00253 } else {
00254 $this->errors[] = 'AUTH command failed: ' . trim(substr(trim($error),3));
00255 return false;
00256 }
00257 }
00258
00262 private function mail($from)
00263 {
00264 if ($this->is_connected()
00265 AND $this->send_data('MAIL FROM:<'.$from.'>')
00266 AND substr(trim($this->get_data()), 0, 2) === '250' ) {
00267
00268 return true;
00269
00270 } else {
00271 return false;
00272 }
00273 }
00274
00278 private function rcpt($to)
00279 {
00280 if($this->is_connected()
00281 AND $this->send_data('RCPT TO:<'.$to.'>')
00282 AND substr(trim($error = $this->get_data()), 0, 2) === '25' ){
00283
00284 return true;
00285
00286 } else {
00287 $this->errors[] = trim(substr(trim($error), 3));
00288 return false;
00289 }
00290 }
00291
00295 private function data()
00296 {
00297 if($this->is_connected()
00298 AND $this->send_data('DATA')
00299 AND substr(trim($error = $this->get_data()), 0, 3) === '354' ) {
00300
00301 return true;
00302
00303 } else {
00304 $this->errors[] = trim(substr(trim($error), 3));
00305 return false;
00306 }
00307 }
00308
00313 private function is_connected()
00314 {
00315 return (is_resource($this->connection) AND ($this->status === SMTP_STATUS_CONNECTED));
00316 }
00317
00321 private function send_data($data)
00322 {
00323 if(is_resource($this->connection)){
00324 return fwrite($this->connection, $data.CRLF, strlen($data)+2);
00325
00326 } else {
00327 return false;
00328 }
00329 }
00330
00334 private function get_data()
00335 {
00336 $return = '';
00337 $line = '';
00338 $loops = 0;
00339
00340 if(is_resource($this->connection)){
00341 while((strpos($return, CRLF) === FALSE OR substr($line,3,1) !== ' ') AND $loops < 100){
00342 $line = fgets($this->connection, 512);
00343 $return .= $line;
00344 $loops++;
00345 }
00346 return $return;
00347
00348 }else
00349 return false;
00350 }
00351
00355 public function set($var, $value)
00356 {
00357 $this->$var = $value;
00358 return true;
00359 }
00360
00364 public function getErrors()
00365 {
00366 return $this->errors;
00367 }
00368
00369
00370 }
00371 ?>