phpmailer.smtp.php
上传用户:stephen_wu
上传日期:2008-07-05
资源大小:1757k
文件大小:32k
源码类别:

网络

开发平台:

Unix_Linux

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