Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/phpmailer/class.smtp.php
Go to the documentation of this file.
00001 <?php
00002 /*~ class.smtp.php
00003 .---------------------------------------------------------------------------.
00004 |  Software: PHPMailer - PHP email class                                    |
00005 |   Version: 5.1                                                            |
00006 |   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
00007 |      Info: http://phpmailer.sourceforge.net                               |
00008 |   Support: http://sourceforge.net/projects/phpmailer/                     |
00009 | ------------------------------------------------------------------------- |
00010 |     Admin: Andy Prevost (project admininistrator)                         |
00011 |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
00012 |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
00013 |   Founder: Brent R. Matzelle (original founder)                           |
00014 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
00015 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
00016 | ------------------------------------------------------------------------- |
00017 |   License: Distributed under the Lesser General Public License (LGPL)     |
00018 |            http://www.gnu.org/copyleft/lesser.html                        |
00019 | This program is distributed in the hope that it will be useful - WITHOUT  |
00020 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
00021 | FITNESS FOR A PARTICULAR PURPOSE.                                         |
00022 | ------------------------------------------------------------------------- |
00023 | We offer a number of paid services (www.codeworxtech.com):                |
00024 | - Web Hosting on highly optimized fast and secure servers                 |
00025 | - Technology Consulting                                                   |
00026 | - Oursourcing (highly qualified programmers and graphic designers)        |
00027 '---------------------------------------------------------------------------'
00028 */
00029 
00049 class SMTP {
00054   public $SMTP_PORT = 25;
00055 
00060   public $CRLF = "\r\n";
00061 
00066   public $do_debug;       // the level of debug to perform
00067 
00072   public $do_verp = false;
00073 
00075   // PROPERTIES, PRIVATE AND PROTECTED
00077 
00078   private $smtp_conn; // the socket to the server
00079   private $error;     // error if any on the last call
00080   private $helo_rply; // the reply the server sent to us for HELO
00081 
00087   public function __construct() {
00088     $this->smtp_conn = 0;
00089     $this->error = null;
00090     $this->helo_rply = null;
00091 
00092     $this->do_debug = 0;
00093   }
00094 
00096   // CONNECTION FUNCTIONS
00098 
00112   public function Connect($host, $port = 0, $tval = 30) {
00113     // set the error val to null so there is no confusion
00114     $this->error = null;
00115 
00116     // make sure we are __not__ connected
00117     if($this->connected()) {
00118       // already connected, generate error
00119       $this->error = array("error" => "Already connected to a server");
00120       return false;
00121     }
00122 
00123     if(empty($port)) {
00124       $port = $this->SMTP_PORT;
00125     }
00126 
00127     // connect to the smtp server
00128     $this->smtp_conn = @fsockopen($host,    // the host of the server
00129                                  $port,    // the port to use
00130                                  $errno,   // error number if any
00131                                  $errstr,  // error message if any
00132                                  $tval);   // give up after ? secs
00133     // verify we connected properly
00134     if(empty($this->smtp_conn)) {
00135       $this->error = array("error" => "Failed to connect to server",
00136                            "errno" => $errno,
00137                            "errstr" => $errstr);
00138       if($this->do_debug >= 1) {
00139         echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
00140       }
00141       return false;
00142     }
00143 
00144     // SMTP server can take longer to respond, give longer timeout for first read
00145     // Windows does not have support for this timeout function
00146     if(substr(PHP_OS, 0, 3) != "WIN")
00147      socket_set_timeout($this->smtp_conn, $tval, 0);
00148 
00149     // get any announcement
00150     $announce = $this->get_lines();
00151 
00152     if($this->do_debug >= 2) {
00153       echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
00154     }
00155 
00156     return true;
00157   }
00158 
00168   public function StartTLS() {
00169     $this->error = null; # to avoid confusion
00170 
00171     if(!$this->connected()) {
00172       $this->error = array("error" => "Called StartTLS() without being connected");
00173       return false;
00174     }
00175 
00176     fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
00177 
00178     $rply = $this->get_lines();
00179     $code = substr($rply,0,3);
00180 
00181     if($this->do_debug >= 2) {
00182       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00183     }
00184 
00185     if($code != 220) {
00186       $this->error =
00187          array("error"     => "STARTTLS not accepted from server",
00188                "smtp_code" => $code,
00189                "smtp_msg"  => substr($rply,4));
00190       if($this->do_debug >= 1) {
00191         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00192       }
00193       return false;
00194     }
00195 
00196     // Begin encrypted connection
00197     if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
00198       return false;
00199     }
00200 
00201     return true;
00202   }
00203 
00210   public function Authenticate($username, $password) {
00211     // Start authentication
00212     fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
00213 
00214     $rply = $this->get_lines();
00215     $code = substr($rply,0,3);
00216 
00217     if($code != 334) {
00218       $this->error =
00219         array("error" => "AUTH not accepted from server",
00220               "smtp_code" => $code,
00221               "smtp_msg" => substr($rply,4));
00222       if($this->do_debug >= 1) {
00223         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00224       }
00225       return false;
00226     }
00227 
00228     // Send encoded username
00229     fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
00230 
00231     $rply = $this->get_lines();
00232     $code = substr($rply,0,3);
00233 
00234     if($code != 334) {
00235       $this->error =
00236         array("error" => "Username not accepted from server",
00237               "smtp_code" => $code,
00238               "smtp_msg" => substr($rply,4));
00239       if($this->do_debug >= 1) {
00240         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00241       }
00242       return false;
00243     }
00244 
00245     // Send encoded password
00246     fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
00247 
00248     $rply = $this->get_lines();
00249     $code = substr($rply,0,3);
00250 
00251     if($code != 235) {
00252       $this->error =
00253         array("error" => "Password not accepted from server",
00254               "smtp_code" => $code,
00255               "smtp_msg" => substr($rply,4));
00256       if($this->do_debug >= 1) {
00257         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00258       }
00259       return false;
00260     }
00261 
00262     return true;
00263   }
00264 
00270   public function Connected() {
00271     if(!empty($this->smtp_conn)) {
00272       $sock_status = socket_get_status($this->smtp_conn);
00273       if($sock_status["eof"]) {
00274         // the socket is valid but we are not connected
00275         if($this->do_debug >= 1) {
00276             echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
00277         }
00278         $this->Close();
00279         return false;
00280       }
00281       return true; // everything looks good
00282     }
00283     return false;
00284   }
00285 
00293   public function Close() {
00294     $this->error = null; // so there is no confusion
00295     $this->helo_rply = null;
00296     if(!empty($this->smtp_conn)) {
00297       // close the connection and cleanup
00298       fclose($this->smtp_conn);
00299       $this->smtp_conn = 0;
00300     }
00301   }
00302 
00304   // SMTP COMMANDS
00306 
00326   public function Data($msg_data) {
00327     $this->error = null; // so no confusion is caused
00328 
00329     if(!$this->connected()) {
00330       $this->error = array(
00331               "error" => "Called Data() without being connected");
00332       return false;
00333     }
00334 
00335     fputs($this->smtp_conn,"DATA" . $this->CRLF);
00336 
00337     $rply = $this->get_lines();
00338     $code = substr($rply,0,3);
00339 
00340     if($this->do_debug >= 2) {
00341       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00342     }
00343 
00344     if($code != 354) {
00345       $this->error =
00346         array("error" => "DATA command not accepted from server",
00347               "smtp_code" => $code,
00348               "smtp_msg" => substr($rply,4));
00349       if($this->do_debug >= 1) {
00350         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00351       }
00352       return false;
00353     }
00354 
00355     /* the server is ready to accept data!
00356      * according to rfc 821 we should not send more than 1000
00357      * including the CRLF
00358      * characters on a single line so we will break the data up
00359      * into lines by \r and/or \n then if needed we will break
00360      * each of those into smaller lines to fit within the limit.
00361      * in addition we will be looking for lines that start with
00362      * a period '.' and append and additional period '.' to that
00363      * line. NOTE: this does not count towards limit.
00364      */
00365 
00366     // normalize the line breaks so we know the explode works
00367     $msg_data = str_replace("\r\n","\n",$msg_data);
00368     $msg_data = str_replace("\r","\n",$msg_data);
00369     $lines = explode("\n",$msg_data);
00370 
00371     /* we need to find a good way to determine is headers are
00372      * in the msg_data or if it is a straight msg body
00373      * currently I am assuming rfc 822 definitions of msg headers
00374      * and if the first field of the first line (':' sperated)
00375      * does not contain a space then it _should_ be a header
00376      * and we can process all lines before a blank "" line as
00377      * headers.
00378      */
00379 
00380     $field = substr($lines[0],0,strpos($lines[0],":"));
00381     $in_headers = false;
00382     if(!empty($field) && !strstr($field," ")) {
00383       $in_headers = true;
00384     }
00385 
00386     $max_line_length = 998; // used below; set here for ease in change
00387 
00388     while(list(,$line) = @each($lines)) {
00389       $lines_out = null;
00390       if($line == "" && $in_headers) {
00391         $in_headers = false;
00392       }
00393       // ok we need to break this line up into several smaller lines
00394       while(strlen($line) > $max_line_length) {
00395         $pos = strrpos(substr($line,0,$max_line_length)," ");
00396 
00397         // Patch to fix DOS attack
00398         if(!$pos) {
00399           $pos = $max_line_length - 1;
00400           $lines_out[] = substr($line,0,$pos);
00401           $line = substr($line,$pos);
00402         } else {
00403           $lines_out[] = substr($line,0,$pos);
00404           $line = substr($line,$pos + 1);
00405         }
00406 
00407         /* if processing headers add a LWSP-char to the front of new line
00408          * rfc 822 on long msg headers
00409          */
00410         if($in_headers) {
00411           $line = "\t" . $line;
00412         }
00413       }
00414       $lines_out[] = $line;
00415 
00416       // send the lines to the server
00417       while(list(,$line_out) = @each($lines_out)) {
00418         if(strlen($line_out) > 0)
00419         {
00420           if(substr($line_out, 0, 1) == ".") {
00421             $line_out = "." . $line_out;
00422           }
00423         }
00424         fputs($this->smtp_conn,$line_out . $this->CRLF);
00425       }
00426     }
00427 
00428     // message data has been sent
00429     fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
00430 
00431     $rply = $this->get_lines();
00432     $code = substr($rply,0,3);
00433 
00434     if($this->do_debug >= 2) {
00435       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00436     }
00437 
00438     if($code != 250) {
00439       $this->error =
00440         array("error" => "DATA not accepted from server",
00441               "smtp_code" => $code,
00442               "smtp_msg" => substr($rply,4));
00443       if($this->do_debug >= 1) {
00444         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00445       }
00446       return false;
00447     }
00448     return true;
00449   }
00450 
00463   public function Hello($host = '') {
00464     $this->error = null; // so no confusion is caused
00465 
00466     if(!$this->connected()) {
00467       $this->error = array(
00468             "error" => "Called Hello() without being connected");
00469       return false;
00470     }
00471 
00472     // if hostname for HELO was not specified send default
00473     if(empty($host)) {
00474       // determine appropriate default to send to server
00475       $host = "localhost";
00476     }
00477 
00478     // Send extended hello first (RFC 2821)
00479     if(!$this->SendHello("EHLO", $host)) {
00480       if(!$this->SendHello("HELO", $host)) {
00481         return false;
00482       }
00483     }
00484 
00485     return true;
00486   }
00487 
00493   private function SendHello($hello, $host) {
00494     fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
00495 
00496     $rply = $this->get_lines();
00497     $code = substr($rply,0,3);
00498 
00499     if($this->do_debug >= 2) {
00500       echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
00501     }
00502 
00503     if($code != 250) {
00504       $this->error =
00505         array("error" => $hello . " not accepted from server",
00506               "smtp_code" => $code,
00507               "smtp_msg" => substr($rply,4));
00508       if($this->do_debug >= 1) {
00509         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00510       }
00511       return false;
00512     }
00513 
00514     $this->helo_rply = $rply;
00515 
00516     return true;
00517   }
00518 
00533   public function Mail($from) {
00534     $this->error = null; // so no confusion is caused
00535 
00536     if(!$this->connected()) {
00537       $this->error = array(
00538               "error" => "Called Mail() without being connected");
00539       return false;
00540     }
00541 
00542     $useVerp = ($this->do_verp ? "XVERP" : "");
00543     fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
00544 
00545     $rply = $this->get_lines();
00546     $code = substr($rply,0,3);
00547 
00548     if($this->do_debug >= 2) {
00549       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00550     }
00551 
00552     if($code != 250) {
00553       $this->error =
00554         array("error" => "MAIL not accepted from server",
00555               "smtp_code" => $code,
00556               "smtp_msg" => substr($rply,4));
00557       if($this->do_debug >= 1) {
00558         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00559       }
00560       return false;
00561     }
00562     return true;
00563   }
00564 
00576   public function Quit($close_on_error = true) {
00577     $this->error = null; // so there is no confusion
00578 
00579     if(!$this->connected()) {
00580       $this->error = array(
00581               "error" => "Called Quit() without being connected");
00582       return false;
00583     }
00584 
00585     // send the quit command to the server
00586     fputs($this->smtp_conn,"quit" . $this->CRLF);
00587 
00588     // get any good-bye messages
00589     $byemsg = $this->get_lines();
00590 
00591     if($this->do_debug >= 2) {
00592       echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
00593     }
00594 
00595     $rval = true;
00596     $e = null;
00597 
00598     $code = substr($byemsg,0,3);
00599     if($code != 221) {
00600       // use e as a tmp var cause Close will overwrite $this->error
00601       $e = array("error" => "SMTP server rejected quit command",
00602                  "smtp_code" => $code,
00603                  "smtp_rply" => substr($byemsg,4));
00604       $rval = false;
00605       if($this->do_debug >= 1) {
00606         echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
00607       }
00608     }
00609 
00610     if(empty($e) || $close_on_error) {
00611       $this->Close();
00612     }
00613 
00614     return $rval;
00615   }
00616 
00629   public function Recipient($to) {
00630     $this->error = null; // so no confusion is caused
00631 
00632     if(!$this->connected()) {
00633       $this->error = array(
00634               "error" => "Called Recipient() without being connected");
00635       return false;
00636     }
00637 
00638     fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
00639 
00640     $rply = $this->get_lines();
00641     $code = substr($rply,0,3);
00642 
00643     if($this->do_debug >= 2) {
00644       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00645     }
00646 
00647     if($code != 250 && $code != 251) {
00648       $this->error =
00649         array("error" => "RCPT not accepted from server",
00650               "smtp_code" => $code,
00651               "smtp_msg" => substr($rply,4));
00652       if($this->do_debug >= 1) {
00653         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00654       }
00655       return false;
00656     }
00657     return true;
00658   }
00659 
00672   public function Reset() {
00673     $this->error = null; // so no confusion is caused
00674 
00675     if(!$this->connected()) {
00676       $this->error = array(
00677               "error" => "Called Reset() without being connected");
00678       return false;
00679     }
00680 
00681     fputs($this->smtp_conn,"RSET" . $this->CRLF);
00682 
00683     $rply = $this->get_lines();
00684     $code = substr($rply,0,3);
00685 
00686     if($this->do_debug >= 2) {
00687       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00688     }
00689 
00690     if($code != 250) {
00691       $this->error =
00692         array("error" => "RSET failed",
00693               "smtp_code" => $code,
00694               "smtp_msg" => substr($rply,4));
00695       if($this->do_debug >= 1) {
00696         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00697       }
00698       return false;
00699     }
00700 
00701     return true;
00702   }
00703 
00720   public function SendAndMail($from) {
00721     $this->error = null; // so no confusion is caused
00722 
00723     if(!$this->connected()) {
00724       $this->error = array(
00725           "error" => "Called SendAndMail() without being connected");
00726       return false;
00727     }
00728 
00729     fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
00730 
00731     $rply = $this->get_lines();
00732     $code = substr($rply,0,3);
00733 
00734     if($this->do_debug >= 2) {
00735       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
00736     }
00737 
00738     if($code != 250) {
00739       $this->error =
00740         array("error" => "SAML not accepted from server",
00741               "smtp_code" => $code,
00742               "smtp_msg" => substr($rply,4));
00743       if($this->do_debug >= 1) {
00744         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
00745       }
00746       return false;
00747     }
00748     return true;
00749   }
00750 
00764   public function Turn() {
00765     $this->error = array("error" => "This method, TURN, of the SMTP ".
00766                                     "is not implemented");
00767     if($this->do_debug >= 1) {
00768       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
00769     }
00770     return false;
00771   }
00772 
00778   public function getError() {
00779     return $this->error;
00780   }
00781 
00783   // INTERNAL FUNCTIONS
00785 
00795   private function get_lines() {
00796     $data = "";
00797     while($str = @fgets($this->smtp_conn,515)) {
00798       if($this->do_debug >= 4) {
00799         echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
00800         echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
00801       }
00802       $data .= $str;
00803       if($this->do_debug >= 4) {
00804         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
00805       }
00806       // if 4th character is a space, we are done reading, break the loop
00807       if(substr($str,3,1) == " ") { break; }
00808     }
00809     return $data;
00810   }
00811 
00812 }
00813 
00814 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations