| 1 | <?php
 | 
  
    | 2 | /*~ class.smtp.php
 | 
  
    | 3 | .---------------------------------------------------------------------------.
 | 
  
    | 4 | |  Software: PHPMailer - PHP email class                                    |
 | 
  
    | 5 | |   Version: 5.1                                                            |
 | 
  
    | 6 | |   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
 | 
  
    | 7 | |      Info: http://phpmailer.sourceforge.net                               |
 | 
  
    | 8 | |   Support: http://sourceforge.net/projects/phpmailer/                     |
 | 
  
    | 9 | | ------------------------------------------------------------------------- |
 | 
  
    | 10 | |     Admin: Andy Prevost (project admininistrator)                         |
 | 
  
    | 11 | |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
 | 
  
    | 12 | |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
 | 
  
    | 13 | |   Founder: Brent R. Matzelle (original founder)                           |
 | 
  
    | 14 | | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
 | 
  
    | 15 | | Copyright (c) 2001-2003, Brent R. Matzelle                                |
 | 
  
    | 16 | | ------------------------------------------------------------------------- |
 | 
  
    | 17 | |   License: Distributed under the Lesser General Public License (LGPL)     |
 | 
  
    | 18 | |            http://www.gnu.org/copyleft/lesser.html                        |
 | 
  
    | 19 | | This program is distributed in the hope that it will be useful - WITHOUT  |
 | 
  
    | 20 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
 | 
  
    | 21 | | FITNESS FOR A PARTICULAR PURPOSE.                                         |
 | 
  
    | 22 | | ------------------------------------------------------------------------- |
 | 
  
    | 23 | | We offer a number of paid services (www.codeworxtech.com):                |
 | 
  
    | 24 | | - Web Hosting on highly optimized fast and secure servers                 |
 | 
  
    | 25 | | - Technology Consulting                                                   |
 | 
  
    | 26 | | - Oursourcing (highly qualified programmers and graphic designers)        |
 | 
  
    | 27 | '---------------------------------------------------------------------------'
 | 
  
    | 28 | */
 | 
  
    | 29 | 
 | 
  
    | 30 | /**
 | 
  
    | 31 |  * PHPMailer - PHP SMTP email transport class
 | 
  
    | 32 |  * NOTE: Designed for use with PHP version 5 and up
 | 
  
    | 33 |  * @package PHPMailer
 | 
  
    | 34 |  * @author Andy Prevost
 | 
  
    | 35 |  * @author Marcus Bointon
 | 
  
    | 36 |  * @copyright 2004 - 2008 Andy Prevost
 | 
  
    | 37 |  * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
 | 
  
    | 38 |  * @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $
 | 
  
    | 39 |  */
 | 
  
    | 40 | 
 | 
  
    | 41 | /**
 | 
  
    | 42 |  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
 | 
  
    | 43 |  * commands except TURN which will always return a not implemented
 | 
  
    | 44 |  * error. SMTP also provides some utility methods for sending mail
 | 
  
    | 45 |  * to an SMTP server.
 | 
  
    | 46 |  * original author: Chris Ryan
 | 
  
    | 47 |  */
 | 
  
    | 48 | 
 | 
  
    | 49 | class SMTP {
 | 
  
    | 50 |   /**
 | 
  
    | 51 |    *  SMTP server port
 | 
  
    | 52 |    *  @var int
 | 
  
    | 53 |    */
 | 
  
    | 54 |   public $SMTP_PORT = 25;
 | 
  
    | 55 | 
 | 
  
    | 56 |   /**
 | 
  
    | 57 |    *  SMTP reply line ending
 | 
  
    | 58 |    *  @var string
 | 
  
    | 59 |    */
 | 
  
    | 60 |   public $CRLF = "\r\n";
 | 
  
    | 61 | 
 | 
  
    | 62 |   /**
 | 
  
    | 63 |    *  Sets whether debugging is turned on
 | 
  
    | 64 |    *  @var bool
 | 
  
    | 65 |    */
 | 
  
    | 66 |   public $do_debug;       // the level of debug to perform
 | 
  
    | 67 | 
 | 
  
    | 68 |   /**
 | 
  
    | 69 |    *  Sets VERP use on/off (default is off)
 | 
  
    | 70 |    *  @var bool
 | 
  
    | 71 |    */
 | 
  
    | 72 |   public $do_verp = false;
 | 
  
    | 73 | 
 | 
  
    | 74 |   /////////////////////////////////////////////////
 | 
  
    | 75 |   // PROPERTIES, PRIVATE AND PROTECTED
 | 
  
    | 76 |   /////////////////////////////////////////////////
 | 
  
    | 77 | 
 | 
  
    | 78 |   private $smtp_conn; // the socket to the server
 | 
  
    | 79 |   private $error;     // error if any on the last call
 | 
  
    | 80 |   private $helo_rply; // the reply the server sent to us for HELO
 | 
  
    | 81 | 
 | 
  
    | 82 |   /**
 | 
  
    | 83 |    * Initialize the class so that the data is in a known state.
 | 
  
    | 84 |    * @access public
 | 
  
    | 85 |    * @return void
 | 
  
    | 86 |    */
 | 
  
    | 87 |   public function __construct() {
 | 
  
    | 88 |     $this->smtp_conn = 0;
 | 
  
    | 89 |     $this->error = null;
 | 
  
    | 90 |     $this->helo_rply = null;
 | 
  
    | 91 | 
 | 
  
    | 92 |     $this->do_debug = 0;
 | 
  
    | 93 |   }
 | 
  
    | 94 | 
 | 
  
    | 95 |   /////////////////////////////////////////////////
 | 
  
    | 96 |   // CONNECTION FUNCTIONS
 | 
  
    | 97 |   /////////////////////////////////////////////////
 | 
  
    | 98 | 
 | 
  
    | 99 |   /**
 | 
  
    | 100 |    * Connect to the server specified on the port specified.
 | 
  
    | 101 |    * If the port is not specified use the default SMTP_PORT.
 | 
  
    | 102 |    * If tval is specified then a connection will try and be
 | 
  
    | 103 |    * established with the server for that number of seconds.
 | 
  
    | 104 |    * If tval is not specified the default is 30 seconds to
 | 
  
    | 105 |    * try on the connection.
 | 
  
    | 106 |    *
 | 
  
    | 107 |    * SMTP CODE SUCCESS: 220
 | 
  
    | 108 |    * SMTP CODE FAILURE: 421
 | 
  
    | 109 |    * @access public
 | 
  
    | 110 |    * @return bool
 | 
  
    | 111 |    */
 | 
  
    | 112 |   public function Connect($host, $port = 0, $tval = 30) {
 | 
  
    | 113 |     // set the error val to null so there is no confusion
 | 
  
    | 114 |     $this->error = null;
 | 
  
    | 115 | 
 | 
  
    | 116 |     // make sure we are __not__ connected
 | 
  
    | 117 |     if($this->connected()) {
 | 
  
    | 118 |       // already connected, generate error
 | 
  
    | 119 |       $this->error = array("error" => "Already connected to a server");
 | 
  
    | 120 |       return false;
 | 
  
    | 121 |     }
 | 
  
    | 122 | 
 | 
  
    | 123 |     if(empty($port)) {
 | 
  
    | 124 |       $port = $this->SMTP_PORT;
 | 
  
    | 125 |     }
 | 
  
    | 126 | 
 | 
  
    | 127 |     // connect to the smtp server
 | 
  
    | 128 |     $this->smtp_conn = @fsockopen($host,    // the host of the server
 | 
  
    | 129 |                                  $port,    // the port to use
 | 
  
    | 130 |                                  $errno,   // error number if any
 | 
  
    | 131 |                                  $errstr,  // error message if any
 | 
  
    | 132 |                                  $tval);   // give up after ? secs
 | 
  
    | 133 |     // verify we connected properly
 | 
  
    | 134 |     if(empty($this->smtp_conn)) {
 | 
  
    | 135 |       $this->error = array("error" => "Failed to connect to server",
 | 
  
    | 136 |                            "errno" => $errno,
 | 
  
    | 137 |                            "errstr" => $errstr);
 | 
  
    | 138 |       if($this->do_debug >= 1) {
 | 
  
    | 139 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
 | 
  
    | 140 |       }
 | 
  
    | 141 |       return false;
 | 
  
    | 142 |     }
 | 
  
    | 143 | 
 | 
  
    | 144 |     // SMTP server can take longer to respond, give longer timeout for first read
 | 
  
    | 145 |     // Windows does not have support for this timeout function
 | 
  
    | 146 |     if(substr(PHP_OS, 0, 3) != "WIN")
 | 
  
    | 147 |      socket_set_timeout($this->smtp_conn, $tval, 0);
 | 
  
    | 148 | 
 | 
  
    | 149 |     // get any announcement
 | 
  
    | 150 |     $announce = $this->get_lines();
 | 
  
    | 151 | 
 | 
  
    | 152 |     if($this->do_debug >= 2) {
 | 
  
    | 153 |       echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
 | 
  
    | 154 |     }
 | 
  
    | 155 | 
 | 
  
    | 156 |     return true;
 | 
  
    | 157 |   }
 | 
  
    | 158 | 
 | 
  
    | 159 |   /**
 | 
  
    | 160 |    * Initiate a TLS communication with the server.
 | 
  
    | 161 |    *
 | 
  
    | 162 |    * SMTP CODE 220 Ready to start TLS
 | 
  
    | 163 |    * SMTP CODE 501 Syntax error (no parameters allowed)
 | 
  
    | 164 |    * SMTP CODE 454 TLS not available due to temporary reason
 | 
  
    | 165 |    * @access public
 | 
  
    | 166 |    * @return bool success
 | 
  
    | 167 |    */
 | 
  
    | 168 |   public function StartTLS() {
 | 
  
    | 169 |     $this->error = null; # to avoid confusion
 | 
  
    | 170 | 
 | 
  
    | 171 |     if(!$this->connected()) {
 | 
  
    | 172 |       $this->error = array("error" => "Called StartTLS() without being connected");
 | 
  
    | 173 |       return false;
 | 
  
    | 174 |     }
 | 
  
    | 175 | 
 | 
  
    | 176 |     fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
 | 
  
    | 177 | 
 | 
  
    | 178 |     $rply = $this->get_lines();
 | 
  
    | 179 |     $code = substr($rply,0,3);
 | 
  
    | 180 | 
 | 
  
    | 181 |     if($this->do_debug >= 2) {
 | 
  
    | 182 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 183 |     }
 | 
  
    | 184 | 
 | 
  
    | 185 |     if($code != 220) {
 | 
  
    | 186 |       $this->error =
 | 
  
    | 187 |          array("error"     => "STARTTLS not accepted from server",
 | 
  
    | 188 |                "smtp_code" => $code,
 | 
  
    | 189 |                "smtp_msg"  => substr($rply,4));
 | 
  
    | 190 |       if($this->do_debug >= 1) {
 | 
  
    | 191 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 192 |       }
 | 
  
    | 193 |       return false;
 | 
  
    | 194 |     }
 | 
  
    | 195 | 
 | 
  
    | 196 |     // Begin encrypted connection
 | 
  
    | 197 |     if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
 | 
  
    | 198 |       return false;
 | 
  
    | 199 |     }
 | 
  
    | 200 | 
 | 
  
    | 201 |     return true;
 | 
  
    | 202 |   }
 | 
  
    | 203 | 
 | 
  
    | 204 |   /**
 | 
  
    | 205 |    * Performs SMTP authentication.  Must be run after running the
 | 
  
    | 206 |    * Hello() method.  Returns true if successfully authenticated.
 | 
  
    | 207 |    * @access public
 | 
  
    | 208 |    * @return bool
 | 
  
    | 209 |    */
 | 
  
    | 210 |   public function Authenticate($username, $password) {
 | 
  
    | 211 |     // Start authentication
 | 
  
    | 212 |     fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
 | 
  
    | 213 | 
 | 
  
    | 214 |     $rply = $this->get_lines();
 | 
  
    | 215 |     $code = substr($rply,0,3);
 | 
  
    | 216 | 
 | 
  
    | 217 |     if($code != 334) {
 | 
  
    | 218 |       $this->error =
 | 
  
    | 219 |         array("error" => "AUTH not accepted from server",
 | 
  
    | 220 |               "smtp_code" => $code,
 | 
  
    | 221 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 222 |       if($this->do_debug >= 1) {
 | 
  
    | 223 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 224 |       }
 | 
  
    | 225 |       return false;
 | 
  
    | 226 |     }
 | 
  
    | 227 | 
 | 
  
    | 228 |     // Send encoded username
 | 
  
    | 229 |     fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
 | 
  
    | 230 | 
 | 
  
    | 231 |     $rply = $this->get_lines();
 | 
  
    | 232 |     $code = substr($rply,0,3);
 | 
  
    | 233 | 
 | 
  
    | 234 |     if($code != 334) {
 | 
  
    | 235 |       $this->error =
 | 
  
    | 236 |         array("error" => "Username not accepted from server",
 | 
  
    | 237 |               "smtp_code" => $code,
 | 
  
    | 238 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 239 |       if($this->do_debug >= 1) {
 | 
  
    | 240 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 241 |       }
 | 
  
    | 242 |       return false;
 | 
  
    | 243 |     }
 | 
  
    | 244 | 
 | 
  
    | 245 |     // Send encoded password
 | 
  
    | 246 |     fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
 | 
  
    | 247 | 
 | 
  
    | 248 |     $rply = $this->get_lines();
 | 
  
    | 249 |     $code = substr($rply,0,3);
 | 
  
    | 250 | 
 | 
  
    | 251 |     if($code != 235) {
 | 
  
    | 252 |       $this->error =
 | 
  
    | 253 |         array("error" => "Password not accepted from server",
 | 
  
    | 254 |               "smtp_code" => $code,
 | 
  
    | 255 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 256 |       if($this->do_debug >= 1) {
 | 
  
    | 257 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 258 |       }
 | 
  
    | 259 |       return false;
 | 
  
    | 260 |     }
 | 
  
    | 261 | 
 | 
  
    | 262 |     return true;
 | 
  
    | 263 |   }
 | 
  
    | 264 | 
 | 
  
    | 265 |   /**
 | 
  
    | 266 |    * Returns true if connected to a server otherwise false
 | 
  
    | 267 |    * @access public
 | 
  
    | 268 |    * @return bool
 | 
  
    | 269 |    */
 | 
  
    | 270 |   public function Connected() {
 | 
  
    | 271 |     if(!empty($this->smtp_conn)) {
 | 
  
    | 272 |       $sock_status = socket_get_status($this->smtp_conn);
 | 
  
    | 273 |       if($sock_status["eof"]) {
 | 
  
    | 274 |         // the socket is valid but we are not connected
 | 
  
    | 275 |         if($this->do_debug >= 1) {
 | 
  
    | 276 |             echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
 | 
  
    | 277 |         }
 | 
  
    | 278 |         $this->Close();
 | 
  
    | 279 |         return false;
 | 
  
    | 280 |       }
 | 
  
    | 281 |       return true; // everything looks good
 | 
  
    | 282 |     }
 | 
  
    | 283 |     return false;
 | 
  
    | 284 |   }
 | 
  
    | 285 | 
 | 
  
    | 286 |   /**
 | 
  
    | 287 |    * Closes the socket and cleans up the state of the class.
 | 
  
    | 288 |    * It is not considered good to use this function without
 | 
  
    | 289 |    * first trying to use QUIT.
 | 
  
    | 290 |    * @access public
 | 
  
    | 291 |    * @return void
 | 
  
    | 292 |    */
 | 
  
    | 293 |   public function Close() {
 | 
  
    | 294 |     $this->error = null; // so there is no confusion
 | 
  
    | 295 |     $this->helo_rply = null;
 | 
  
    | 296 |     if(!empty($this->smtp_conn)) {
 | 
  
    | 297 |       // close the connection and cleanup
 | 
  
    | 298 |       fclose($this->smtp_conn);
 | 
  
    | 299 |       $this->smtp_conn = 0;
 | 
  
    | 300 |     }
 | 
  
    | 301 |   }
 | 
  
    | 302 | 
 | 
  
    | 303 |   /////////////////////////////////////////////////
 | 
  
    | 304 |   // SMTP COMMANDS
 | 
  
    | 305 |   /////////////////////////////////////////////////
 | 
  
    | 306 | 
 | 
  
    | 307 |   /**
 | 
  
    | 308 |    * Issues a data command and sends the msg_data to the server
 | 
  
    | 309 |    * finializing the mail transaction. $msg_data is the message
 | 
  
    | 310 |    * that is to be send with the headers. Each header needs to be
 | 
  
    | 311 |    * on a single line followed by a <CRLF> with the message headers
 | 
  
    | 312 |    * and the message body being seperated by and additional <CRLF>.
 | 
  
    | 313 |    *
 | 
  
    | 314 |    * Implements rfc 821: DATA <CRLF>
 | 
  
    | 315 |    *
 | 
  
    | 316 |    * SMTP CODE INTERMEDIATE: 354
 | 
  
    | 317 |    *     [data]
 | 
  
    | 318 |    *     <CRLF>.<CRLF>
 | 
  
    | 319 |    *     SMTP CODE SUCCESS: 250
 | 
  
    | 320 |    *     SMTP CODE FAILURE: 552,554,451,452
 | 
  
    | 321 |    * SMTP CODE FAILURE: 451,554
 | 
  
    | 322 |    * SMTP CODE ERROR  : 500,501,503,421
 | 
  
    | 323 |    * @access public
 | 
  
    | 324 |    * @return bool
 | 
  
    | 325 |    */
 | 
  
    | 326 |   public function Data($msg_data) {
 | 
  
    | 327 |     $this->error = null; // so no confusion is caused
 | 
  
    | 328 | 
 | 
  
    | 329 |     if(!$this->connected()) {
 | 
  
    | 330 |       $this->error = array(
 | 
  
    | 331 |               "error" => "Called Data() without being connected");
 | 
  
    | 332 |       return false;
 | 
  
    | 333 |     }
 | 
  
    | 334 | 
 | 
  
    | 335 |     fputs($this->smtp_conn,"DATA" . $this->CRLF);
 | 
  
    | 336 | 
 | 
  
    | 337 |     $rply = $this->get_lines();
 | 
  
    | 338 |     $code = substr($rply,0,3);
 | 
  
    | 339 | 
 | 
  
    | 340 |     if($this->do_debug >= 2) {
 | 
  
    | 341 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 342 |     }
 | 
  
    | 343 | 
 | 
  
    | 344 |     if($code != 354) {
 | 
  
    | 345 |       $this->error =
 | 
  
    | 346 |         array("error" => "DATA command not accepted from server",
 | 
  
    | 347 |               "smtp_code" => $code,
 | 
  
    | 348 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 349 |       if($this->do_debug >= 1) {
 | 
  
    | 350 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 351 |       }
 | 
  
    | 352 |       return false;
 | 
  
    | 353 |     }
 | 
  
    | 354 | 
 | 
  
    | 355 |     /* the server is ready to accept data!
 | 
  
    | 356 |      * according to rfc 821 we should not send more than 1000
 | 
  
    | 357 |      * including the CRLF
 | 
  
    | 358 |      * characters on a single line so we will break the data up
 | 
  
    | 359 |      * into lines by \r and/or \n then if needed we will break
 | 
  
    | 360 |      * each of those into smaller lines to fit within the limit.
 | 
  
    | 361 |      * in addition we will be looking for lines that start with
 | 
  
    | 362 |      * a period '.' and append and additional period '.' to that
 | 
  
    | 363 |      * line. NOTE: this does not count towards limit.
 | 
  
    | 364 |      */
 | 
  
    | 365 | 
 | 
  
    | 366 |     // normalize the line breaks so we know the explode works
 | 
  
    | 367 |     $msg_data = str_replace("\r\n","\n",$msg_data);
 | 
  
    | 368 |     $msg_data = str_replace("\r","\n",$msg_data);
 | 
  
    | 369 |     $lines = explode("\n",$msg_data);
 | 
  
    | 370 | 
 | 
  
    | 371 |     /* we need to find a good way to determine is headers are
 | 
  
    | 372 |      * in the msg_data or if it is a straight msg body
 | 
  
    | 373 |      * currently I am assuming rfc 822 definitions of msg headers
 | 
  
    | 374 |      * and if the first field of the first line (':' sperated)
 | 
  
    | 375 |      * does not contain a space then it _should_ be a header
 | 
  
    | 376 |      * and we can process all lines before a blank "" line as
 | 
  
    | 377 |      * headers.
 | 
  
    | 378 |      */
 | 
  
    | 379 | 
 | 
  
    | 380 |     $field = substr($lines[0],0,strpos($lines[0],":"));
 | 
  
    | 381 |     $in_headers = false;
 | 
  
    | 382 |     if(!empty($field) && !strstr($field," ")) {
 | 
  
    | 383 |       $in_headers = true;
 | 
  
    | 384 |     }
 | 
  
    | 385 | 
 | 
  
    | 386 |     $max_line_length = 998; // used below; set here for ease in change
 | 
  
    | 387 | 
 | 
  
    | 388 |     while(list(,$line) = @each($lines)) {
 | 
  
    | 389 |       $lines_out = null;
 | 
  
    | 390 |       if($line == "" && $in_headers) {
 | 
  
    | 391 |         $in_headers = false;
 | 
  
    | 392 |       }
 | 
  
    | 393 |       // ok we need to break this line up into several smaller lines
 | 
  
    | 394 |       while(strlen($line) > $max_line_length) {
 | 
  
    | 395 |         $pos = strrpos(substr($line,0,$max_line_length)," ");
 | 
  
    | 396 | 
 | 
  
    | 397 |         // Patch to fix DOS attack
 | 
  
    | 398 |         if(!$pos) {
 | 
  
    | 399 |           $pos = $max_line_length - 1;
 | 
  
    | 400 |           $lines_out[] = substr($line,0,$pos);
 | 
  
    | 401 |           $line = substr($line,$pos);
 | 
  
    | 402 |         } else {
 | 
  
    | 403 |           $lines_out[] = substr($line,0,$pos);
 | 
  
    | 404 |           $line = substr($line,$pos + 1);
 | 
  
    | 405 |         }
 | 
  
    | 406 | 
 | 
  
    | 407 |         /* if processing headers add a LWSP-char to the front of new line
 | 
  
    | 408 |          * rfc 822 on long msg headers
 | 
  
    | 409 |          */
 | 
  
    | 410 |         if($in_headers) {
 | 
  
    | 411 |           $line = "\t" . $line;
 | 
  
    | 412 |         }
 | 
  
    | 413 |       }
 | 
  
    | 414 |       $lines_out[] = $line;
 | 
  
    | 415 | 
 | 
  
    | 416 |       // send the lines to the server
 | 
  
    | 417 |       while(list(,$line_out) = @each($lines_out)) {
 | 
  
    | 418 |         if(strlen($line_out) > 0)
 | 
  
    | 419 |         {
 | 
  
    | 420 |           if(substr($line_out, 0, 1) == ".") {
 | 
  
    | 421 |             $line_out = "." . $line_out;
 | 
  
    | 422 |           }
 | 
  
    | 423 |         }
 | 
  
    | 424 |         fputs($this->smtp_conn,$line_out . $this->CRLF);
 | 
  
    | 425 |       }
 | 
  
    | 426 |     }
 | 
  
    | 427 | 
 | 
  
    | 428 |     // message data has been sent
 | 
  
    | 429 |     fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
 | 
  
    | 430 | 
 | 
  
    | 431 |     $rply = $this->get_lines();
 | 
  
    | 432 |     $code = substr($rply,0,3);
 | 
  
    | 433 | 
 | 
  
    | 434 |     if($this->do_debug >= 2) {
 | 
  
    | 435 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 436 |     }
 | 
  
    | 437 | 
 | 
  
    | 438 |     if($code != 250) {
 | 
  
    | 439 |       $this->error =
 | 
  
    | 440 |         array("error" => "DATA not accepted from server",
 | 
  
    | 441 |               "smtp_code" => $code,
 | 
  
    | 442 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 443 |       if($this->do_debug >= 1) {
 | 
  
    | 444 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 445 |       }
 | 
  
    | 446 |       return false;
 | 
  
    | 447 |     }
 | 
  
    | 448 |     return true;
 | 
  
    | 449 |   }
 | 
  
    | 450 | 
 | 
  
    | 451 |   /**
 | 
  
    | 452 |    * Sends the HELO command to the smtp server.
 | 
  
    | 453 |    * This makes sure that we and the server are in
 | 
  
    | 454 |    * the same known state.
 | 
  
    | 455 |    *
 | 
  
    | 456 |    * Implements from rfc 821: HELO <SP> <domain> <CRLF>
 | 
  
    | 457 |    *
 | 
  
    | 458 |    * SMTP CODE SUCCESS: 250
 | 
  
    | 459 |    * SMTP CODE ERROR  : 500, 501, 504, 421
 | 
  
    | 460 |    * @access public
 | 
  
    | 461 |    * @return bool
 | 
  
    | 462 |    */
 | 
  
    | 463 |   public function Hello($host = '') {
 | 
  
    | 464 |     $this->error = null; // so no confusion is caused
 | 
  
    | 465 | 
 | 
  
    | 466 |     if(!$this->connected()) {
 | 
  
    | 467 |       $this->error = array(
 | 
  
    | 468 |             "error" => "Called Hello() without being connected");
 | 
  
    | 469 |       return false;
 | 
  
    | 470 |     }
 | 
  
    | 471 | 
 | 
  
    | 472 |     // if hostname for HELO was not specified send default
 | 
  
    | 473 |     if(empty($host)) {
 | 
  
    | 474 |       // determine appropriate default to send to server
 | 
  
    | 475 |       $host = "localhost";
 | 
  
    | 476 |     }
 | 
  
    | 477 | 
 | 
  
    | 478 |     // Send extended hello first (RFC 2821)
 | 
  
    | 479 |     if(!$this->SendHello("EHLO", $host)) {
 | 
  
    | 480 |       if(!$this->SendHello("HELO", $host)) {
 | 
  
    | 481 |         return false;
 | 
  
    | 482 |       }
 | 
  
    | 483 |     }
 | 
  
    | 484 | 
 | 
  
    | 485 |     return true;
 | 
  
    | 486 |   }
 | 
  
    | 487 | 
 | 
  
    | 488 |   /**
 | 
  
    | 489 |    * Sends a HELO/EHLO command.
 | 
  
    | 490 |    * @access private
 | 
  
    | 491 |    * @return bool
 | 
  
    | 492 |    */
 | 
  
    | 493 |   private function SendHello($hello, $host) {
 | 
  
    | 494 |     fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
 | 
  
    | 495 | 
 | 
  
    | 496 |     $rply = $this->get_lines();
 | 
  
    | 497 |     $code = substr($rply,0,3);
 | 
  
    | 498 | 
 | 
  
    | 499 |     if($this->do_debug >= 2) {
 | 
  
    | 500 |       echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
 | 
  
    | 501 |     }
 | 
  
    | 502 | 
 | 
  
    | 503 |     if($code != 250) {
 | 
  
    | 504 |       $this->error =
 | 
  
    | 505 |         array("error" => $hello . " not accepted from server",
 | 
  
    | 506 |               "smtp_code" => $code,
 | 
  
    | 507 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 508 |       if($this->do_debug >= 1) {
 | 
  
    | 509 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 510 |       }
 | 
  
    | 511 |       return false;
 | 
  
    | 512 |     }
 | 
  
    | 513 | 
 | 
  
    | 514 |     $this->helo_rply = $rply;
 | 
  
    | 515 | 
 | 
  
    | 516 |     return true;
 | 
  
    | 517 |   }
 | 
  
    | 518 | 
 | 
  
    | 519 |   /**
 | 
  
    | 520 |    * Starts a mail transaction from the email address specified in
 | 
  
    | 521 |    * $from. Returns true if successful or false otherwise. If True
 | 
  
    | 522 |    * the mail transaction is started and then one or more Recipient
 | 
  
    | 523 |    * commands may be called followed by a Data command.
 | 
  
    | 524 |    *
 | 
  
    | 525 |    * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
 | 
  
    | 526 |    *
 | 
  
    | 527 |    * SMTP CODE SUCCESS: 250
 | 
  
    | 528 |    * SMTP CODE SUCCESS: 552,451,452
 | 
  
    | 529 |    * SMTP CODE SUCCESS: 500,501,421
 | 
  
    | 530 |    * @access public
 | 
  
    | 531 |    * @return bool
 | 
  
    | 532 |    */
 | 
  
    | 533 |   public function Mail($from) {
 | 
  
    | 534 |     $this->error = null; // so no confusion is caused
 | 
  
    | 535 | 
 | 
  
    | 536 |     if(!$this->connected()) {
 | 
  
    | 537 |       $this->error = array(
 | 
  
    | 538 |               "error" => "Called Mail() without being connected");
 | 
  
    | 539 |       return false;
 | 
  
    | 540 |     }
 | 
  
    | 541 | 
 | 
  
    | 542 |     $useVerp = ($this->do_verp ? "XVERP" : "");
 | 
  
    | 543 |     fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
 | 
  
    | 544 | 
 | 
  
    | 545 |     $rply = $this->get_lines();
 | 
  
    | 546 |     $code = substr($rply,0,3);
 | 
  
    | 547 | 
 | 
  
    | 548 |     if($this->do_debug >= 2) {
 | 
  
    | 549 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 550 |     }
 | 
  
    | 551 | 
 | 
  
    | 552 |     if($code != 250) {
 | 
  
    | 553 |       $this->error =
 | 
  
    | 554 |         array("error" => "MAIL not accepted from server",
 | 
  
    | 555 |               "smtp_code" => $code,
 | 
  
    | 556 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 557 |       if($this->do_debug >= 1) {
 | 
  
    | 558 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 559 |       }
 | 
  
    | 560 |       return false;
 | 
  
    | 561 |     }
 | 
  
    | 562 |     return true;
 | 
  
    | 563 |   }
 | 
  
    | 564 | 
 | 
  
    | 565 |   /**
 | 
  
    | 566 |    * Sends the quit command to the server and then closes the socket
 | 
  
    | 567 |    * if there is no error or the $close_on_error argument is true.
 | 
  
    | 568 |    *
 | 
  
    | 569 |    * Implements from rfc 821: QUIT <CRLF>
 | 
  
    | 570 |    *
 | 
  
    | 571 |    * SMTP CODE SUCCESS: 221
 | 
  
    | 572 |    * SMTP CODE ERROR  : 500
 | 
  
    | 573 |    * @access public
 | 
  
    | 574 |    * @return bool
 | 
  
    | 575 |    */
 | 
  
    | 576 |   public function Quit($close_on_error = true) {
 | 
  
    | 577 |     $this->error = null; // so there is no confusion
 | 
  
    | 578 | 
 | 
  
    | 579 |     if(!$this->connected()) {
 | 
  
    | 580 |       $this->error = array(
 | 
  
    | 581 |               "error" => "Called Quit() without being connected");
 | 
  
    | 582 |       return false;
 | 
  
    | 583 |     }
 | 
  
    | 584 | 
 | 
  
    | 585 |     // send the quit command to the server
 | 
  
    | 586 |     fputs($this->smtp_conn,"quit" . $this->CRLF);
 | 
  
    | 587 | 
 | 
  
    | 588 |     // get any good-bye messages
 | 
  
    | 589 |     $byemsg = $this->get_lines();
 | 
  
    | 590 | 
 | 
  
    | 591 |     if($this->do_debug >= 2) {
 | 
  
    | 592 |       echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
 | 
  
    | 593 |     }
 | 
  
    | 594 | 
 | 
  
    | 595 |     $rval = true;
 | 
  
    | 596 |     $e = null;
 | 
  
    | 597 | 
 | 
  
    | 598 |     $code = substr($byemsg,0,3);
 | 
  
    | 599 |     if($code != 221) {
 | 
  
    | 600 |       // use e as a tmp var cause Close will overwrite $this->error
 | 
  
    | 601 |       $e = array("error" => "SMTP server rejected quit command",
 | 
  
    | 602 |                  "smtp_code" => $code,
 | 
  
    | 603 |                  "smtp_rply" => substr($byemsg,4));
 | 
  
    | 604 |       $rval = false;
 | 
  
    | 605 |       if($this->do_debug >= 1) {
 | 
  
    | 606 |         echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
 | 
  
    | 607 |       }
 | 
  
    | 608 |     }
 | 
  
    | 609 | 
 | 
  
    | 610 |     if(empty($e) || $close_on_error) {
 | 
  
    | 611 |       $this->Close();
 | 
  
    | 612 |     }
 | 
  
    | 613 | 
 | 
  
    | 614 |     return $rval;
 | 
  
    | 615 |   }
 | 
  
    | 616 | 
 | 
  
    | 617 |   /**
 | 
  
    | 618 |    * Sends the command RCPT to the SMTP server with the TO: argument of $to.
 | 
  
    | 619 |    * Returns true if the recipient was accepted false if it was rejected.
 | 
  
    | 620 |    *
 | 
  
    | 621 |    * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
 | 
  
    | 622 |    *
 | 
  
    | 623 |    * SMTP CODE SUCCESS: 250,251
 | 
  
    | 624 |    * SMTP CODE FAILURE: 550,551,552,553,450,451,452
 | 
  
    | 625 |    * SMTP CODE ERROR  : 500,501,503,421
 | 
  
    | 626 |    * @access public
 | 
  
    | 627 |    * @return bool
 | 
  
    | 628 |    */
 | 
  
    | 629 |   public function Recipient($to) {
 | 
  
    | 630 |     $this->error = null; // so no confusion is caused
 | 
  
    | 631 | 
 | 
  
    | 632 |     if(!$this->connected()) {
 | 
  
    | 633 |       $this->error = array(
 | 
  
    | 634 |               "error" => "Called Recipient() without being connected");
 | 
  
    | 635 |       return false;
 | 
  
    | 636 |     }
 | 
  
    | 637 | 
 | 
  
    | 638 |     fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
 | 
  
    | 639 | 
 | 
  
    | 640 |     $rply = $this->get_lines();
 | 
  
    | 641 |     $code = substr($rply,0,3);
 | 
  
    | 642 | 
 | 
  
    | 643 |     if($this->do_debug >= 2) {
 | 
  
    | 644 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 645 |     }
 | 
  
    | 646 | 
 | 
  
    | 647 |     if($code != 250 && $code != 251) {
 | 
  
    | 648 |       $this->error =
 | 
  
    | 649 |         array("error" => "RCPT not accepted from server",
 | 
  
    | 650 |               "smtp_code" => $code,
 | 
  
    | 651 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 652 |       if($this->do_debug >= 1) {
 | 
  
    | 653 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 654 |       }
 | 
  
    | 655 |       return false;
 | 
  
    | 656 |     }
 | 
  
    | 657 |     return true;
 | 
  
    | 658 |   }
 | 
  
    | 659 | 
 | 
  
    | 660 |   /**
 | 
  
    | 661 |    * Sends the RSET command to abort and transaction that is
 | 
  
    | 662 |    * currently in progress. Returns true if successful false
 | 
  
    | 663 |    * otherwise.
 | 
  
    | 664 |    *
 | 
  
    | 665 |    * Implements rfc 821: RSET <CRLF>
 | 
  
    | 666 |    *
 | 
  
    | 667 |    * SMTP CODE SUCCESS: 250
 | 
  
    | 668 |    * SMTP CODE ERROR  : 500,501,504,421
 | 
  
    | 669 |    * @access public
 | 
  
    | 670 |    * @return bool
 | 
  
    | 671 |    */
 | 
  
    | 672 |   public function Reset() {
 | 
  
    | 673 |     $this->error = null; // so no confusion is caused
 | 
  
    | 674 | 
 | 
  
    | 675 |     if(!$this->connected()) {
 | 
  
    | 676 |       $this->error = array(
 | 
  
    | 677 |               "error" => "Called Reset() without being connected");
 | 
  
    | 678 |       return false;
 | 
  
    | 679 |     }
 | 
  
    | 680 | 
 | 
  
    | 681 |     fputs($this->smtp_conn,"RSET" . $this->CRLF);
 | 
  
    | 682 | 
 | 
  
    | 683 |     $rply = $this->get_lines();
 | 
  
    | 684 |     $code = substr($rply,0,3);
 | 
  
    | 685 | 
 | 
  
    | 686 |     if($this->do_debug >= 2) {
 | 
  
    | 687 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 688 |     }
 | 
  
    | 689 | 
 | 
  
    | 690 |     if($code != 250) {
 | 
  
    | 691 |       $this->error =
 | 
  
    | 692 |         array("error" => "RSET failed",
 | 
  
    | 693 |               "smtp_code" => $code,
 | 
  
    | 694 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 695 |       if($this->do_debug >= 1) {
 | 
  
    | 696 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 697 |       }
 | 
  
    | 698 |       return false;
 | 
  
    | 699 |     }
 | 
  
    | 700 | 
 | 
  
    | 701 |     return true;
 | 
  
    | 702 |   }
 | 
  
    | 703 | 
 | 
  
    | 704 |   /**
 | 
  
    | 705 |    * Starts a mail transaction from the email address specified in
 | 
  
    | 706 |    * $from. Returns true if successful or false otherwise. If True
 | 
  
    | 707 |    * the mail transaction is started and then one or more Recipient
 | 
  
    | 708 |    * commands may be called followed by a Data command. This command
 | 
  
    | 709 |    * will send the message to the users terminal if they are logged
 | 
  
    | 710 |    * in and send them an email.
 | 
  
    | 711 |    *
 | 
  
    | 712 |    * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
 | 
  
    | 713 |    *
 | 
  
    | 714 |    * SMTP CODE SUCCESS: 250
 | 
  
    | 715 |    * SMTP CODE SUCCESS: 552,451,452
 | 
  
    | 716 |    * SMTP CODE SUCCESS: 500,501,502,421
 | 
  
    | 717 |    * @access public
 | 
  
    | 718 |    * @return bool
 | 
  
    | 719 |    */
 | 
  
    | 720 |   public function SendAndMail($from) {
 | 
  
    | 721 |     $this->error = null; // so no confusion is caused
 | 
  
    | 722 | 
 | 
  
    | 723 |     if(!$this->connected()) {
 | 
  
    | 724 |       $this->error = array(
 | 
  
    | 725 |           "error" => "Called SendAndMail() without being connected");
 | 
  
    | 726 |       return false;
 | 
  
    | 727 |     }
 | 
  
    | 728 | 
 | 
  
    | 729 |     fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
 | 
  
    | 730 | 
 | 
  
    | 731 |     $rply = $this->get_lines();
 | 
  
    | 732 |     $code = substr($rply,0,3);
 | 
  
    | 733 | 
 | 
  
    | 734 |     if($this->do_debug >= 2) {
 | 
  
    | 735 |       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 | 
  
    | 736 |     }
 | 
  
    | 737 | 
 | 
  
    | 738 |     if($code != 250) {
 | 
  
    | 739 |       $this->error =
 | 
  
    | 740 |         array("error" => "SAML not accepted from server",
 | 
  
    | 741 |               "smtp_code" => $code,
 | 
  
    | 742 |               "smtp_msg" => substr($rply,4));
 | 
  
    | 743 |       if($this->do_debug >= 1) {
 | 
  
    | 744 |         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
 | 
  
    | 745 |       }
 | 
  
    | 746 |       return false;
 | 
  
    | 747 |     }
 | 
  
    | 748 |     return true;
 | 
  
    | 749 |   }
 | 
  
    | 750 | 
 | 
  
    | 751 |   /**
 | 
  
    | 752 |    * This is an optional command for SMTP that this class does not
 | 
  
    | 753 |    * support. This method is here to make the RFC821 Definition
 | 
  
    | 754 |    * complete for this class and __may__ be implimented in the future
 | 
  
    | 755 |    *
 | 
  
    | 756 |    * Implements from rfc 821: TURN <CRLF>
 | 
  
    | 757 |    *
 | 
  
    | 758 |    * SMTP CODE SUCCESS: 250
 | 
  
    | 759 |    * SMTP CODE FAILURE: 502
 | 
  
    | 760 |    * SMTP CODE ERROR  : 500, 503
 | 
  
    | 761 |    * @access public
 | 
  
    | 762 |    * @return bool
 | 
  
    | 763 |    */
 | 
  
    | 764 |   public function Turn() {
 | 
  
    | 765 |     $this->error = array("error" => "This method, TURN, of the SMTP ".
 | 
  
    | 766 |                                     "is not implemented");
 | 
  
    | 767 |     if($this->do_debug >= 1) {
 | 
  
    | 768 |       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
 | 
  
    | 769 |     }
 | 
  
    | 770 |     return false;
 | 
  
    | 771 |   }
 | 
  
    | 772 | 
 | 
  
    | 773 |   /**
 | 
  
    | 774 |   * Get the current error
 | 
  
    | 775 |   * @access public
 | 
  
    | 776 |   * @return array
 | 
  
    | 777 |   */
 | 
  
    | 778 |   public function getError() {
 | 
  
    | 779 |     return $this->error;
 | 
  
    | 780 |   }
 | 
  
    | 781 | 
 | 
  
    | 782 |   /////////////////////////////////////////////////
 | 
  
    | 783 |   // INTERNAL FUNCTIONS
 | 
  
    | 784 |   /////////////////////////////////////////////////
 | 
  
    | 785 | 
 | 
  
    | 786 |   /**
 | 
  
    | 787 |    * Read in as many lines as possible
 | 
  
    | 788 |    * either before eof or socket timeout occurs on the operation.
 | 
  
    | 789 |    * With SMTP we can tell if we have more lines to read if the
 | 
  
    | 790 |    * 4th character is '-' symbol. If it is a space then we don't
 | 
  
    | 791 |    * need to read anything else.
 | 
  
    | 792 |    * @access private
 | 
  
    | 793 |    * @return string
 | 
  
    | 794 |    */
 | 
  
    | 795 |   private function get_lines() {
 | 
  
    | 796 |     $data = "";
 | 
  
    | 797 |     while($str = @fgets($this->smtp_conn,515)) {
 | 
  
    | 798 |       if($this->do_debug >= 4) {
 | 
  
    | 799 |         echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
 | 
  
    | 800 |         echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
 | 
  
    | 801 |       }
 | 
  
    | 802 |       $data .= $str;
 | 
  
    | 803 |       if($this->do_debug >= 4) {
 | 
  
    | 804 |         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
 | 
  
    | 805 |       }
 | 
  
    | 806 |       // if 4th character is a space, we are done reading, break the loop
 | 
  
    | 807 |       if(substr($str,3,1) == " ") { break; }
 | 
  
    | 808 |     }
 | 
  
    | 809 |     return $data;
 | 
  
    | 810 |   }
 | 
  
    | 811 | 
 | 
  
    | 812 | }
 | 
  
    | 813 | 
 | 
  
    | 814 | ?>
 |