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