home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 April / CMCD0404.ISO / Software / Freeware / Programare / groupoffice-com-2.01 / classes / phpmailer / class.smtp.php < prev    next >
PHP Script  |  2004-03-08  |  34KB  |  1,040 lines

  1. <?php
  2. ////////////////////////////////////////////////////
  3. // SMTP - PHP SMTP class
  4. //
  5. // Version 1.02
  6. //
  7. // Define an SMTP class that can be used to connect
  8. // and communicate with any SMTP server. It implements
  9. // all the SMTP functions defined in RFC821 except TURN.
  10. //
  11. // Author: Chris Ryan
  12. //
  13. // License: LGPL, see LICENSE
  14. ////////////////////////////////////////////////////
  15.  
  16. /**
  17.  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
  18.  * commands except TURN which will always return a not implemented
  19.  * error. SMTP also provides some utility methods for sending mail
  20.  * to an SMTP server.
  21.  * @package PHPMailer
  22.  * @author Chris Ryan
  23.  */
  24. class SMTP
  25. {
  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;
  94.         }
  95.  
  96.         if(empty($port)) {
  97.             $port = $this->SMTP_PORT;
  98.         }
  99.  
  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;
  116.         }
  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;
  133.         }
  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 seperated 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.                 $lines_out[] = substr($line,0,$pos);
  336.                 $line = substr($line,$pos + 1);
  337.                 # if we are processing headers we need to
  338.                 # add a LWSP-char to the front of the new line
  339.                 # rfc 822 on long msg headers
  340.                 if($in_headers) {
  341.                     $line = "\t" . $line;
  342.                 }
  343.             }
  344.             $lines_out[] = $line;
  345.  
  346.             # now send the lines to the server
  347.             while(list(,$line_out) = @each($lines_out)) {
  348.                 if(strlen($line_out) > 0)
  349.                 {
  350.                     if(substr($line_out, 0, 1) == ".") {
  351.                         $line_out = "." . $line_out;
  352.                     }
  353.                 }
  354.                 fputs($this->smtp_conn,$line_out . $this->CRLF);
  355.             }
  356.         }
  357.  
  358.         # ok all the message data has been sent so lets get this
  359.         # over with aleady
  360.         fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
  361.  
  362.         $rply = $this->get_lines();
  363.         $code = substr($rply,0,3);
  364.  
  365.         if($this->do_debug >= 2) {
  366.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  367.         }
  368.  
  369.         if($code != 250) {
  370.             $this->error =
  371.                 array("error" => "DATA not accepted from server",
  372.                       "smtp_code" => $code,
  373.                       "smtp_msg" => substr($rply,4));
  374.             if($this->do_debug >= 1) {
  375.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  376.                          ": " . $rply . $this->CRLF;
  377.             }
  378.             return false;
  379.         }
  380.         return true;
  381.     }
  382.  
  383.     /**
  384.      * Expand takes the name and asks the server to list all the
  385.      * people who are members of the _list_. Expand will return
  386.      * back and array of the result or false if an error occurs.
  387.      * Each value in the array returned has the format of:
  388.      *     [ <full-name> <sp> ] <path>
  389.      * The definition of <path> is defined in rfc 821
  390.      *
  391.      * Implements rfc 821: EXPN <SP> <string> <CRLF>
  392.      *
  393.      * SMTP CODE SUCCESS: 250
  394.      * SMTP CODE FAILURE: 550
  395.      * SMTP CODE ERROR  : 500,501,502,504,421
  396.      * @access public
  397.      * @return string array
  398.      */
  399.     function Expand($name) {
  400.         $this->error = null; # so no confusion is caused
  401.  
  402.         if(!$this->connected()) {
  403.             $this->error = array(
  404.                     "error" => "Called Expand() without being connected");
  405.             return false;
  406.         }
  407.  
  408.         fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
  409.  
  410.         $rply = $this->get_lines();
  411.         $code = substr($rply,0,3);
  412.  
  413.         if($this->do_debug >= 2) {
  414.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  415.         }
  416.  
  417.         if($code != 250) {
  418.             $this->error =
  419.                 array("error" => "EXPN not accepted from server",
  420.                       "smtp_code" => $code,
  421.                       "smtp_msg" => substr($rply,4));
  422.             if($this->do_debug >= 1) {
  423.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  424.                          ": " . $rply . $this->CRLF;
  425.             }
  426.             return false;
  427.         }
  428.  
  429.         # parse the reply and place in our array to return to user
  430.         $entries = explode($this->CRLF,$rply);
  431.         while(list(,$l) = @each($entries)) {
  432.             $list[] = substr($l,4);
  433.         }
  434.  
  435.         return $list;
  436.     }
  437.  
  438.     /**
  439.      * Sends the HELO command to the smtp server.
  440.      * This makes sure that we and the server are in
  441.      * the same known state.
  442.      *
  443.      * Implements from rfc 821: HELO <SP> <domain> <CRLF>
  444.      *
  445.      * SMTP CODE SUCCESS: 250
  446.      * SMTP CODE ERROR  : 500, 501, 504, 421
  447.      * @access public
  448.      * @return bool
  449.      */
  450.     function Hello($host="") {
  451.         $this->error = null; # so no confusion is caused
  452.  
  453.         if(!$this->connected()) {
  454.             $this->error = array(
  455.                     "error" => "Called Hello() without being connected");
  456.             return false;
  457.         }
  458.  
  459.         # if a hostname for the HELO wasn't specified determine
  460.         # a suitable one to send
  461.         if(empty($host)) {
  462.             # we need to determine some sort of appopiate default
  463.             # to send to the server
  464.             $host = "localhost";
  465.         }
  466.  
  467.         // Send extended hello first (RFC 2821)
  468.         if(!$this->SendHello("EHLO", $host))
  469.         {
  470.             if(!$this->SendHello("HELO", $host))
  471.                 return false;
  472.         }
  473.  
  474.         return true;
  475.     }
  476.  
  477.     /**
  478.      * Sends a HELO/EHLO command.
  479.      * @access private
  480.      * @return bool
  481.      */
  482.     function SendHello($hello, $host) {
  483.         fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
  484.  
  485.         $rply = $this->get_lines();
  486.         $code = substr($rply,0,3);
  487.  
  488.         if($this->do_debug >= 2) {
  489.             echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
  490.         }
  491.  
  492.         if($code != 250) {
  493.             $this->error =
  494.                 array("error" => $hello . " not accepted from server",
  495.                       "smtp_code" => $code,
  496.                       "smtp_msg" => substr($rply,4));
  497.             if($this->do_debug >= 1) {
  498.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  499.                          ": " . $rply . $this->CRLF;
  500.             }
  501.             return false;
  502.         }
  503.  
  504.         $this->helo_rply = $rply;
  505.         
  506.         return true;
  507.     }
  508.  
  509.     /**
  510.      * Gets help information on the keyword specified. If the keyword
  511.      * is not specified then returns generic help, ussually contianing
  512.      * A list of keywords that help is available on. This function
  513.      * returns the results back to the user. It is up to the user to
  514.      * handle the returned data. If an error occurs then false is
  515.      * returned with $this->error set appropiately.
  516.      *
  517.      * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
  518.      *
  519.      * SMTP CODE SUCCESS: 211,214
  520.      * SMTP CODE ERROR  : 500,501,502,504,421
  521.      * @access public
  522.      * @return string
  523.      */
  524.     function Help($keyword="") {
  525.         $this->error = null; # to avoid confusion
  526.  
  527.         if(!$this->connected()) {
  528.             $this->error = array(
  529.                     "error" => "Called Help() without being connected");
  530.             return false;
  531.         }
  532.  
  533.         $extra = "";
  534.         if(!empty($keyword)) {
  535.             $extra = " " . $keyword;
  536.         }
  537.  
  538.         fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
  539.  
  540.         $rply = $this->get_lines();
  541.         $code = substr($rply,0,3);
  542.  
  543.         if($this->do_debug >= 2) {
  544.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  545.         }
  546.  
  547.         if($code != 211 && $code != 214) {
  548.             $this->error =
  549.                 array("error" => "HELP not accepted from server",
  550.                       "smtp_code" => $code,
  551.                       "smtp_msg" => substr($rply,4));
  552.             if($this->do_debug >= 1) {
  553.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  554.                          ": " . $rply . $this->CRLF;
  555.             }
  556.             return false;
  557.         }
  558.  
  559.         return $rply;
  560.     }
  561.  
  562.     /**
  563.      * Starts a mail transaction from the email address specified in
  564.      * $from. Returns true if successful or false otherwise. If True
  565.      * the mail transaction is started and then one or more Recipient
  566.      * commands may be called followed by a Data command.
  567.      *
  568.      * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
  569.      *
  570.      * SMTP CODE SUCCESS: 250
  571.      * SMTP CODE SUCCESS: 552,451,452
  572.      * SMTP CODE SUCCESS: 500,501,421
  573.      * @access public
  574.      * @return bool
  575.      */
  576.     function Mail($from) {
  577.         $this->error = null; # so no confusion is caused
  578.  
  579.         if(!$this->connected()) {
  580.             $this->error = array(
  581.                     "error" => "Called Mail() without being connected");
  582.             return false;
  583.         }
  584.  
  585.         fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);
  586.  
  587.         $rply = $this->get_lines();
  588.         $code = substr($rply,0,3);
  589.  
  590.         if($this->do_debug >= 2) {
  591.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  592.         }
  593.  
  594.         if($code != 250) {
  595.             $this->error =
  596.                 array("error" => "MAIL not accepted from server",
  597.                       "smtp_code" => $code,
  598.                       "smtp_msg" => substr($rply,4));
  599.             if($this->do_debug >= 1) {
  600.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  601.                          ": " . $rply . $this->CRLF;
  602.             }
  603.             return false;
  604.         }
  605.         return true;
  606.     }
  607.  
  608.     /**
  609.      * Sends the command NOOP to the SMTP server.
  610.      *
  611.      * Implements from rfc 821: NOOP <CRLF>
  612.      *
  613.      * SMTP CODE SUCCESS: 250
  614.      * SMTP CODE ERROR  : 500, 421
  615.      * @access public
  616.      * @return bool
  617.      */
  618.     function Noop() {
  619.         $this->error = null; # so no confusion is caused
  620.  
  621.         if(!$this->connected()) {
  622.             $this->error = array(
  623.                     "error" => "Called Noop() without being connected");
  624.             return false;
  625.         }
  626.  
  627.         fputs($this->smtp_conn,"NOOP" . $this->CRLF);
  628.  
  629.         $rply = $this->get_lines();
  630.         $code = substr($rply,0,3);
  631.  
  632.         if($this->do_debug >= 2) {
  633.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  634.         }
  635.  
  636.         if($code != 250) {
  637.             $this->error =
  638.                 array("error" => "NOOP not accepted from server",
  639.                       "smtp_code" => $code,
  640.                       "smtp_msg" => substr($rply,4));
  641.             if($this->do_debug >= 1) {
  642.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  643.                          ": " . $rply . $this->CRLF;
  644.             }
  645.             return false;
  646.         }
  647.         return true;
  648.     }
  649.  
  650.     /**
  651.      * Sends the quit command to the server and then closes the socket
  652.      * if there is no error or the $close_on_error argument is true.
  653.      *
  654.      * Implements from rfc 821: QUIT <CRLF>
  655.      *
  656.      * SMTP CODE SUCCESS: 221
  657.      * SMTP CODE ERROR  : 500
  658.      * @access public
  659.      * @return bool
  660.      */
  661.     function Quit($close_on_error=true) {
  662.         $this->error = null; # so there is no confusion
  663.  
  664.         if(!$this->connected()) {
  665.             $this->error = array(
  666.                     "error" => "Called Quit() without being connected");
  667.             return false;
  668.         }
  669.  
  670.         # send the quit command to the server
  671.         fputs($this->smtp_conn,"quit" . $this->CRLF);
  672.  
  673.         # get any good-bye messages
  674.         $byemsg = $this->get_lines();
  675.  
  676.         if($this->do_debug >= 2) {
  677.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
  678.         }
  679.  
  680.         $rval = true;
  681.         $e = null;
  682.  
  683.         $code = substr($byemsg,0,3);
  684.         if($code != 221) {
  685.             # use e as a tmp var cause Close will overwrite $this->error
  686.             $e = array("error" => "SMTP server rejected quit command",
  687.                        "smtp_code" => $code,
  688.                        "smtp_rply" => substr($byemsg,4));
  689.             $rval = false;
  690.             if($this->do_debug >= 1) {
  691.                 echo "SMTP -> ERROR: " . $e["error"] . ": " .
  692.                          $byemsg . $this->CRLF;
  693.             }
  694.         }
  695.  
  696.         if(empty($e) || $close_on_error) {
  697.             $this->Close();
  698.         }
  699.  
  700.         return $rval;
  701.     }
  702.  
  703.     /**
  704.      * Sends the command RCPT to the SMTP server with the TO: argument of $to.
  705.      * Returns true if the recipient was accepted false if it was rejected.
  706.      *
  707.      * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
  708.      *
  709.      * SMTP CODE SUCCESS: 250,251
  710.      * SMTP CODE FAILURE: 550,551,552,553,450,451,452
  711.      * SMTP CODE ERROR  : 500,501,503,421
  712.      * @access public
  713.      * @return bool
  714.      */
  715.     function Recipient($to) {
  716.         $this->error = null; # so no confusion is caused
  717.  
  718.         if(!$this->connected()) {
  719.             $this->error = array(
  720.                     "error" => "Called Recipient() without being connected");
  721.             return false;
  722.         }
  723.  
  724.         fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
  725.  
  726.         $rply = $this->get_lines();
  727.         $code = substr($rply,0,3);
  728.  
  729.         if($this->do_debug >= 2) {
  730.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  731.         }
  732.  
  733.         if($code != 250 && $code != 251) {
  734.             $this->error =
  735.                 array("error" => "RCPT 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.     /**
  748.      * Sends the RSET command to abort and transaction that is
  749.      * currently in progress. Returns true if successful false
  750.      * otherwise.
  751.      *
  752.      * Implements rfc 821: RSET <CRLF>
  753.      *
  754.      * SMTP CODE SUCCESS: 250
  755.      * SMTP CODE ERROR  : 500,501,504,421
  756.      * @access public
  757.      * @return bool
  758.      */
  759.     function Reset() {
  760.         $this->error = null; # so no confusion is caused
  761.  
  762.         if(!$this->connected()) {
  763.             $this->error = array(
  764.                     "error" => "Called Reset() without being connected");
  765.             return false;
  766.         }
  767.  
  768.         fputs($this->smtp_conn,"RSET" . $this->CRLF);
  769.  
  770.         $rply = $this->get_lines();
  771.         $code = substr($rply,0,3);
  772.  
  773.         if($this->do_debug >= 2) {
  774.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  775.         }
  776.  
  777.         if($code != 250) {
  778.             $this->error =
  779.                 array("error" => "RSET failed",
  780.                       "smtp_code" => $code,
  781.                       "smtp_msg" => substr($rply,4));
  782.             if($this->do_debug >= 1) {
  783.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  784.                          ": " . $rply . $this->CRLF;
  785.             }
  786.             return false;
  787.         }
  788.  
  789.         return true;
  790.     }
  791.  
  792.     /**
  793.      * Starts a mail transaction from the email address specified in
  794.      * $from. Returns true if successful or false otherwise. If True
  795.      * the mail transaction is started and then one or more Recipient
  796.      * commands may be called followed by a Data command. This command
  797.      * will send the message to the users terminal if they are logged
  798.      * in.
  799.      *
  800.      * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
  801.      *
  802.      * SMTP CODE SUCCESS: 250
  803.      * SMTP CODE SUCCESS: 552,451,452
  804.      * SMTP CODE SUCCESS: 500,501,502,421
  805.      * @access public
  806.      * @return bool
  807.      */
  808.     function Send($from) {
  809.         $this->error = null; # so no confusion is caused
  810.  
  811.         if(!$this->connected()) {
  812.             $this->error = array(
  813.                     "error" => "Called Send() without being connected");
  814.             return false;
  815.         }
  816.  
  817.         fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
  818.  
  819.         $rply = $this->get_lines();
  820.         $code = substr($rply,0,3);
  821.  
  822.         if($this->do_debug >= 2) {
  823.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  824.         }
  825.  
  826.         if($code != 250) {
  827.             $this->error =
  828.                 array("error" => "SEND not accepted from server",
  829.                       "smtp_code" => $code,
  830.                       "smtp_msg" => substr($rply,4));
  831.             if($this->do_debug >= 1) {
  832.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  833.                          ": " . $rply . $this->CRLF;
  834.             }
  835.             return false;
  836.         }
  837.         return true;
  838.     }
  839.  
  840.     /**
  841.      * Starts a mail transaction from the email address specified in
  842.      * $from. Returns true if successful or false otherwise. If True
  843.      * the mail transaction is started and then one or more Recipient
  844.      * commands may be called followed by a Data command. This command
  845.      * will send the message to the users terminal if they are logged
  846.      * in and send them an email.
  847.      *
  848.      * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
  849.      *
  850.      * SMTP CODE SUCCESS: 250
  851.      * SMTP CODE SUCCESS: 552,451,452
  852.      * SMTP CODE SUCCESS: 500,501,502,421
  853.      * @access public
  854.      * @return bool
  855.      */
  856.     function SendAndMail($from) {
  857.         $this->error = null; # so no confusion is caused
  858.  
  859.         if(!$this->connected()) {
  860.             $this->error = array(
  861.                 "error" => "Called SendAndMail() without being connected");
  862.             return false;
  863.         }
  864.  
  865.         fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
  866.  
  867.         $rply = $this->get_lines();
  868.         $code = substr($rply,0,3);
  869.  
  870.         if($this->do_debug >= 2) {
  871.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  872.         }
  873.  
  874.         if($code != 250) {
  875.             $this->error =
  876.                 array("error" => "SAML not accepted from server",
  877.                       "smtp_code" => $code,
  878.                       "smtp_msg" => substr($rply,4));
  879.             if($this->do_debug >= 1) {
  880.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  881.                          ": " . $rply . $this->CRLF;
  882.             }
  883.             return false;
  884.         }
  885.         return true;
  886.     }
  887.  
  888.     /**
  889.      * Starts a mail transaction from the email address specified in
  890.      * $from. Returns true if successful or false otherwise. If True
  891.      * the mail transaction is started and then one or more Recipient
  892.      * commands may be called followed by a Data command. This command
  893.      * will send the message to the users terminal if they are logged
  894.      * in or mail it to them if they are not.
  895.      *
  896.      * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
  897.      *
  898.      * SMTP CODE SUCCESS: 250
  899.      * SMTP CODE SUCCESS: 552,451,452
  900.      * SMTP CODE SUCCESS: 500,501,502,421
  901.      * @access public
  902.      * @return bool
  903.      */
  904.     function SendOrMail($from) {
  905.         $this->error = null; # so no confusion is caused
  906.  
  907.         if(!$this->connected()) {
  908.             $this->error = array(
  909.                 "error" => "Called SendOrMail() without being connected");
  910.             return false;
  911.         }
  912.  
  913.         fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
  914.  
  915.         $rply = $this->get_lines();
  916.         $code = substr($rply,0,3);
  917.  
  918.         if($this->do_debug >= 2) {
  919.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  920.         }
  921.  
  922.         if($code != 250) {
  923.             $this->error =
  924.                 array("error" => "SOML not accepted from server",
  925.                       "smtp_code" => $code,
  926.                       "smtp_msg" => substr($rply,4));
  927.             if($this->do_debug >= 1) {
  928.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  929.                          ": " . $rply . $this->CRLF;
  930.             }
  931.             return false;
  932.         }
  933.         return true;
  934.     }
  935.  
  936.     /**
  937.      * This is an optional command for SMTP that this class does not
  938.      * support. This method is here to make the RFC821 Definition
  939.      * complete for this class and __may__ be implimented in the future
  940.      *
  941.      * Implements from rfc 821: TURN <CRLF>
  942.      *
  943.      * SMTP CODE SUCCESS: 250
  944.      * SMTP CODE FAILURE: 502
  945.      * SMTP CODE ERROR  : 500, 503
  946.      * @access public
  947.      * @return bool
  948.      */
  949.     function Turn() {
  950.         $this->error = array("error" => "This method, TURN, of the SMTP ".
  951.                                         "is not implemented");
  952.         if($this->do_debug >= 1) {
  953.             echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
  954.         }
  955.         return false;
  956.     }
  957.  
  958.     /**
  959.      * Verifies that the name is recognized by the server.
  960.      * Returns false if the name could not be verified otherwise
  961.      * the response from the server is returned.
  962.      *
  963.      * Implements rfc 821: VRFY <SP> <string> <CRLF>
  964.      *
  965.      * SMTP CODE SUCCESS: 250,251
  966.      * SMTP CODE FAILURE: 550,551,553
  967.      * SMTP CODE ERROR  : 500,501,502,421
  968.      * @access public
  969.      * @return int
  970.      */
  971.     function Verify($name) {
  972.         $this->error = null; # so no confusion is caused
  973.  
  974.         if(!$this->connected()) {
  975.             $this->error = array(
  976.                     "error" => "Called Verify() without being connected");
  977.             return false;
  978.         }
  979.  
  980.         fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
  981.  
  982.         $rply = $this->get_lines();
  983.         $code = substr($rply,0,3);
  984.  
  985.         if($this->do_debug >= 2) {
  986.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  987.         }
  988.  
  989.         if($code != 250 && $code != 251) {
  990.             $this->error =
  991.                 array("error" => "VRFY failed on name '$name'",
  992.                       "smtp_code" => $code,
  993.                       "smtp_msg" => substr($rply,4));
  994.             if($this->do_debug >= 1) {
  995.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  996.                          ": " . $rply . $this->CRLF;
  997.             }
  998.             return false;
  999.         }
  1000.         return $rply;
  1001.     }
  1002.  
  1003.     /*******************************************************************
  1004.      *                       INTERNAL FUNCTIONS                       *
  1005.      ******************************************************************/
  1006.  
  1007.     /**
  1008.      * Read in as many lines as possible
  1009.      * either before eof or socket timeout occurs on the operation.
  1010.      * With SMTP we can tell if we have more lines to read if the
  1011.      * 4th character is '-' symbol. If it is a space then we don't
  1012.      * need to read anything else.
  1013.      * @access private
  1014.      * @return string
  1015.      */
  1016.     function get_lines() {
  1017.         $data = "";
  1018.         while($str = fgets($this->smtp_conn,515)) {
  1019.             if($this->do_debug >= 4) {
  1020.                 echo "SMTP -> get_lines(): \$data was \"$data\"" .
  1021.                          $this->CRLF;
  1022.                 echo "SMTP -> get_lines(): \$str is \"$str\"" .
  1023.                          $this->CRLF;
  1024.             }
  1025.             $data .= $str;
  1026.             if($this->do_debug >= 4) {
  1027.                 echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
  1028.             }
  1029.             # if the 4th character is a space then we are done reading
  1030.             # so just break the loop
  1031.             if(substr($str,3,1) == " ") { break; }
  1032.         }
  1033.         return $data;
  1034.     }
  1035.  
  1036. }
  1037.  
  1038.  
  1039.  ?>
  1040.