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