[phpBB Debug] PHP Warning: in file [ROOT]/includes/crs/crs_misc_functions.php on line 37: mime_content_type(): Empty filename or path
[phpBB Debug] PHP Warning: in file [ROOT]/includes/crs/crs_misc_functions.php on line 37: mime_content_type(): Empty filename or path
Zen Cart 源代码 class.smtp.php

Zen Cart 源代码 class.smtp.php




下载文件

文件名: class.smtp.php
文件类型: PHP文件
文件大小: 33 KiB
MD5: 9e54240e6d65e255100d2ac2aa1420fd

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


cron