<?php |
/** |
* PHPMailer RFC821 SMTP email transport class. |
* PHP Version 5 |
* @package PHPMailer |
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project |
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> |
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> |
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> |
* @author Brent R. Matzelle (original founder) |
* @copyright 2014 Marcus Bointon |
* @copyright 2010 - 2012 Jim Jagielski |
* @copyright 2004 - 2009 Andy Prevost |
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License |
* @note 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. |
*/ |
/** |
* PHPMailer RFC821 SMTP email transport class. |
* Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. |
* @package PHPMailer |
* @author Chris Ryan <unknown@example.com> |
* @author Marcus Bointon <phpmailer@synchromedia.co.uk> |
*/ |
class SMTP |
{ |
/** |
* The PHPMailer SMTP version number. |
* @type string |
*/ |
const VERSION = '5.2.7' ; |
/** |
* SMTP line break constant. |
* @type string |
*/ |
const CRLF = "\r\n" ; |
/** |
* The SMTP port to use if one is not specified. |
* @type int |
*/ |
const DEFAULT_SMTP_PORT = 25; |
/** |
* The maximum line length allowed by RFC 2822 section 2.1.1 |
* @type int |
*/ |
const MAX_LINE_LENGTH = 998; |
/** |
* The PHPMailer SMTP Version number. |
* @type string |
* @deprecated Use the constant instead |
* @see SMTP::VERSION |
*/ |
public $Version = '5.2.7' ; |
/** |
* SMTP server port number. |
* @type int |
* @deprecated This is only ever used as a default value, so use the constant instead |
* @see SMTP::DEFAULT_SMTP_PORT |
*/ |
public $SMTP_PORT = 25; |
/** |
* SMTP reply line ending. |
* @type string |
* @deprecated Use the constant instead |
* @see SMTP::CRLF |
*/ |
public $CRLF = "\r\n" ; |
/** |
* Debug output level. |
* Options: |
* * `0` No output |
* * `1` Commands |
* * `2` Data and commands |
* * `3` As 2 plus connection status |
* * `4` Low-level data output |
* @type int |
*/ |
public $do_debug = 0; |
/** |
* How to handle debug output. |
* Options: |
* * `echo` Output plain-text as-is, appropriate for CLI |
* * `html` Output escaped, line breaks converted to <br>, appropriate for browser output |
* * `error_log` Output to error log as configured in php.ini |
* @type string |
*/ |
public $Debugoutput = 'echo' ; |
/** |
* Whether to use VERP. |
* @link http://en.wikipedia.org/wiki/Variable_envelope_return_path |
* @link http://www.postfix.org/VERP_README.html Info on VERP |
* @type bool |
*/ |
public $do_verp = false; |
/** |
* The timeout value for connection, in seconds. |
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 |
* This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. |
* @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 |
* @type int |
*/ |
public $Timeout = 300; |
/** |
* The SMTP timelimit value for reads, in seconds. |
* @type int |
*/ |
public $Timelimit = 30; |
/** |
* The socket for the server connection. |
* @type resource |
*/ |
protected $smtp_conn ; |
/** |
* Error message, if any, for the last call. |
* @type string |
*/ |
protected $error = '' ; |
/** |
* The reply the server sent to us for HELO. |
* @type string |
*/ |
protected $helo_rply = '' ; |
/** |
* The most recent reply received from the server. |
* @type string |
*/ |
protected $last_reply = '' ; |
/** |
* Constructor. |
* @access public |
*/ |
public function __construct() |
{ |
$this ->smtp_conn = 0; |
$this ->error = null; |
$this ->helo_rply = null; |
$this ->do_debug = 0; |
} |
/** |
* Output debugging info via a user-selected method. |
* @param string $str Debug string to output |
* @return void |
*/ |
protected function edebug( $str ) |
{ |
switch ( $this ->Debugoutput) { |
case 'error_log' : |
//Don't output, just log |
error_log ( $str ); |
break ; |
case 'html' : |
//Cleans up output a bit for a better looking, HTML-safe output |
echo htmlentities( |
preg_replace( '/[\r\n]+/' , '' , $str ), |
ENT_QUOTES, |
'UTF-8' |
) |
. "<br>\n" ; |
break ; |
case 'echo' : |
default : |
echo gmdate ( 'Y-m-d H:i:s' ). "\t" .trim( $str ). "\n" ; |
} |
} |
/** |
* Connect to an SMTP server. |
* @param string $host SMTP server IP or host name |
* @param int $port The port number to connect to |
* @param int $timeout How long to wait for the connection to open |
* @param array $options An array of options for stream_context_create() |
* @access public |
* @return bool |
*/ |
public function connect( $host , $port = null, $timeout = 30, $options = array ()) |
{ |
// Clear errors to avoid confusion |
$this ->error = null; |
// Make sure we are __not__ connected |
if ( $this ->connected()) { |
// Already connected, generate error |
$this ->error = array ( 'error' => 'Already connected to a server' ); |
return false; |
} |
if ( empty ( $port )) { |
$port = self::DEFAULT_SMTP_PORT; |
} |
// Connect to the SMTP server |
if ( $this ->do_debug >= 3) { |
$this ->edebug( 'Connection: opening' ); |
} |
$errno = 0; |
$errstr = '' ; |
$socket_context = stream_context_create( $options ); |
//Suppress errors; connection failures are handled at a higher level |
$this ->smtp_conn = @stream_socket_client( |
$host . ":" . $port , |
$errno , |
$errstr , |
$timeout , |
STREAM_CLIENT_CONNECT, |
$socket_context |
); |
// Verify we connected properly |
if ( empty ( $this ->smtp_conn)) { |
$this ->error = array ( |
'error' => 'Failed to connect to server' , |
'errno' => $errno , |
'errstr' => $errstr |
); |
if ( $this ->do_debug >= 1) { |
$this ->edebug( |
'SMTP ERROR: ' . $this ->error[ 'error' ] |
. ": $errstr ($errno)" |
); |
} |
return false; |
} |
if ( $this ->do_debug >= 3) { |
$this ->edebug( 'Connection: opened' ); |
} |
// 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' ) { |
$max = ini_get ( 'max_execution_time' ); |
if ( $max != 0 && $timeout > $max ) { // Don't bother if unlimited |
@set_time_limit( $timeout ); |
} |
stream_set_timeout( $this ->smtp_conn, $timeout , 0); |
} |
// Get any announcement |
$announce = $this ->get_lines(); |
if ( $this ->do_debug >= 2) { |
$this ->edebug( 'SERVER -> CLIENT: ' . $announce ); |
} |
return true; |
} |
/** |
* Initiate a TLS (encrypted) session. |
* @access public |
* @return bool |
*/ |
public function startTLS() |
{ |
if (! $this ->sendCommand( 'STARTTLS' , 'STARTTLS' , 220)) { |
return false; |
} |
// Begin encrypted connection |
if (!stream_socket_enable_crypto( |
$this ->smtp_conn, |
true, |
STREAM_CRYPTO_METHOD_TLS_CLIENT |
)) { |
return false; |
} |
return true; |
} |
/** |
* Perform SMTP authentication. |
* Must be run after hello(). |
* @see hello() |
* @param string $username The user name |
* @param string $password The password |
* @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5) |
* @param string $realm The auth realm for NTLM |
* @param string $workstation The auth workstation for NTLM |
* @access public |
* @return bool True if successfully authenticated. |
*/ |
public function authenticate( |
$username , |
$password , |
$authtype = 'LOGIN' , |
$realm = '' , |
$workstation = '' |
) { |
if ( empty ( $authtype )) { |
$authtype = 'LOGIN' ; |
} |
switch ( $authtype ) { |
case 'PLAIN' : |
// Start authentication |
if (! $this ->sendCommand( 'AUTH' , 'AUTH PLAIN' , 334)) { |
return false; |
} |
// Send encoded username and password |
if (! $this ->sendCommand( |
'User & Password' , |
base64_encode ( "\0" . $username . "\0" . $password ), |
235 |
) |
) { |
return false; |
} |
break ; |
case 'LOGIN' : |
// Start authentication |
if (! $this ->sendCommand( 'AUTH' , 'AUTH LOGIN' , 334)) { |
return false; |
} |
if (! $this ->sendCommand( "Username" , base64_encode ( $username ), 334)) { |
return false; |
} |
if (! $this ->sendCommand( "Password" , base64_encode ( $password ), 235)) { |
return false; |
} |
break ; |
case 'NTLM' : |
/* |
* ntlm_sasl_client.php |
* Bundled with Permission |
* |
* How to telnet in windows: |
* http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx |
* PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication |
*/ |
require_once 'extras/ntlm_sasl_client.php' ; |
$temp = new stdClass(); |
$ntlm_client = new ntlm_sasl_client_class; |
//Check that functions are available |
if (! $ntlm_client ->Initialize( $temp )) { |
$this ->error = array ( 'error' => $temp ->error); |
if ( $this ->do_debug >= 1) { |
$this ->edebug( |
'You need to enable some modules in your php.ini file: ' |
. $this ->error[ 'error' ] |
); |
} |
return false; |
} |
//msg1 |
$msg1 = $ntlm_client ->TypeMsg1( $realm , $workstation ); //msg1 |
if (! $this ->sendCommand( |
'AUTH NTLM' , |
'AUTH NTLM ' . base64_encode ( $msg1 ), |
334 |
) |
) { |
return false; |
} |
//Though 0 based, there is a white space after the 3 digit number |
//msg2 |
$challenge = substr ( $this ->last_reply, 3); |
$challenge = base64_decode ( $challenge ); |
$ntlm_res = $ntlm_client ->NTLMResponse( |
substr ( $challenge , 24, 8), |
$password |
); |
//msg3 |
$msg3 = $ntlm_client ->TypeMsg3( |
$ntlm_res , |
$username , |
$realm , |
$workstation |
); |
// send encoded username |
return $this ->sendCommand( 'Username' , base64_encode ( $msg3 ), 235); |
break ; |
case 'CRAM-MD5' : |
// Start authentication |
if (! $this ->sendCommand( 'AUTH CRAM-MD5' , 'AUTH CRAM-MD5' , 334)) { |
return false; |
} |
// Get the challenge |
$challenge = base64_decode ( substr ( $this ->last_reply, 4)); |
// Build the response |
$response = $username . ' ' . $this ->hmac( $challenge , $password ); |
// send encoded credentials |
return $this ->sendCommand( 'Username' , base64_encode ( $response ), 235); |
break ; |
} |
return true; |
} |
/** |
* Calculate an MD5 HMAC hash. |
* Works like hash_hmac('md5', $data, $key) |
* in case that function is not available |
* @param string $data The data to hash |
* @param string $key The key to hash with |
* @access protected |
* @return string |
*/ |
protected function hmac( $data , $key ) |
{ |
if (function_exists( 'hash_hmac' )) { |
return hash_hmac( 'md5' , $data , $key ); |
} |
// The following borrowed from |
// http://php.net/manual/en/function.mhash.php#27225 |
// RFC 2104 HMAC implementation for php. |
// Creates an md5 HMAC. |
// Eliminates the need to install mhash to compute a HMAC |
// Hacked by Lance Rushing |
$bytelen = 64; // byte length for md5 |
if ( strlen ( $key ) > $bytelen ) { |
$key = pack( 'H*' , md5( $key )); |
} |
$key = str_pad ( $key , $bytelen , chr (0x00)); |
$ipad = str_pad ( '' , $bytelen , chr (0x36)); |
$opad = str_pad ( '' , $bytelen , chr (0x5c)); |
$k_ipad = $key ^ $ipad ; |
$k_opad = $key ^ $opad ; |
return md5( $k_opad . pack( 'H*' , md5( $k_ipad . $data ))); |
} |
/** |
* Check connection state. |
* @access public |
* @return bool True if connected. |
*/ |
public function connected() |
{ |
if (! empty ( $this ->smtp_conn)) { |
$sock_status = stream_get_meta_data( $this ->smtp_conn); |
if ( $sock_status [ 'eof' ]) { |
// the socket is valid but we are not connected |
if ( $this ->do_debug >= 1) { |
$this ->edebug( |
'SMTP NOTICE: EOF caught while checking if connected' |
); |
} |
$this ->close(); |
return false; |
} |
return true; // everything looks good |
} |
return false; |
} |
/** |
* Close the socket and clean up the state of the class. |
* Don't use this function without first trying to use QUIT. |
* @see quit() |
* @access public |
* @return void |
*/ |
public function close() |
{ |
$this ->error = null; // so there is no confusion |
$this ->helo_rply = null; |
if (! empty ( $this ->smtp_conn)) { |
// close the connection and cleanup |
fclose( $this ->smtp_conn); |
if ( $this ->do_debug >= 3) { |
$this ->edebug( 'Connection: closed' ); |
} |
$this ->smtp_conn = 0; |
} |
} |
/** |
* Send an SMTP DATA command. |
* 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 separated by and additional <CRLF>. |
* Implements rfc 821: DATA <CRLF> |
* @param string $msg_data Message data to send |
* @access public |
* @return bool |
*/ |
public function data( $msg_data ) |
{ |
if (! $this ->sendCommand( 'DATA' , 'DATA' , 354)) { |
return false; |
} |
/* The server is ready to accept data! |
* According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) |
* 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. |
* We will also look for lines that start with a '.' and prepend an additional '.'. |
* NOTE: this does not count towards line-length limit. |
*/ |
// Normalize line breaks before exploding |
$lines = explode ( "\n" , str_replace ( array ( "\r\n" , "\r" ), "\n" , $msg_data )); |
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field |
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will |
* process all lines before a blank line as headers. |
*/ |
$field = substr ( $lines [0], 0, strpos ( $lines [0], ':' )); |
$in_headers = false; |
if (! empty ( $field ) && strpos ( $field , ' ' ) === false) { |
$in_headers = true; |
} |
foreach ( $lines as $line ) { |
$lines_out = array (); |
if ( $in_headers and $line == '' ) { |
$in_headers = false; |
} |
// ok we need to break this line up into several smaller lines |
//This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len) |
while (isset( $line [self::MAX_LINE_LENGTH])) { |
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on |
//so as to avoid breaking in the middle of a word |
$pos = strrpos ( substr ( $line , 0, self::MAX_LINE_LENGTH), ' ' ); |
if (! $pos ) { //Deliberately matches both false and 0 |
//No nice break found, add a hard break |
$pos = self::MAX_LINE_LENGTH - 1; |
$lines_out [] = substr ( $line , 0, $pos ); |
$line = substr ( $line , $pos ); |
} else { |
//Break at the found point |
$lines_out [] = substr ( $line , 0, $pos ); |
//Move along by the amount we dealt with |
$line = substr ( $line , $pos + 1); |
} |
/* If processing headers add a LWSP-char to the front of new line |
* RFC822 section 3.1.1 |
*/ |
if ( $in_headers ) { |
$line = "\t" . $line ; |
} |
} |
$lines_out [] = $line ; |
// Send the lines to the server |
foreach ( $lines_out as $line_out ) { |
//RFC2821 section 4.5.2 |
if (! empty ( $line_out ) and $line_out [0] == '.' ) { |
$line_out = '.' . $line_out ; |
} |
$this ->client_send( $line_out . self::CRLF); |
} |
} |
// Message data has been sent, complete the command |
return $this ->sendCommand( 'DATA END' , '.' , 250); |
} |
/** |
* Send an SMTP HELO or EHLO command. |
* Used to identify the sending server to the receiving server. |
* This makes sure that client and server are in a known state. |
* Implements RFC 821: HELO <SP> <domain> <CRLF> |
* and RFC 2821 EHLO. |
* @param string $host The host name or IP to connect to |
* @access public |
* @return bool |
*/ |
public function hello( $host = '' ) |
{ |
// Try extended hello first (RFC 2821) |
return (bool)( $this ->sendHello( 'EHLO' , $host ) or $this ->sendHello( 'HELO' , $host )); |
} |
/** |
* Send an SMTP HELO or EHLO command. |
* Low-level implementation used by hello() |
* @see hello() |
* @param string $hello The HELO string |
* @param string $host The hostname to say we are |
* @access protected |
* @return bool |
*/ |
protected function sendHello( $hello , $host ) |
{ |
$noerror = $this ->sendCommand( $hello , $hello . ' ' . $host , 250); |
$this ->helo_rply = $this ->last_reply; |
return $noerror ; |
} |
/** |
* Send an SMTP MAIL command. |
* 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> |
* @param string $from Source address of this message |
* @access public |
* @return bool |
*/ |
public function mail( $from ) |
{ |
$useVerp = ( $this ->do_verp ? ' XVERP' : '' ); |
return $this ->sendCommand( |
'MAIL FROM' , |
'MAIL FROM:<' . $from . '>' . $useVerp , |
250 |
); |
} |
/** |
* Send an SMTP QUIT command. |
* Closes the socket if there is no error or the $close_on_error argument is true. |
* Implements from rfc 821: QUIT <CRLF> |
* @param bool $close_on_error Should the connection close if an error occurs? |
* @access public |
* @return bool |
*/ |
public function quit( $close_on_error = true) |
{ |
$noerror = $this ->sendCommand( 'QUIT' , 'QUIT' , 221); |
$err = $this ->error; //Save any error |
if ( $noerror or $close_on_error ) { |
$this ->close(); |
$this ->error = $err ; //Restore any error from the quit command |
} |
return $noerror ; |
} |
/** |
* Send an SMTP RCPT command. |
* Sets the TO argument to $toaddr. |
* Returns true if the recipient was accepted false if it was rejected. |
* Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> |
* @param string $toaddr The address the message is being sent to |
* @access public |
* @return bool |
*/ |
public function recipient( $toaddr ) |
{ |
return $this ->sendCommand( |
'RCPT TO' , |
'RCPT TO:<' . $toaddr . '>' , |
array (250, 251) |
); |
} |
/** |
* Send an SMTP RSET command. |
* Abort any transaction that is currently in progress. |
* Implements rfc 821: RSET <CRLF> |
* @access public |
* @return bool True on success. |
*/ |
public function reset() |
{ |
return $this ->sendCommand( 'RSET' , 'RSET' , 250); |
} |
/** |
* Send a command to an SMTP server and check its return code. |
* @param string $command The command name - not sent to the server |
* @param string $commandstring The actual command to send |
* @param int|array $expect One or more expected integer success codes |
* @access protected |
* @return bool True on success. |
*/ |
protected function sendCommand( $command , $commandstring , $expect ) |
{ |
if (! $this ->connected()) { |
$this ->error = array ( |
'error' => "Called $command without being connected" |
); |
return false; |
} |
$this ->client_send( $commandstring . self::CRLF); |
$reply = $this ->get_lines(); |
$code = substr ( $reply , 0, 3); |
if ( $this ->do_debug >= 2) { |
$this ->edebug( 'SERVER -> CLIENT: ' . $reply ); |
} |
if (!in_array( $code , ( array ) $expect )) { |
$this ->last_reply = null; |
$this ->error = array ( |
'error' => "$command command failed" , |
'smtp_code' => $code , |
'detail' => substr ( $reply , 4) |
); |
if ( $this ->do_debug >= 1) { |
$this ->edebug( |
'SMTP ERROR: ' . $this ->error[ 'error' ] . ': ' . $reply |
); |
} |
return false; |
} |
$this ->last_reply = $reply ; |
$this ->error = null; |
return true; |
} |
/** |
* Send an SMTP SAML command. |
* 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> |
* @param string $from The address the message is from |
* @access public |
* @return bool |
*/ |
public function sendAndMail( $from ) |
{ |
return $this ->sendCommand( 'SAML' , "SAML FROM:$from" , 250); |
} |
/** |
* Send an SMTP VRFY command. |
* @param string $name The name to verify |
* @access public |
* @return bool |
*/ |
public function verify( $name ) |
{ |
return $this ->sendCommand( 'VRFY' , "VRFY $name" , array (250, 251)); |
} |
/** |
* Send an SMTP NOOP command. |
* Used to keep keep-alives alive, doesn't actually do anything |
* @access public |
* @return bool |
*/ |
public function noop() |
{ |
return $this ->sendCommand( 'NOOP' , 'NOOP' , 250); |
} |
/** |
* Send an SMTP TURN command. |
* 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 implemented in future |
* Implements from rfc 821: TURN <CRLF> |
* @access public |
* @return bool |
*/ |
public function turn() |
{ |
$this ->error = array ( |
'error' => 'The SMTP TURN command is not implemented' |
); |
if ( $this ->do_debug >= 1) { |
$this ->edebug( 'SMTP NOTICE: ' . $this ->error[ 'error' ]); |
} |
return false; |
} |
/** |
* Send raw data to the server. |
* @param string $data The data to send |
* @access public |
* @return int|bool The number of bytes sent to the server or false on error |
*/ |
public function client_send( $data ) |
{ |
if ( $this ->do_debug >= 1) { |
$this ->edebug( "CLIENT -> SERVER: $data" ); |
} |
return fwrite( $this ->smtp_conn, $data ); |
} |
/** |
* Get the latest error. |
* @access public |
* @return array |
*/ |
public function getError() |
{ |
return $this ->error; |
} |
/** |
* Get the last reply from the server. |
* @access public |
* @return string |
*/ |
public function getLastReply() |
{ |
return $this ->last_reply; |
} |
/** |
* Read the SMTP server's response. |
* 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. |
* @access protected |
* @return string |
*/ |
protected function get_lines() |
{ |
// If the connection is bad, give up straight away |
if (! is_resource ( $this ->smtp_conn)) { |
return '' ; |
} |
$data = '' ; |
$endtime = 0; |
stream_set_timeout( $this ->smtp_conn, $this ->Timeout); |
if ( $this ->Timelimit > 0) { |
$endtime = time() + $this ->Timelimit; |
} |
while ( is_resource ( $this ->smtp_conn) && ! feof ( $this ->smtp_conn)) { |
$str = @ fgets ( $this ->smtp_conn, 515); |
if ( $this ->do_debug >= 4) { |
$this ->edebug( "SMTP -> get_lines(): \$data was \"$data\"" ); |
$this ->edebug( "SMTP -> get_lines(): \$str is \"$str\"" ); |
} |
$data .= $str ; |
if ( $this ->do_debug >= 4) { |
$this ->edebug( "SMTP -> get_lines(): \$data is \"$data\"" ); |
} |
// If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen |
if ((isset( $str [3]) and $str [3] == ' ' )) { |
break ; |
} |
// Timed-out? Log and break |
$info = stream_get_meta_data( $this ->smtp_conn); |
if ( $info [ 'timed_out' ]) { |
if ( $this ->do_debug >= 4) { |
$this ->edebug( |
'SMTP -> get_lines(): timed-out (' . $this ->Timeout . ' sec)' |
); |
} |
break ; |
} |
// Now check if reads took too long |
if ( $endtime and time() > $endtime ) { |
if ( $this ->do_debug >= 4) { |
$this ->edebug( |
'SMTP -> get_lines(): timelimit reached (' . |
$this ->Timelimit . ' sec)' |
); |
} |
break ; |
} |
} |
return $data ; |
} |
/** |
* Enable or disable VERP address generation. |
* @param bool $enabled |
*/ |
public function setVerp( $enabled = false) |
{ |
$this ->do_verp = $enabled ; |
} |
/** |
* Get VERP address generation mode. |
* @return bool |
*/ |
public function getVerp() |
{ |
return $this ->do_verp; |
} |
/** |
* Set debug output method. |
* @param string $method The function/method to use for debugging output. |
*/ |
public function setDebugOutput( $method = 'echo' ) |
{ |
$this ->Debugoutput = $method ; |
} |
/** |
* Get debug output method. |
* @return string |
*/ |
public function getDebugOutput() |
{ |
return $this ->Debugoutput; |
} |
/** |
* Set debug output level. |
* @param int $level |
*/ |
public function setDebugLevel( $level = 0) |
{ |
$this ->do_debug = $level ; |
} |
/** |
* Get debug output level. |
* @return int |
*/ |
public function getDebugLevel() |
{ |
return $this ->do_debug; |
} |
/** |
* Set SMTP timeout. |
* @param int $timeout |
*/ |
public function setTimeout( $timeout = 0) |
{ |
$this ->Timeout = $timeout ; |
} |
/** |
* Get SMTP timeout. |
* @return int |
*/ |
public function getTimeout() |
{ |
return $this ->Timeout; |
} |
} |