Source for file class.smtp.php
Documentation is available at class.smtp.php
.---------------------------------------------------------------------------.
| Software: PHPMailer - PHP email class |
| Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
| Info: http://phpmailer.sourceforge.net |
| Support: http://sourceforge.net/projects/phpmailer/ |
| ------------------------------------------------------------------------- |
| Admin: Andy Prevost (project admininistrator) |
| Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net |
| Founder: Brent R. Matzelle (original founder) |
| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. |
| Copyright (c) 2001-2003, Brent R. Matzelle |
| ------------------------------------------------------------------------- |
| License: Distributed under the Lesser General Public License (LGPL) |
| http://www.gnu.org/copyleft/lesser.html |
| This program is distributed in the hope that it will be useful - WITHOUT |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. |
| ------------------------------------------------------------------------- |
| We offer a number of paid services (www.codeworxtech.com): |
| - Web Hosting on highly optimized fast and secure servers |
| - Technology Consulting |
| - Oursourcing (highly qualified programmers and graphic designers) |
'---------------------------------------------------------------------------'
* PHPMailer - PHP SMTP email transport class
* NOTE: Designed for use with PHP version 5 and up
* @copyright 2004 - 2008 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
* @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $
* SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
* commands except TURN which will always return a not implemented
* error. SMTP also provides some utility methods for sending mail
* original author: Chris Ryan
* Sets whether debugging is turned on
public $do_debug; // the level of debug to perform
* Sets VERP use on/off (default is off)
/////////////////////////////////////////////////
// PROPERTIES, PRIVATE AND PROTECTED
/////////////////////////////////////////////////
private $smtp_conn; // the socket to the server
private $error; // error if any on the last call
private $helo_rply; // the reply the server sent to us for HELO
* Initialize the class so that the data is in a known state.
/////////////////////////////////////////////////
/////////////////////////////////////////////////
* Connect to the server specified on the port specified.
* If the port is not specified use the default SMTP_PORT.
* If tval is specified then a connection will try and be
* established with the server for that number of seconds.
* If tval is not specified the default is 30 seconds to
public function Connect($host, $port =
0, $tval =
30) {
// set the error val to null so there is no confusion
// make sure we are __not__ connected
// already connected, generate error
$this->error =
array("error" =>
"Already connected to a server");
// connect to the smtp server
$this->smtp_conn =
@fsockopen($host, // the host of the server
$port, // the port to use
$errno, // error number if any
$errstr, // error message if any
$tval); // give up after ? secs
// verify we connected properly
if(empty($this->smtp_conn)) {
$this->error =
array("error" =>
"Failed to connect to server",
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": $errstr ($errno)" .
$this->CRLF .
'<br />';
// SMTP server can take longer to respond, give longer timeout for first read
// Windows does not have support for this timeout function
if(substr(PHP_OS, 0, 3) !=
"WIN")
$announce =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$announce .
$this->CRLF .
'<br />';
* Initiate a TLS communication with the server.
* SMTP CODE 220 Ready to start TLS
* SMTP CODE 501 Syntax error (no parameters allowed)
* SMTP CODE 454 TLS not available due to temporary reason
$this->error =
null; # to avoid confusion
if(!$this->connected()) {
$this->error =
array("error" =>
"Called StartTLS() without being connected");
fputs($this->smtp_conn,"STARTTLS" .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
array("error" =>
"STARTTLS not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
// Begin encrypted connection
* Performs SMTP authentication. Must be run after running the
* Hello() method. Returns true if successfully authenticated.
fputs($this->smtp_conn,"AUTH LOGIN" .
$this->CRLF);
$rply =
$this->get_lines();
array("error" =>
"AUTH not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
$rply =
$this->get_lines();
array("error" =>
"Username not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
$rply =
$this->get_lines();
array("error" =>
"Password not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
* Returns true if connected to a server otherwise false
if(!empty($this->smtp_conn)) {
if($sock_status["eof"]) {
// the socket is valid but we are not connected
echo
"SMTP -> NOTICE:" .
$this->CRLF .
"EOF caught while checking if connected";
return true; // everything looks good
* Closes the socket and cleans up the state of the class.
* It is not considered good to use this function without
* first trying to use QUIT.
public function Close() {
$this->error =
null; // so there is no confusion
if(!empty($this->smtp_conn)) {
// close the connection and cleanup
/////////////////////////////////////////////////
/////////////////////////////////////////////////
* Issues a data command and sends the msg_data to the server
* finializing the mail transaction. $msg_data is the message
* that is to be send with the headers. Each header needs to be
* on a single line followed by a <CRLF> with the message headers
* and the message body being seperated by and additional <CRLF>.
* Implements rfc 821: DATA <CRLF>
* SMTP CODE INTERMEDIATE: 354
* SMTP CODE FAILURE: 552,554,451,452
* SMTP CODE FAILURE: 451,554
* SMTP CODE ERROR : 500,501,503,421
public function Data($msg_data) {
$this->error =
null; // so no confusion is caused
if(!$this->connected()) {
"error" =>
"Called Data() without being connected");
fputs($this->smtp_conn,"DATA" .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
array("error" =>
"DATA command not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
/* the server is ready to accept data!
* according to rfc 821 we should not send more than 1000
* characters on a single line so we will break the data up
* into lines by \r and/or \n then if needed we will break
* each of those into smaller lines to fit within the limit.
* in addition we will be looking for lines that start with
* a period '.' and append and additional period '.' to that
* line. NOTE: this does not count towards limit.
// normalize the line breaks so we know the explode works
/* we need to find a good way to determine is headers are
* in the msg_data or if it is a straight msg body
* currently I am assuming rfc 822 definitions of msg headers
* and if the first field of the first line (':' sperated)
* does not contain a space then it _should_ be a header
* and we can process all lines before a blank "" line as
if(!empty($field) &&
!strstr($field," ")) {
$max_line_length =
998; // used below; set here for ease in change
while(list
(,$line) =
@each($lines)) {
if($line ==
"" &&
$in_headers) {
// ok we need to break this line up into several smaller lines
while(strlen($line) >
$max_line_length) {
// Patch to fix DOS attack
$pos =
$max_line_length -
1;
$lines_out[] =
substr($line,0,$pos);
$lines_out[] =
substr($line,0,$pos);
$line =
substr($line,$pos +
1);
/* if processing headers add a LWSP-char to the front of new line
* rfc 822 on long msg headers
// send the lines to the server
while(list
(,$line_out) =
@each($lines_out)) {
if(substr($line_out, 0, 1) ==
".") {
$line_out =
"." .
$line_out;
fputs($this->smtp_conn,$line_out .
$this->CRLF);
// message data has been sent
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
array("error" =>
"DATA not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
* Sends the HELO command to the smtp server.
* This makes sure that we and the server are in
* Implements from rfc 821: HELO <SP> <domain> <CRLF>
* SMTP CODE ERROR : 500, 501, 504, 421
public function Hello($host =
'') {
$this->error =
null; // so no confusion is caused
if(!$this->connected()) {
"error" =>
"Called Hello() without being connected");
// if hostname for HELO was not specified send default
// determine appropriate default to send to server
// Send extended hello first (RFC 2821)
if(!$this->SendHello("EHLO", $host)) {
if(!$this->SendHello("HELO", $host)) {
* Sends a HELO/EHLO command.
private function SendHello($hello, $host) {
fputs($this->smtp_conn, $hello .
" " .
$host .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER: " .
$rply .
$this->CRLF .
'<br />';
array("error" =>
$hello .
" not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
$this->helo_rply =
$rply;
* Starts a mail transaction from the email address specified in
* $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more Recipient
* commands may be called followed by a Data command.
* Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
* SMTP CODE SUCCESS: 552,451,452
* SMTP CODE SUCCESS: 500,501,421
public function Mail($from) {
$this->error =
null; // so no confusion is caused
if(!$this->connected()) {
"error" =>
"Called Mail() without being connected");
$useVerp =
($this->do_verp ?
"XVERP" :
"");
fputs($this->smtp_conn,"MAIL FROM:<" .
$from .
">" .
$useVerp .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
array("error" =>
"MAIL not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
* Sends the quit command to the server and then closes the socket
* if there is no error or the $close_on_error argument is true.
* Implements from rfc 821: QUIT <CRLF>
public function Quit($close_on_error =
true) {
$this->error =
null; // so there is no confusion
if(!$this->connected()) {
"error" =>
"Called Quit() without being connected");
// send the quit command to the server
fputs($this->smtp_conn,"quit" .
$this->CRLF);
// get any good-bye messages
$byemsg =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$byemsg .
$this->CRLF .
'<br />';
// use e as a tmp var cause Close will overwrite $this->error
$e =
array("error" =>
"SMTP server rejected quit command",
"smtp_rply" =>
substr($byemsg,4));
echo
"SMTP -> ERROR: " .
$e["error"] .
": " .
$byemsg .
$this->CRLF .
'<br />';
if(empty($e) ||
$close_on_error) {
* Sends the command RCPT to the SMTP server with the TO: argument of $to.
* Returns true if the recipient was accepted false if it was rejected.
* Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
* SMTP CODE SUCCESS: 250,251
* SMTP CODE FAILURE: 550,551,552,553,450,451,452
* SMTP CODE ERROR : 500,501,503,421
$this->error =
null; // so no confusion is caused
if(!$this->connected()) {
"error" =>
"Called Recipient() without being connected");
fputs($this->smtp_conn,"RCPT TO:<" .
$to .
">" .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
if($code !=
250 &&
$code !=
251) {
array("error" =>
"RCPT not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
* Sends the RSET command to abort and transaction that is
* currently in progress. Returns true if successful false
* Implements rfc 821: RSET <CRLF>
* SMTP CODE ERROR : 500,501,504,421
public function Reset() {
$this->error =
null; // so no confusion is caused
if(!$this->connected()) {
"error" =>
"Called Reset() without being connected");
fputs($this->smtp_conn,"RSET" .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
array("error" =>
"RSET failed",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
* Starts a mail transaction from the email address specified in
* $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more Recipient
* commands may be called followed by a Data command. This command
* will send the message to the users terminal if they are logged
* in and send them an email.
* Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
* SMTP CODE SUCCESS: 552,451,452
* SMTP CODE SUCCESS: 500,501,502,421
$this->error =
null; // so no confusion is caused
if(!$this->connected()) {
"error" =>
"Called SendAndMail() without being connected");
fputs($this->smtp_conn,"SAML FROM:" .
$from .
$this->CRLF);
$rply =
$this->get_lines();
echo
"SMTP -> FROM SERVER:" .
$rply .
$this->CRLF .
'<br />';
array("error" =>
"SAML not accepted from server",
"smtp_msg" =>
substr($rply,4));
echo
"SMTP -> ERROR: " .
$this->error["error"] .
": " .
$rply .
$this->CRLF .
'<br />';
* This is an optional command for SMTP that this class does not
* support. This method is here to make the RFC821 Definition
* complete for this class and __may__ be implimented in the future
* Implements from rfc 821: TURN <CRLF>
* SMTP CODE ERROR : 500, 503
$this->error =
array("error" =>
"This method, TURN, of the SMTP ".
echo
"SMTP -> NOTICE: " .
$this->error["error"] .
$this->CRLF .
'<br />';
/////////////////////////////////////////////////
/////////////////////////////////////////////////
* Read in as many lines as possible
* either before eof or socket timeout occurs on the operation.
* With SMTP we can tell if we have more lines to read if the
* 4th character is '-' symbol. If it is a space then we don't
* need to read anything else.
private function get_lines() {
while($str =
@fgets($this->smtp_conn,515)) {
echo
"SMTP -> get_lines(): \$data was \"$data\"" .
$this->CRLF .
'<br />';
echo
"SMTP -> get_lines(): \$str is \"$str\"" .
$this->CRLF .
'<br />';
echo
"SMTP -> get_lines(): \$data is \"$data\"" .
$this->CRLF .
'<br />';
// if 4th character is a space, we are done reading, break the loop
if(substr($str,3,1) ==
" ") { break; }
Documentation generated on Sun, 04 Apr 2010 22:43:39 +0200 by phpDocumentor 1.4.1