Make WordPress Core


Ignore:
Timestamp:
08/28/2008 08:26:36 PM (16 years ago)
Author:
ryan
Message:

Update phpMailer to 2.0.2. Props mattyrob. fixes #7474

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/class-smtp.php

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