web/wp-includes/class-smtp.php
changeset 136 bde1974c263b
child 194 32102edaa81b
equal deleted inserted replaced
135:53cff4b4a802 136:bde1974c263b
       
     1 <?php
       
     2 /*~ class.smtp.php
       
     3 .---------------------------------------------------------------------------.
       
     4 |  Software: PHPMailer - PHP email class                                    |
       
     5 |   Version: 2.0.4                                                          |
       
     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 |    Author: Andy Prevost (project admininistrator)                         |
       
    11 |    Author: Brent R. Matzelle (original founder)                           |
       
    12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved.               |
       
    13 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
       
    14 | ------------------------------------------------------------------------- |
       
    15 |   License: Distributed under the Lesser General Public License (LGPL)     |
       
    16 |            http://www.gnu.org/copyleft/lesser.html                        |
       
    17 | This program is distributed in the hope that it will be useful - WITHOUT  |
       
    18 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
       
    19 | FITNESS FOR A PARTICULAR PURPOSE.                                         |
       
    20 | ------------------------------------------------------------------------- |
       
    21 | We offer a number of paid services (www.codeworxtech.com):                |
       
    22 | - Web Hosting on highly optimized fast and secure servers                 |
       
    23 | - Technology Consulting                                                   |
       
    24 | - Oursourcing (highly qualified programmers and graphic designers)        |
       
    25 '---------------------------------------------------------------------------'
       
    26  */
       
    27 /**
       
    28  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
       
    29  * commands except TURN which will always return a not implemented
       
    30  * error. SMTP also provides some utility methods for sending mail
       
    31  * to an SMTP server.
       
    32  * @package PHPMailer
       
    33  * @author Chris Ryan
       
    34  */
       
    35 
       
    36 class SMTP
       
    37 {
       
    38   /**
       
    39    *  SMTP server port
       
    40    *  @var int
       
    41    */
       
    42   var $SMTP_PORT = 25;
       
    43 
       
    44   /**
       
    45    *  SMTP reply line ending
       
    46    *  @var string
       
    47    */
       
    48   var $CRLF = "\r\n";
       
    49 
       
    50   /**
       
    51    *  Sets whether debugging is turned on
       
    52    *  @var bool
       
    53    */
       
    54   var $do_debug;       # the level of debug to perform
       
    55 
       
    56   /**
       
    57    *  Sets VERP use on/off (default is off)
       
    58    *  @var bool
       
    59    */
       
    60   var $do_verp = false;
       
    61 
       
    62   /**#@+
       
    63    * @access private
       
    64    */
       
    65   var $smtp_conn;      # the socket to the server
       
    66   var $error;          # error if any on the last call
       
    67   var $helo_rply;      # the reply the server sent to us for HELO
       
    68   /**#@-*/
       
    69 
       
    70   /**
       
    71    * Initialize the class so that the data is in a known state.
       
    72    * @access public
       
    73    * @return void
       
    74    */
       
    75   function SMTP() {
       
    76     $this->smtp_conn = 0;
       
    77     $this->error = null;
       
    78     $this->helo_rply = null;
       
    79 
       
    80     $this->do_debug = 0;
       
    81   }
       
    82 
       
    83   /*************************************************************
       
    84    *                    CONNECTION FUNCTIONS                  *
       
    85    ***********************************************************/
       
    86 
       
    87   /**
       
    88    * Connect to the server specified on the port specified.
       
    89    * If the port is not specified use the default SMTP_PORT.
       
    90    * If tval is specified then a connection will try and be
       
    91    * established with the server for that number of seconds.
       
    92    * If tval is not specified the default is 30 seconds to
       
    93    * try on the connection.
       
    94    *
       
    95    * SMTP CODE SUCCESS: 220
       
    96    * SMTP CODE FAILURE: 421
       
    97    * @access public
       
    98    * @return bool
       
    99    */
       
   100   function Connect($host,$port=0,$tval=30) {
       
   101     # set the error val to null so there is no confusion
       
   102     $this->error = null;
       
   103 
       
   104     # make sure we are __not__ connected
       
   105     if($this->connected()) {
       
   106       # ok we are connected! what should we do?
       
   107       # for now we will just give an error saying we
       
   108       # are already connected
       
   109       $this->error = array("error" => "Already connected to a server");
       
   110       return false;
       
   111     }
       
   112 
       
   113     if(empty($port)) {
       
   114       $port = $this->SMTP_PORT;
       
   115     }
       
   116 
       
   117     #connect to the smtp server
       
   118     $this->smtp_conn = fsockopen($host,    # the host of the server
       
   119                                  $port,    # the port to use
       
   120                                  $errno,   # error number if any
       
   121                                  $errstr,  # error message if any
       
   122                                  $tval);   # give up after ? secs
       
   123     # verify we connected properly
       
   124     if(empty($this->smtp_conn)) {
       
   125       $this->error = array("error" => "Failed to connect to server",
       
   126                            "errno" => $errno,
       
   127                            "errstr" => $errstr);
       
   128       if($this->do_debug >= 1) {
       
   129         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   130                  ": $errstr ($errno)" . $this->CRLF;
       
   131       }
       
   132       return false;
       
   133     }
       
   134 
       
   135     # sometimes the SMTP server takes a little longer to respond
       
   136     # so we will give it a longer timeout for the first read
       
   137     // Windows still does not have support for this timeout function
       
   138     if(substr(PHP_OS, 0, 3) != "WIN")
       
   139      socket_set_timeout($this->smtp_conn, $tval, 0);
       
   140 
       
   141     # get any announcement stuff
       
   142     $announce = $this->get_lines();
       
   143 
       
   144     # set the timeout  of any socket functions at 1/10 of a second
       
   145     //if(function_exists("socket_set_timeout"))
       
   146     //   socket_set_timeout($this->smtp_conn, 0, 100000);
       
   147 
       
   148     if($this->do_debug >= 2) {
       
   149       echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
       
   150     }
       
   151 
       
   152     return true;
       
   153   }
       
   154 
       
   155   /**
       
   156    * Performs SMTP authentication.  Must be run after running the
       
   157    * Hello() method.  Returns true if successfully authenticated.
       
   158    * @access public
       
   159    * @return bool
       
   160    */
       
   161   function Authenticate($username, $password) {
       
   162     // Start authentication
       
   163     fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
       
   164 
       
   165     $rply = $this->get_lines();
       
   166     $code = substr($rply,0,3);
       
   167 
       
   168     if($code != 334) {
       
   169       $this->error =
       
   170         array("error" => "AUTH not accepted from server",
       
   171               "smtp_code" => $code,
       
   172               "smtp_msg" => substr($rply,4));
       
   173       if($this->do_debug >= 1) {
       
   174         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   175                  ": " . $rply . $this->CRLF;
       
   176       }
       
   177       return false;
       
   178     }
       
   179 
       
   180     // Send encoded username
       
   181     fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
       
   182 
       
   183     $rply = $this->get_lines();
       
   184     $code = substr($rply,0,3);
       
   185 
       
   186     if($code != 334) {
       
   187       $this->error =
       
   188         array("error" => "Username not accepted from server",
       
   189               "smtp_code" => $code,
       
   190               "smtp_msg" => substr($rply,4));
       
   191       if($this->do_debug >= 1) {
       
   192         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   193                  ": " . $rply . $this->CRLF;
       
   194       }
       
   195       return false;
       
   196     }
       
   197 
       
   198     // Send encoded password
       
   199     fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
       
   200 
       
   201     $rply = $this->get_lines();
       
   202     $code = substr($rply,0,3);
       
   203 
       
   204     if($code != 235) {
       
   205       $this->error =
       
   206         array("error" => "Password not accepted from server",
       
   207               "smtp_code" => $code,
       
   208               "smtp_msg" => substr($rply,4));
       
   209       if($this->do_debug >= 1) {
       
   210         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   211                  ": " . $rply . $this->CRLF;
       
   212       }
       
   213       return false;
       
   214     }
       
   215 
       
   216     return true;
       
   217   }
       
   218 
       
   219   /**
       
   220    * Returns true if connected to a server otherwise false
       
   221    * @access private
       
   222    * @return bool
       
   223    */
       
   224   function Connected() {
       
   225     if(!empty($this->smtp_conn)) {
       
   226       $sock_status = socket_get_status($this->smtp_conn);
       
   227       if($sock_status["eof"]) {
       
   228         # hmm this is an odd situation... the socket is
       
   229         # valid but we are not connected anymore
       
   230         if($this->do_debug >= 1) {
       
   231             echo "SMTP -> NOTICE:" . $this->CRLF .
       
   232                  "EOF caught while checking if connected";
       
   233         }
       
   234         $this->Close();
       
   235         return false;
       
   236       }
       
   237       return true; # everything looks good
       
   238     }
       
   239     return false;
       
   240   }
       
   241 
       
   242   /**
       
   243    * Closes the socket and cleans up the state of the class.
       
   244    * It is not considered good to use this function without
       
   245    * first trying to use QUIT.
       
   246    * @access public
       
   247    * @return void
       
   248    */
       
   249   function Close() {
       
   250     $this->error = null; # so there is no confusion
       
   251     $this->helo_rply = null;
       
   252     if(!empty($this->smtp_conn)) {
       
   253       # close the connection and cleanup
       
   254       fclose($this->smtp_conn);
       
   255       $this->smtp_conn = 0;
       
   256     }
       
   257   }
       
   258 
       
   259   /***************************************************************
       
   260    *                        SMTP COMMANDS                       *
       
   261    *************************************************************/
       
   262 
       
   263   /**
       
   264    * Issues a data command and sends the msg_data to the server
       
   265    * finializing the mail transaction. $msg_data is the message
       
   266    * that is to be send with the headers. Each header needs to be
       
   267    * on a single line followed by a <CRLF> with the message headers
       
   268    * and the message body being seperated by and additional <CRLF>.
       
   269    *
       
   270    * Implements rfc 821: DATA <CRLF>
       
   271    *
       
   272    * SMTP CODE INTERMEDIATE: 354
       
   273    *     [data]
       
   274    *     <CRLF>.<CRLF>
       
   275    *     SMTP CODE SUCCESS: 250
       
   276    *     SMTP CODE FAILURE: 552,554,451,452
       
   277    * SMTP CODE FAILURE: 451,554
       
   278    * SMTP CODE ERROR  : 500,501,503,421
       
   279    * @access public
       
   280    * @return bool
       
   281    */
       
   282   function Data($msg_data) {
       
   283     $this->error = null; # so no confusion is caused
       
   284 
       
   285     if(!$this->connected()) {
       
   286       $this->error = array(
       
   287               "error" => "Called Data() without being connected");
       
   288       return false;
       
   289     }
       
   290 
       
   291     fputs($this->smtp_conn,"DATA" . $this->CRLF);
       
   292 
       
   293     $rply = $this->get_lines();
       
   294     $code = substr($rply,0,3);
       
   295 
       
   296     if($this->do_debug >= 2) {
       
   297       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   298     }
       
   299 
       
   300     if($code != 354) {
       
   301       $this->error =
       
   302         array("error" => "DATA command not accepted from server",
       
   303               "smtp_code" => $code,
       
   304               "smtp_msg" => substr($rply,4));
       
   305       if($this->do_debug >= 1) {
       
   306         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   307                  ": " . $rply . $this->CRLF;
       
   308       }
       
   309       return false;
       
   310     }
       
   311 
       
   312     # the server is ready to accept data!
       
   313     # according to rfc 821 we should not send more than 1000
       
   314     # including the CRLF
       
   315     # characters on a single line so we will break the data up
       
   316     # into lines by \r and/or \n then if needed we will break
       
   317     # each of those into smaller lines to fit within the limit.
       
   318     # in addition we will be looking for lines that start with
       
   319     # a period '.' and append and additional period '.' to that
       
   320     # line. NOTE: this does not count towards are limit.
       
   321 
       
   322     # normalize the line breaks so we know the explode works
       
   323     $msg_data = str_replace("\r\n","\n",$msg_data);
       
   324     $msg_data = str_replace("\r","\n",$msg_data);
       
   325     $lines = explode("\n",$msg_data);
       
   326 
       
   327     # we need to find a good way to determine is headers are
       
   328     # in the msg_data or if it is a straight msg body
       
   329     # currently I am assuming rfc 822 definitions of msg headers
       
   330     # and if the first field of the first line (':' sperated)
       
   331     # does not contain a space then it _should_ be a header
       
   332     # and we can process all lines before a blank "" line as
       
   333     # headers.
       
   334     $field = substr($lines[0],0,strpos($lines[0],":"));
       
   335     $in_headers = false;
       
   336     if(!empty($field) && !strstr($field," ")) {
       
   337       $in_headers = true;
       
   338     }
       
   339 
       
   340     $max_line_length = 998; # used below; set here for ease in change
       
   341 
       
   342     while(list(,$line) = @each($lines)) {
       
   343       $lines_out = null;
       
   344       if($line == "" && $in_headers) {
       
   345         $in_headers = false;
       
   346       }
       
   347       # ok we need to break this line up into several
       
   348       # smaller lines
       
   349       while(strlen($line) > $max_line_length) {
       
   350         $pos = strrpos(substr($line,0,$max_line_length)," ");
       
   351 
       
   352         # Patch to fix DOS attack
       
   353         if(!$pos) {
       
   354           $pos = $max_line_length - 1;
       
   355         }
       
   356 
       
   357         $lines_out[] = substr($line,0,$pos);
       
   358         $line = substr($line,$pos + 1);
       
   359         # if we are processing headers we need to
       
   360         # add a LWSP-char to the front of the new line
       
   361         # rfc 822 on long msg headers
       
   362         if($in_headers) {
       
   363           $line = "\t" . $line;
       
   364         }
       
   365       }
       
   366       $lines_out[] = $line;
       
   367 
       
   368       # now send the lines to the server
       
   369       while(list(,$line_out) = @each($lines_out)) {
       
   370         if(strlen($line_out) > 0)
       
   371         {
       
   372           if(substr($line_out, 0, 1) == ".") {
       
   373             $line_out = "." . $line_out;
       
   374           }
       
   375         }
       
   376         fputs($this->smtp_conn,$line_out . $this->CRLF);
       
   377       }
       
   378     }
       
   379 
       
   380     # ok all the message data has been sent so lets get this
       
   381     # over with aleady
       
   382     fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
       
   383 
       
   384     $rply = $this->get_lines();
       
   385     $code = substr($rply,0,3);
       
   386 
       
   387     if($this->do_debug >= 2) {
       
   388       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   389     }
       
   390 
       
   391     if($code != 250) {
       
   392       $this->error =
       
   393         array("error" => "DATA not accepted from server",
       
   394               "smtp_code" => $code,
       
   395               "smtp_msg" => substr($rply,4));
       
   396       if($this->do_debug >= 1) {
       
   397         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   398                  ": " . $rply . $this->CRLF;
       
   399       }
       
   400       return false;
       
   401     }
       
   402     return true;
       
   403   }
       
   404 
       
   405   /**
       
   406    * Expand takes the name and asks the server to list all the
       
   407    * people who are members of the _list_. Expand will return
       
   408    * back and array of the result or false if an error occurs.
       
   409    * Each value in the array returned has the format of:
       
   410    *     [ <full-name> <sp> ] <path>
       
   411    * The definition of <path> is defined in rfc 821
       
   412    *
       
   413    * Implements rfc 821: EXPN <SP> <string> <CRLF>
       
   414    *
       
   415    * SMTP CODE SUCCESS: 250
       
   416    * SMTP CODE FAILURE: 550
       
   417    * SMTP CODE ERROR  : 500,501,502,504,421
       
   418    * @access public
       
   419    * @return string array
       
   420    */
       
   421   function Expand($name) {
       
   422     $this->error = null; # so no confusion is caused
       
   423 
       
   424     if(!$this->connected()) {
       
   425       $this->error = array(
       
   426             "error" => "Called Expand() without being connected");
       
   427       return false;
       
   428     }
       
   429 
       
   430     fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
       
   431 
       
   432     $rply = $this->get_lines();
       
   433     $code = substr($rply,0,3);
       
   434 
       
   435     if($this->do_debug >= 2) {
       
   436       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   437     }
       
   438 
       
   439     if($code != 250) {
       
   440       $this->error =
       
   441         array("error" => "EXPN not accepted from server",
       
   442               "smtp_code" => $code,
       
   443               "smtp_msg" => substr($rply,4));
       
   444       if($this->do_debug >= 1) {
       
   445         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   446                  ": " . $rply . $this->CRLF;
       
   447       }
       
   448       return false;
       
   449     }
       
   450 
       
   451     # parse the reply and place in our array to return to user
       
   452     $entries = explode($this->CRLF,$rply);
       
   453     while(list(,$l) = @each($entries)) {
       
   454       $list[] = substr($l,4);
       
   455     }
       
   456 
       
   457     return $list;
       
   458   }
       
   459 
       
   460   /**
       
   461    * Sends the HELO command to the smtp server.
       
   462    * This makes sure that we and the server are in
       
   463    * the same known state.
       
   464    *
       
   465    * Implements from rfc 821: HELO <SP> <domain> <CRLF>
       
   466    *
       
   467    * SMTP CODE SUCCESS: 250
       
   468    * SMTP CODE ERROR  : 500, 501, 504, 421
       
   469    * @access public
       
   470    * @return bool
       
   471    */
       
   472   function Hello($host="") {
       
   473     $this->error = null; # so no confusion is caused
       
   474 
       
   475     if(!$this->connected()) {
       
   476       $this->error = array(
       
   477             "error" => "Called Hello() without being connected");
       
   478       return false;
       
   479     }
       
   480 
       
   481     # if a hostname for the HELO was not specified determine
       
   482     # a suitable one to send
       
   483     if(empty($host)) {
       
   484       # we need to determine some sort of appopiate default
       
   485       # to send to the server
       
   486       $host = "localhost";
       
   487     }
       
   488 
       
   489     // Send extended hello first (RFC 2821)
       
   490     if(!$this->SendHello("EHLO", $host))
       
   491     {
       
   492       if(!$this->SendHello("HELO", $host))
       
   493           return false;
       
   494     }
       
   495 
       
   496     return true;
       
   497   }
       
   498 
       
   499   /**
       
   500    * Sends a HELO/EHLO command.
       
   501    * @access private
       
   502    * @return bool
       
   503    */
       
   504   function SendHello($hello, $host) {
       
   505     fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
       
   506 
       
   507     $rply = $this->get_lines();
       
   508     $code = substr($rply,0,3);
       
   509 
       
   510     if($this->do_debug >= 2) {
       
   511       echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
       
   512     }
       
   513 
       
   514     if($code != 250) {
       
   515       $this->error =
       
   516         array("error" => $hello . " not accepted from server",
       
   517               "smtp_code" => $code,
       
   518               "smtp_msg" => substr($rply,4));
       
   519       if($this->do_debug >= 1) {
       
   520         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   521                  ": " . $rply . $this->CRLF;
       
   522       }
       
   523       return false;
       
   524     }
       
   525 
       
   526     $this->helo_rply = $rply;
       
   527 
       
   528     return true;
       
   529   }
       
   530 
       
   531   /**
       
   532    * Gets help information on the keyword specified. If the keyword
       
   533    * is not specified then returns generic help, ussually contianing
       
   534    * A list of keywords that help is available on. This function
       
   535    * returns the results back to the user. It is up to the user to
       
   536    * handle the returned data. If an error occurs then false is
       
   537    * returned with $this->error set appropiately.
       
   538    *
       
   539    * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
       
   540    *
       
   541    * SMTP CODE SUCCESS: 211,214
       
   542    * SMTP CODE ERROR  : 500,501,502,504,421
       
   543    * @access public
       
   544    * @return string
       
   545    */
       
   546   function Help($keyword="") {
       
   547     $this->error = null; # to avoid confusion
       
   548 
       
   549     if(!$this->connected()) {
       
   550       $this->error = array(
       
   551               "error" => "Called Help() without being connected");
       
   552       return false;
       
   553     }
       
   554 
       
   555     $extra = "";
       
   556     if(!empty($keyword)) {
       
   557       $extra = " " . $keyword;
       
   558     }
       
   559 
       
   560     fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
       
   561 
       
   562     $rply = $this->get_lines();
       
   563     $code = substr($rply,0,3);
       
   564 
       
   565     if($this->do_debug >= 2) {
       
   566       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   567     }
       
   568 
       
   569     if($code != 211 && $code != 214) {
       
   570       $this->error =
       
   571         array("error" => "HELP not accepted from server",
       
   572               "smtp_code" => $code,
       
   573               "smtp_msg" => substr($rply,4));
       
   574       if($this->do_debug >= 1) {
       
   575         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   576                  ": " . $rply . $this->CRLF;
       
   577       }
       
   578       return false;
       
   579     }
       
   580 
       
   581     return $rply;
       
   582   }
       
   583 
       
   584   /**
       
   585    * Starts a mail transaction from the email address specified in
       
   586    * $from. Returns true if successful or false otherwise. If True
       
   587    * the mail transaction is started and then one or more Recipient
       
   588    * commands may be called followed by a Data command.
       
   589    *
       
   590    * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
       
   591    *
       
   592    * SMTP CODE SUCCESS: 250
       
   593    * SMTP CODE SUCCESS: 552,451,452
       
   594    * SMTP CODE SUCCESS: 500,501,421
       
   595    * @access public
       
   596    * @return bool
       
   597    */
       
   598   function Mail($from) {
       
   599     $this->error = null; # so no confusion is caused
       
   600 
       
   601     if(!$this->connected()) {
       
   602       $this->error = array(
       
   603               "error" => "Called Mail() without being connected");
       
   604       return false;
       
   605     }
       
   606 
       
   607     $useVerp = ($this->do_verp ? "XVERP" : "");
       
   608     fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
       
   609 
       
   610     $rply = $this->get_lines();
       
   611     $code = substr($rply,0,3);
       
   612 
       
   613     if($this->do_debug >= 2) {
       
   614       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   615     }
       
   616 
       
   617     if($code != 250) {
       
   618       $this->error =
       
   619         array("error" => "MAIL not accepted from server",
       
   620               "smtp_code" => $code,
       
   621               "smtp_msg" => substr($rply,4));
       
   622       if($this->do_debug >= 1) {
       
   623         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   624                  ": " . $rply . $this->CRLF;
       
   625       }
       
   626       return false;
       
   627     }
       
   628     return true;
       
   629   }
       
   630 
       
   631   /**
       
   632    * Sends the command NOOP to the SMTP server.
       
   633    *
       
   634    * Implements from rfc 821: NOOP <CRLF>
       
   635    *
       
   636    * SMTP CODE SUCCESS: 250
       
   637    * SMTP CODE ERROR  : 500, 421
       
   638    * @access public
       
   639    * @return bool
       
   640    */
       
   641   function Noop() {
       
   642     $this->error = null; # so no confusion is caused
       
   643 
       
   644     if(!$this->connected()) {
       
   645       $this->error = array(
       
   646               "error" => "Called Noop() without being connected");
       
   647       return false;
       
   648     }
       
   649 
       
   650     fputs($this->smtp_conn,"NOOP" . $this->CRLF);
       
   651 
       
   652     $rply = $this->get_lines();
       
   653     $code = substr($rply,0,3);
       
   654 
       
   655     if($this->do_debug >= 2) {
       
   656       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   657     }
       
   658 
       
   659     if($code != 250) {
       
   660       $this->error =
       
   661         array("error" => "NOOP not accepted from server",
       
   662               "smtp_code" => $code,
       
   663               "smtp_msg" => substr($rply,4));
       
   664       if($this->do_debug >= 1) {
       
   665         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   666                  ": " . $rply . $this->CRLF;
       
   667       }
       
   668       return false;
       
   669     }
       
   670     return true;
       
   671   }
       
   672 
       
   673   /**
       
   674    * Sends the quit command to the server and then closes the socket
       
   675    * if there is no error or the $close_on_error argument is true.
       
   676    *
       
   677    * Implements from rfc 821: QUIT <CRLF>
       
   678    *
       
   679    * SMTP CODE SUCCESS: 221
       
   680    * SMTP CODE ERROR  : 500
       
   681    * @access public
       
   682    * @return bool
       
   683    */
       
   684   function Quit($close_on_error=true) {
       
   685     $this->error = null; # so there is no confusion
       
   686 
       
   687     if(!$this->connected()) {
       
   688       $this->error = array(
       
   689               "error" => "Called Quit() without being connected");
       
   690       return false;
       
   691     }
       
   692 
       
   693     # send the quit command to the server
       
   694     fputs($this->smtp_conn,"quit" . $this->CRLF);
       
   695 
       
   696     # get any good-bye messages
       
   697     $byemsg = $this->get_lines();
       
   698 
       
   699     if($this->do_debug >= 2) {
       
   700       echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
       
   701     }
       
   702 
       
   703     $rval = true;
       
   704     $e = null;
       
   705 
       
   706     $code = substr($byemsg,0,3);
       
   707     if($code != 221) {
       
   708       # use e as a tmp var cause Close will overwrite $this->error
       
   709       $e = array("error" => "SMTP server rejected quit command",
       
   710                  "smtp_code" => $code,
       
   711                  "smtp_rply" => substr($byemsg,4));
       
   712       $rval = false;
       
   713       if($this->do_debug >= 1) {
       
   714         echo "SMTP -> ERROR: " . $e["error"] . ": " .
       
   715                  $byemsg . $this->CRLF;
       
   716       }
       
   717     }
       
   718 
       
   719     if(empty($e) || $close_on_error) {
       
   720       $this->Close();
       
   721     }
       
   722 
       
   723     return $rval;
       
   724   }
       
   725 
       
   726   /**
       
   727    * Sends the command RCPT to the SMTP server with the TO: argument of $to.
       
   728    * Returns true if the recipient was accepted false if it was rejected.
       
   729    *
       
   730    * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
       
   731    *
       
   732    * SMTP CODE SUCCESS: 250,251
       
   733    * SMTP CODE FAILURE: 550,551,552,553,450,451,452
       
   734    * SMTP CODE ERROR  : 500,501,503,421
       
   735    * @access public
       
   736    * @return bool
       
   737    */
       
   738   function Recipient($to) {
       
   739     $this->error = null; # so no confusion is caused
       
   740 
       
   741     if(!$this->connected()) {
       
   742       $this->error = array(
       
   743               "error" => "Called Recipient() without being connected");
       
   744       return false;
       
   745     }
       
   746 
       
   747     fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
       
   748 
       
   749     $rply = $this->get_lines();
       
   750     $code = substr($rply,0,3);
       
   751 
       
   752     if($this->do_debug >= 2) {
       
   753       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   754     }
       
   755 
       
   756     if($code != 250 && $code != 251) {
       
   757       $this->error =
       
   758         array("error" => "RCPT not accepted from server",
       
   759               "smtp_code" => $code,
       
   760               "smtp_msg" => substr($rply,4));
       
   761       if($this->do_debug >= 1) {
       
   762         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   763                  ": " . $rply . $this->CRLF;
       
   764       }
       
   765       return false;
       
   766     }
       
   767     return true;
       
   768   }
       
   769 
       
   770   /**
       
   771    * Sends the RSET command to abort and transaction that is
       
   772    * currently in progress. Returns true if successful false
       
   773    * otherwise.
       
   774    *
       
   775    * Implements rfc 821: RSET <CRLF>
       
   776    *
       
   777    * SMTP CODE SUCCESS: 250
       
   778    * SMTP CODE ERROR  : 500,501,504,421
       
   779    * @access public
       
   780    * @return bool
       
   781    */
       
   782   function Reset() {
       
   783     $this->error = null; # so no confusion is caused
       
   784 
       
   785     if(!$this->connected()) {
       
   786       $this->error = array(
       
   787               "error" => "Called Reset() without being connected");
       
   788       return false;
       
   789     }
       
   790 
       
   791     fputs($this->smtp_conn,"RSET" . $this->CRLF);
       
   792 
       
   793     $rply = $this->get_lines();
       
   794     $code = substr($rply,0,3);
       
   795 
       
   796     if($this->do_debug >= 2) {
       
   797       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   798     }
       
   799 
       
   800     if($code != 250) {
       
   801       $this->error =
       
   802         array("error" => "RSET failed",
       
   803               "smtp_code" => $code,
       
   804               "smtp_msg" => substr($rply,4));
       
   805       if($this->do_debug >= 1) {
       
   806         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   807                  ": " . $rply . $this->CRLF;
       
   808       }
       
   809       return false;
       
   810     }
       
   811 
       
   812     return true;
       
   813   }
       
   814 
       
   815   /**
       
   816    * Starts a mail transaction from the email address specified in
       
   817    * $from. Returns true if successful or false otherwise. If True
       
   818    * the mail transaction is started and then one or more Recipient
       
   819    * commands may be called followed by a Data command. This command
       
   820    * will send the message to the users terminal if they are logged
       
   821    * in.
       
   822    *
       
   823    * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
       
   824    *
       
   825    * SMTP CODE SUCCESS: 250
       
   826    * SMTP CODE SUCCESS: 552,451,452
       
   827    * SMTP CODE SUCCESS: 500,501,502,421
       
   828    * @access public
       
   829    * @return bool
       
   830    */
       
   831   function Send($from) {
       
   832     $this->error = null; # so no confusion is caused
       
   833 
       
   834     if(!$this->connected()) {
       
   835       $this->error = array(
       
   836               "error" => "Called Send() without being connected");
       
   837       return false;
       
   838     }
       
   839 
       
   840     fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
       
   841 
       
   842     $rply = $this->get_lines();
       
   843     $code = substr($rply,0,3);
       
   844 
       
   845     if($this->do_debug >= 2) {
       
   846       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   847     }
       
   848 
       
   849     if($code != 250) {
       
   850       $this->error =
       
   851         array("error" => "SEND not accepted from server",
       
   852               "smtp_code" => $code,
       
   853               "smtp_msg" => substr($rply,4));
       
   854       if($this->do_debug >= 1) {
       
   855         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   856                  ": " . $rply . $this->CRLF;
       
   857       }
       
   858       return false;
       
   859     }
       
   860     return true;
       
   861   }
       
   862 
       
   863   /**
       
   864    * Starts a mail transaction from the email address specified in
       
   865    * $from. Returns true if successful or false otherwise. If True
       
   866    * the mail transaction is started and then one or more Recipient
       
   867    * commands may be called followed by a Data command. This command
       
   868    * will send the message to the users terminal if they are logged
       
   869    * in and send them an email.
       
   870    *
       
   871    * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
       
   872    *
       
   873    * SMTP CODE SUCCESS: 250
       
   874    * SMTP CODE SUCCESS: 552,451,452
       
   875    * SMTP CODE SUCCESS: 500,501,502,421
       
   876    * @access public
       
   877    * @return bool
       
   878    */
       
   879   function SendAndMail($from) {
       
   880     $this->error = null; # so no confusion is caused
       
   881 
       
   882     if(!$this->connected()) {
       
   883       $this->error = array(
       
   884           "error" => "Called SendAndMail() without being connected");
       
   885       return false;
       
   886     }
       
   887 
       
   888     fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
       
   889 
       
   890     $rply = $this->get_lines();
       
   891     $code = substr($rply,0,3);
       
   892 
       
   893     if($this->do_debug >= 2) {
       
   894       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   895     }
       
   896 
       
   897     if($code != 250) {
       
   898       $this->error =
       
   899         array("error" => "SAML not accepted from server",
       
   900               "smtp_code" => $code,
       
   901               "smtp_msg" => substr($rply,4));
       
   902       if($this->do_debug >= 1) {
       
   903         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   904                  ": " . $rply . $this->CRLF;
       
   905       }
       
   906       return false;
       
   907     }
       
   908     return true;
       
   909   }
       
   910 
       
   911   /**
       
   912    * Starts a mail transaction from the email address specified in
       
   913    * $from. Returns true if successful or false otherwise. If True
       
   914    * the mail transaction is started and then one or more Recipient
       
   915    * commands may be called followed by a Data command. This command
       
   916    * will send the message to the users terminal if they are logged
       
   917    * in or mail it to them if they are not.
       
   918    *
       
   919    * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
       
   920    *
       
   921    * SMTP CODE SUCCESS: 250
       
   922    * SMTP CODE SUCCESS: 552,451,452
       
   923    * SMTP CODE SUCCESS: 500,501,502,421
       
   924    * @access public
       
   925    * @return bool
       
   926    */
       
   927   function SendOrMail($from) {
       
   928     $this->error = null; # so no confusion is caused
       
   929 
       
   930     if(!$this->connected()) {
       
   931       $this->error = array(
       
   932           "error" => "Called SendOrMail() without being connected");
       
   933       return false;
       
   934     }
       
   935 
       
   936     fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
       
   937 
       
   938     $rply = $this->get_lines();
       
   939     $code = substr($rply,0,3);
       
   940 
       
   941     if($this->do_debug >= 2) {
       
   942       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
   943     }
       
   944 
       
   945     if($code != 250) {
       
   946       $this->error =
       
   947         array("error" => "SOML not accepted from server",
       
   948               "smtp_code" => $code,
       
   949               "smtp_msg" => substr($rply,4));
       
   950       if($this->do_debug >= 1) {
       
   951         echo "SMTP -> ERROR: " . $this->error["error"] .
       
   952                  ": " . $rply . $this->CRLF;
       
   953       }
       
   954       return false;
       
   955     }
       
   956     return true;
       
   957   }
       
   958 
       
   959   /**
       
   960    * This is an optional command for SMTP that this class does not
       
   961    * support. This method is here to make the RFC821 Definition
       
   962    * complete for this class and __may__ be implimented in the future
       
   963    *
       
   964    * Implements from rfc 821: TURN <CRLF>
       
   965    *
       
   966    * SMTP CODE SUCCESS: 250
       
   967    * SMTP CODE FAILURE: 502
       
   968    * SMTP CODE ERROR  : 500, 503
       
   969    * @access public
       
   970    * @return bool
       
   971    */
       
   972   function Turn() {
       
   973     $this->error = array("error" => "This method, TURN, of the SMTP ".
       
   974                                     "is not implemented");
       
   975     if($this->do_debug >= 1) {
       
   976       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
       
   977     }
       
   978     return false;
       
   979   }
       
   980 
       
   981   /**
       
   982    * Verifies that the name is recognized by the server.
       
   983    * Returns false if the name could not be verified otherwise
       
   984    * the response from the server is returned.
       
   985    *
       
   986    * Implements rfc 821: VRFY <SP> <string> <CRLF>
       
   987    *
       
   988    * SMTP CODE SUCCESS: 250,251
       
   989    * SMTP CODE FAILURE: 550,551,553
       
   990    * SMTP CODE ERROR  : 500,501,502,421
       
   991    * @access public
       
   992    * @return int
       
   993    */
       
   994   function Verify($name) {
       
   995     $this->error = null; # so no confusion is caused
       
   996 
       
   997     if(!$this->connected()) {
       
   998       $this->error = array(
       
   999               "error" => "Called Verify() without being connected");
       
  1000       return false;
       
  1001     }
       
  1002 
       
  1003     fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
       
  1004 
       
  1005     $rply = $this->get_lines();
       
  1006     $code = substr($rply,0,3);
       
  1007 
       
  1008     if($this->do_debug >= 2) {
       
  1009       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
       
  1010     }
       
  1011 
       
  1012     if($code != 250 && $code != 251) {
       
  1013       $this->error =
       
  1014         array("error" => "VRFY failed on name '$name'",
       
  1015               "smtp_code" => $code,
       
  1016               "smtp_msg" => substr($rply,4));
       
  1017       if($this->do_debug >= 1) {
       
  1018         echo "SMTP -> ERROR: " . $this->error["error"] .
       
  1019                  ": " . $rply . $this->CRLF;
       
  1020       }
       
  1021       return false;
       
  1022     }
       
  1023     return $rply;
       
  1024   }
       
  1025 
       
  1026   /*******************************************************************
       
  1027    *                       INTERNAL FUNCTIONS                       *
       
  1028    ******************************************************************/
       
  1029 
       
  1030   /**
       
  1031    * Read in as many lines as possible
       
  1032    * either before eof or socket timeout occurs on the operation.
       
  1033    * With SMTP we can tell if we have more lines to read if the
       
  1034    * 4th character is '-' symbol. If it is a space then we don't
       
  1035    * need to read anything else.
       
  1036    * @access private
       
  1037    * @return string
       
  1038    */
       
  1039   function get_lines() {
       
  1040     $data = "";
       
  1041     while($str = @fgets($this->smtp_conn,515)) {
       
  1042       if($this->do_debug >= 4) {
       
  1043         echo "SMTP -> get_lines(): \$data was \"$data\"" .
       
  1044                  $this->CRLF;
       
  1045         echo "SMTP -> get_lines(): \$str is \"$str\"" .
       
  1046                  $this->CRLF;
       
  1047       }
       
  1048       $data .= $str;
       
  1049       if($this->do_debug >= 4) {
       
  1050         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
       
  1051       }
       
  1052       # if the 4th character is a space then we are done reading
       
  1053       # so just break the loop
       
  1054       if(substr($str,3,1) == " ") { break; }
       
  1055     }
       
  1056     return $data;
       
  1057   }
       
  1058 
       
  1059 }
       
  1060 
       
  1061 
       
  1062  ?>