3
3
* PHPMailer RFC821 SMTP email transport class.
8
* @link https://github.com/PHPMailer/PHPMailer/
9
* @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
6
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
7
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
10
8
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
11
9
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
12
* @copyright 2013 Marcus Bointon
13
* @copyright 2004 - 2008 Andy Prevost
10
* @author Brent R. Matzelle (original founder)
11
* @copyright 2014 Marcus Bointon
14
12
* @copyright 2010 - 2012 Jim Jagielski
15
* @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
13
* @copyright 2004 - 2009 Andy Prevost
14
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
15
* @note This program is distributed in the hope that it will be useful - WITHOUT
16
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
* FITNESS FOR A PARTICULAR PURPOSE.
19
21
* PHPMailer RFC821 SMTP email transport class.
21
* Implements RFC 821 SMTP commands
22
* and provides some utility methods for sending mail to an SMTP server.
28
* @link https://github.com/PHPMailer/PHPMailer/blob/master/class.smtp.php
29
* @author Chris Ryan <unknown@example.com>
30
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
31
* @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
22
* Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server.
25
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
37
* The PHPMailer SMTP Version number.
30
* The PHPMailer SMTP version number.
39
const VERSION = '5.2.7';
33
const VERSION = '5.2.10';
42
36
* SMTP line break constant.
44
39
const CRLF = "\r\n";
47
42
* The SMTP port to use if one is not specified.
49
45
const DEFAULT_SMTP_PORT = 25;
48
* The maximum line length allowed by RFC 2822 section 2.1.1
51
const MAX_LINE_LENGTH = 998;
54
* Debug level for no output
59
* Debug level to show client -> server messages
61
const DEBUG_CLIENT = 1;
64
* Debug level to show client -> server and server -> client messages
66
const DEBUG_SERVER = 2;
69
* Debug level to show connection status, client -> server and server -> client messages
71
const DEBUG_CONNECTION = 3;
74
* Debug level to show all messages
76
const DEBUG_LOWLEVEL = 4;
52
79
* The PHPMailer SMTP Version number.
54
* @deprecated This should be a constant
81
* @deprecated Use the `VERSION` constant instead
55
82
* @see SMTP::VERSION
57
public $Version = '5.2.7';
84
public $Version = '5.2.10';
60
87
* SMTP server port number.
62
* @deprecated This is only ever ued as default value, so should be a constant
89
* @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead
63
90
* @see SMTP::DEFAULT_SMTP_PORT
65
92
public $SMTP_PORT = 25;
68
* SMTP reply line ending
95
* SMTP reply line ending.
70
* @deprecated Use the class constant instead
97
* @deprecated Use the `CRLF` constant instead
73
100
public $CRLF = "\r\n";
76
103
* Debug output level.
77
* Options: 0 for no output, 1 for commands, 2 for data and commands
105
* * self::DEBUG_OFF (`0`) No debug output, default
106
* * self::DEBUG_CLIENT (`1`) Client commands
107
* * self::DEBUG_SERVER (`2`) Client commands and server responses
108
* * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status
109
* * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages
112
public $do_debug = self::DEBUG_OFF;
83
* The function/method to use for debugging output.
84
* Options: 'echo', 'html' or 'error_log'
115
* How to handle debug output.
117
* * `echo` Output plain-text as-is, appropriate for CLI
118
* * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
119
* * `error_log` Output to error log as configured in php.ini
121
* Alternatively, you can provide a callable expecting two params: a message string and the debug level:
123
* $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
125
* @type string|callable
87
127
public $Debugoutput = 'echo';
90
130
* Whether to use VERP.
131
* @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
132
* @link http://www.postfix.org/VERP_README.html Info on VERP
93
135
public $do_verp = false;
96
* The SMTP timeout value for reads, in seconds.
138
* The timeout value for connection, in seconds.
139
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
140
* This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
141
* @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
144
public $Timeout = 300;
102
* The SMTP timelimit value for reads, in seconds.
147
* How long to wait for commands to complete, in seconds.
148
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
105
public $Timelimit = 30;
151
public $Timelimit = 300;
108
154
* The socket for the server connection.
167
//Just echoes whatever was received
228
//Normalize line breaks
229
$str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
230
echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
173
239
* Connect to an SMTP server.
174
* @param string $host SMTP server IP or host name
175
* @param int $port The port number to connect to
176
* @param int $timeout How long to wait for the connection to open
240
* @param string $host SMTP server IP or host name
241
* @param integer $port The port number to connect to
242
* @param integer $timeout How long to wait for the connection to open
177
243
* @param array $options An array of options for stream_context_create()
181
247
public function connect($host, $port = null, $timeout = 30, $options = array())
250
//This is enabled by default since 5.0.0 but some providers disable it
251
//Check this once and cache the result
252
if (is_null($streamok)) {
253
$streamok = function_exists('stream_socket_client');
183
255
// Clear errors to avoid confusion
186
257
// Make sure we are __not__ connected
187
258
if ($this->connected()) {
188
259
// Already connected, generate error
189
$this->error = array('error' => 'Already connected to a server');
260
$this->setError('Already connected to a server');
193
263
if (empty($port)) {
194
264
$port = self::DEFAULT_SMTP_PORT;
197
266
// Connect to the SMTP server
268
"Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true),
269
self::DEBUG_CONNECTION
200
$socket_context = stream_context_create($options);
201
//Suppress errors; connection failures are handled at a higher level
202
$this->smtp_conn = @stream_socket_client(
207
STREAM_CLIENT_CONNECT,
274
$socket_context = stream_context_create($options);
275
//Suppress errors; connection failures are handled at a higher level
276
$this->smtp_conn = @stream_socket_client(
281
STREAM_CLIENT_CONNECT,
285
//Fall back to fsockopen which should work in more places, but is missing some features
287
"Connection: stream_socket_client not available, falling back to fsockopen",
288
self::DEBUG_CONNECTION
290
$this->smtp_conn = fsockopen(
211
298
// Verify we connected properly
212
if (empty($this->smtp_conn)) {
213
$this->error = array(
214
'error' => 'Failed to connect to server',
218
if ($this->do_debug >= 1) {
220
'SMTP -> ERROR: ' . $this->error['error']
221
. ": $errstr ($errno)"
299
if (!is_resource($this->smtp_conn)) {
301
'Failed to connect to server',
306
'SMTP ERROR: ' . $this->error['error']
307
. ": $errstr ($errno)",
312
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
227
313
// SMTP server can take longer to respond, give longer timeout for first read
228
314
// Windows does not have support for this timeout function
229
315
if (substr(PHP_OS, 0, 3) != 'WIN') {
230
316
$max = ini_get('max_execution_time');
231
if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
317
// Don't bother if unlimited
318
if ($max != 0 && $timeout > $max) {
232
319
@set_time_limit($timeout);
234
321
stream_set_timeout($this->smtp_conn, $timeout, 0);
237
323
// Get any announcement
238
324
$announce = $this->get_lines();
240
if ($this->do_debug >= 2) {
241
$this->edebug('SMTP -> FROM SERVER:' . $announce);
325
$this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
248
330
* Initiate a TLS (encrypted) session.
252
334
public function startTLS()
254
if (!$this->sendCommand("STARTTLS", "STARTTLS", 220)) {
336
if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
257
339
// Begin encrypted connection
276
357
* @param string $realm The auth realm for NTLM
277
358
* @param string $workstation The auth workstation for NTLM
279
* @return bool True if successfully authenticated.
360
* @return boolean True if successfully authenticated.
281
362
public function authenticate(
286
367
$workstation = ''
288
if (empty($authtype)) {
369
if (!$this->server_caps) {
370
$this->setError('Authentication is not allowed before HELO/EHLO');
374
if (array_key_exists('EHLO', $this->server_caps)) {
375
// SMTP extensions are available. Let's try to find a proper authentication method
377
if (!array_key_exists('AUTH', $this->server_caps)) {
378
$this->setError('Authentication is not allowed at this stage');
379
// 'at this stage' means that auth may be allowed after the stage changes
380
// e.g. after STARTTLS
384
self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL);
386
'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
390
if (empty($authtype)) {
391
foreach (array('LOGIN', 'CRAM-MD5', 'PLAIN') as $method) {
392
if (in_array($method, $this->server_caps['AUTH'])) {
397
if (empty($authtype)) {
398
$this->setError('No supported authentication methods found');
401
self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL);
404
if (!in_array($authtype, $this->server_caps['AUTH'])) {
405
$this->setError("The requested authentication method \"$authtype\" is not supported by the server");
408
} elseif (empty($authtype)) {
289
409
$authtype = 'LOGIN';
292
411
switch ($authtype) {
294
413
// Start authentication
322
* ntlm_sasl_client.php
323
* Bundled with Permission
325
* How to telnet in windows:
326
* http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
327
* PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
329
require_once 'extras/ntlm_sasl_client.php';
330
$temp = new stdClass();
331
$ntlm_client = new ntlm_sasl_client_class;
332
//Check that functions are available
333
if (!$ntlm_client->Initialize($temp)) {
334
$this->error = array('error' => $temp->error);
335
if ($this->do_debug >= 1) {
337
'You need to enable some modules in your php.ini file: '
338
. $this->error['error']
344
$msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
346
if (!$this->sendCommand(
348
'AUTH NTLM ' . base64_encode($msg1),
355
//Though 0 based, there is a white space after the 3 digit number
357
$challenge = substr($this->last_reply, 3);
358
$challenge = base64_decode($challenge);
359
$ntlm_res = $ntlm_client->NTLMResponse(
360
substr($challenge, 24, 8),
364
$msg3 = $ntlm_client->TypeMsg3(
370
// send encoded username
371
return $this->sendCommand('Username', base64_encode($msg3), 235);
374
440
// Start authentication
375
441
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
476
545
* Implements rfc 821: DATA <CRLF>
477
546
* @param string $msg_data Message data to send
481
550
public function data($msg_data)
552
//This will use the standard timelimit
483
553
if (!$this->sendCommand('DATA', 'DATA', 354)) {
487
557
/* The server is ready to accept data!
488
* according to rfc821 we should not send more than 1000
490
* characters on a single line so we will break the data up
491
* into lines by \r and/or \n then if needed we will break
492
* each of those into smaller lines to fit within the limit.
493
* in addition we will be looking for lines that start with
494
* a period '.' and append and additional period '.' to that
495
* line. NOTE: this does not count towards limit.
558
* According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF)
559
* so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
560
* smaller lines to fit within the limit.
561
* We will also look for lines that start with a '.' and prepend an additional '.'.
562
* NOTE: this does not count towards line-length limit.
498
// Normalize the line breaks before exploding
499
$msg_data = str_replace("\r\n", "\n", $msg_data);
500
$msg_data = str_replace("\r", "\n", $msg_data);
501
$lines = explode("\n", $msg_data);
565
// Normalize line breaks before exploding
566
$lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data));
503
/* We need to find a good way to determine if headers are
504
* in the msg_data or if it is a straight msg body
505
* currently I am assuming rfc822 definitions of msg headers
506
* and if the first field of the first line (':' separated)
507
* does not contain a space then it _should_ be a header
508
* and we can process all lines before a blank "" line as
568
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
569
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will
570
* process all lines before a blank line as headers.
512
573
$field = substr($lines[0], 0, strpos($lines[0], ':'));
513
574
$in_headers = false;
514
if (!empty($field) && !strstr($field, ' ')) {
575
if (!empty($field) && strpos($field, ' ') === false) {
515
576
$in_headers = true;
518
//RFC 2822 section 2.1.1 limit
519
$max_line_length = 998;
521
579
foreach ($lines as $line) {
523
if ($line == '' && $in_headers) {
580
$lines_out = array();
581
if ($in_headers and $line == '') {
524
582
$in_headers = false;
526
// ok we need to break this line up into several smaller lines
527
while (strlen($line) > $max_line_length) {
528
$pos = strrpos(substr($line, 0, $max_line_length), ' ');
530
// Patch to fix DOS attack
584
//Break this line up into several smaller lines if it's too long
585
//Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len),
586
while (isset($line[self::MAX_LINE_LENGTH])) {
587
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
588
//so as to avoid breaking in the middle of a word
589
$pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
590
//Deliberately matches both false and 0
532
$pos = $max_line_length - 1;
592
//No nice break found, add a hard break
593
$pos = self::MAX_LINE_LENGTH - 1;
533
594
$lines_out[] = substr($line, 0, $pos);
534
595
$line = substr($line, $pos);
597
//Break at the found point
536
598
$lines_out[] = substr($line, 0, $pos);
599
//Move along by the amount we dealt with
537
600
$line = substr($line, $pos + 1);
540
/* If processing headers add a LWSP-char to the front of new line
541
* rfc822 on long msg headers
602
//If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
543
603
if ($in_headers) {
544
604
$line = "\t" . $line;
547
607
$lines_out[] = $line;
549
// send the lines to the server
550
while (list(, $line_out) = @each($lines_out)) {
551
if (strlen($line_out) > 0) {
552
if (substr($line_out, 0, 1) == '.') {
553
$line_out = '.' . $line_out;
609
//Send the lines to the server
610
foreach ($lines_out as $line_out) {
611
//RFC2821 section 4.5.2
612
if (!empty($line_out) and $line_out[0] == '.') {
613
$line_out = '.' . $line_out;
556
615
$this->client_send($line_out . self::CRLF);
560
// Message data has been sent, complete the command
561
return $this->sendCommand('DATA END', '.', 250);
619
//Message data has been sent, complete the command
620
//Increase timelimit for end of DATA command
621
$savetimelimit = $this->Timelimit;
622
$this->Timelimit = $this->Timelimit * 2;
623
$result = $this->sendCommand('DATA END', '.', 250);
625
$this->Timelimit = $savetimelimit;
565
630
* Send an SMTP HELO or EHLO command.
566
631
* Used to identify the sending server to the receiving server.
567
632
* This makes sure that client and server are in a known state.
568
* Implements from RFC 821: HELO <SP> <domain> <CRLF>
633
* Implements RFC 821: HELO <SP> <domain> <CRLF>
569
634
* and RFC 2821 EHLO.
570
635
* @param string $host The host name or IP to connect to
574
639
public function hello($host = '')
576
// Try extended hello first (RFC 2821)
577
if (!$this->sendHello('EHLO', $host)) {
578
if (!$this->sendHello('HELO', $host)) {
641
//Try extended hello first (RFC 2821)
642
return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host));
588
647
* Low-level implementation used by hello()
590
649
* @param string $hello The HELO string
591
* @param string $host The hostname to say we are
650
* @param string $host The hostname to say we are
592
651
* @access protected
595
654
protected function sendHello($hello, $host)
597
656
$noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
598
657
$this->helo_rply = $this->last_reply;
659
$this->parseHelloFields($hello);
661
$this->server_caps = null;
667
* Parse a reply to HELO/EHLO command to discover server extensions.
668
* In case of HELO, the only parameter that can be discovered is a server name.
670
* @param string $type - 'HELO' or 'EHLO'
672
protected function parseHelloFields($type)
674
$this->server_caps = array();
675
$lines = explode("\n", $this->last_reply);
676
foreach ($lines as $n => $s) {
677
$s = trim(substr($s, 4));
681
$fields = explode(' ', $s);
682
if (!empty($fields)) {
685
$fields = $fields[0];
687
$name = array_shift($fields);
688
if ($name == 'SIZE') {
689
$fields = ($fields) ? $fields[0] : 0;
692
$this->server_caps[$name] = ($fields ? $fields : true);
603
698
* Send an SMTP MAIL command.
604
699
* Starts a mail transaction from the email address specified in
605
700
* $from. Returns true if successful or false otherwise. If True
624
719
* Send an SMTP QUIT command.
625
720
* Closes the socket if there is no error or the $close_on_error argument is true.
626
721
* Implements from rfc 821: QUIT <CRLF>
627
* @param bool $close_on_error Should the connection close if an error occurs?
722
* @param boolean $close_on_error Should the connection close if an error occurs?
631
726
public function quit($close_on_error = true)
633
728
$noerror = $this->sendCommand('QUIT', 'QUIT', 221);
634
$e = $this->error; //Save any error
729
$err = $this->error; //Save any error
635
730
if ($noerror or $close_on_error) {
637
$this->error = $e; //Restore any error from the quit command
732
$this->error = $err; //Restore any error from the quit command
643
738
* Send an SMTP RCPT command.
644
* Sets the TO argument to $to.
739
* Sets the TO argument to $toaddr.
645
740
* Returns true if the recipient was accepted false if it was rejected.
646
741
* Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
647
* @param string $to The address the message is being sent to
742
* @param string $toaddr The address the message is being sent to
651
public function recipient($to)
746
public function recipient($toaddr)
653
748
return $this->sendCommand(
655
'RCPT TO:<' . $to . '>',
750
'RCPT TO:<' . $toaddr . '>',
673
768
* Send a command to an SMTP server and check its return code.
674
769
* @param string $command The command name - not sent to the server
675
770
* @param string $commandstring The actual command to send
676
* @param int|array $expect One or more expected integer success codes
771
* @param integer|array $expect One or more expected integer success codes
677
772
* @access protected
678
* @return bool True on success.
773
* @return boolean True on success.
680
775
protected function sendCommand($command, $commandstring, $expect)
682
777
if (!$this->connected()) {
683
$this->error = array(
684
"error" => "Called $command without being connected"
778
$this->setError("Called $command without being connected");
688
781
$this->client_send($commandstring . self::CRLF);
690
$reply = $this->get_lines();
691
$code = substr($reply, 0, 3);
693
if ($this->do_debug >= 2) {
694
$this->edebug('SMTP -> FROM SERVER:' . $reply);
783
$this->last_reply = $this->get_lines();
784
// Fetch SMTP code and possible error code explanation
786
if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) {
788
$code_ex = (count($matches) > 2 ? $matches[2] : null);
789
// Cut off error code from each response line
790
$detail = preg_replace(
791
"/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m",
796
// Fall back to simple parsing if regex fails
797
$code = substr($this->last_reply, 0, 3);
799
$detail = substr($this->last_reply, 4);
802
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
697
804
if (!in_array($code, (array)$expect)) {
698
$this->last_reply = null;
699
$this->error = array(
700
"error" => "$command command failed",
701
"smtp_code" => $code,
702
"detail" => substr($reply, 4)
704
if ($this->do_debug >= 1) {
706
'SMTP -> ERROR: ' . $this->error['error'] . ': ' . $reply
806
"$command command failed",
812
'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply,
712
$this->last_reply = $reply;
725
830
* Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
726
831
* @param string $from The address the message is from
730
835
public function sendAndMail($from)
732
return $this->sendCommand("SAML", "SAML FROM:$from", 250);
837
return $this->sendCommand('SAML', "SAML FROM:$from", 250);
736
841
* Send an SMTP VRFY command.
737
842
* @param string $name The name to verify
741
846
public function verify($name)
743
return $this->sendCommand("VRFY", "VRFY $name", array(250, 251));
848
return $this->sendCommand('VRFY', "VRFY $name", array(250, 251));
747
852
* Send an SMTP NOOP command.
748
853
* Used to keep keep-alives alive, doesn't actually do anything
752
857
public function noop()
754
return $this->sendCommand("NOOP", "NOOP", 250);
859
return $this->sendCommand('NOOP', 'NOOP', 250);
758
863
* Send an SMTP TURN command.
759
864
* This is an optional command for SMTP that this class does not support.
760
* This method is here to make the RFC821 Definition
761
* complete for this class and __may__ be implemented in future
865
* This method is here to make the RFC821 Definition complete for this class
866
* and _may_ be implemented in future
762
867
* Implements from rfc 821: TURN <CRLF>
766
871
public function turn()
768
$this->error = array(
769
'error' => 'The SMTP TURN command is not implemented'
771
if ($this->do_debug >= 1) {
772
$this->edebug('SMTP -> NOTICE: ' . $this->error['error']);
873
$this->setError('The SMTP TURN command is not implemented');
874
$this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT);
901
* Get SMTP extensions available on the server
905
public function getServerExtList()
907
return $this->server_caps;
911
* A multipurpose method
912
* The method works in three ways, dependent on argument value and current state
913
* 1. HELO/EHLO was not sent - returns null and set up $this->error
915
* $name = 'HELO': returns server name
916
* $name = 'EHLO': returns boolean false
917
* $name = any string: returns null and set up $this->error
919
* $name = 'HELO'|'EHLO': returns server name
920
* $name = any string: if extension $name exists, returns boolean True
921
* or its options. Otherwise returns boolean False
922
* In other words, one can use this method to detect 3 conditions:
923
* - null returned: handshake was not or we don't know about ext (refer to $this->error)
924
* - false returned: the requested feature exactly not exists
925
* - positive value returned: the requested feature exists
926
* @param string $name Name of SMTP extension or 'HELO'|'EHLO'
929
public function getServerExt($name)
931
if (!$this->server_caps) {
932
$this->setError('No HELO/EHLO was sent');
936
// the tight logic knot ;)
937
if (!array_key_exists($name, $this->server_caps)) {
938
if ($name == 'HELO') {
939
return $this->server_caps['EHLO'];
941
if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) {
944
$this->setError('HELO handshake was used. Client knows nothing about server extensions');
948
return $this->server_caps[$name];
802
952
* Get the last reply from the server.
820
970
protected function get_lines()
972
// If the connection is bad, give up straight away
973
if (!is_resource($this->smtp_conn)) {
824
// If the connection is bad, give up now
825
if (!is_resource($this->smtp_conn)) {
828
978
stream_set_timeout($this->smtp_conn, $this->Timeout);
829
979
if ($this->Timelimit > 0) {
830
980
$endtime = time() + $this->Timelimit;
832
982
while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
833
983
$str = @fgets($this->smtp_conn, 515);
834
if ($this->do_debug >= 4) {
835
$this->edebug("SMTP -> get_lines(): \$data was \"$data\"");
836
$this->edebug("SMTP -> get_lines(): \$str is \"$str\"");
984
$this->edebug("SMTP -> get_lines(): \$data was \"$data\"", self::DEBUG_LOWLEVEL);
985
$this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL);
839
if ($this->do_debug >= 4) {
840
$this->edebug("SMTP -> get_lines(): \$data is \"$data\"");
842
// if 4th character is a space, we are done reading, break the loop
843
if (substr($str, 3, 1) == ' ') {
987
$this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
988
// If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen
989
if ((isset($str[3]) and $str[3] == ' ')) {
846
992
// Timed-out? Log and break
847
993
$info = stream_get_meta_data($this->smtp_conn);
848
994
if ($info['timed_out']) {
849
if ($this->do_debug >= 4) {
851
'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)'
996
'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
856
1001
// Now check if reads took too long
858
if (time() > $endtime) {
859
if ($this->do_debug >= 4) {
861
'SMTP -> get_lines(): timelimit reached ('
862
. $this->Timelimit . ' sec)'
1002
if ($endtime and time() > $endtime) {
1004
'SMTP -> get_lines(): timelimit reached ('.
1005
$this->Timelimit . ' sec)',
1006
self::DEBUG_LOWLEVEL