source: trunk/include/class.smtp.php @ 24951

Last change on this file since 24951 was 24951, checked in by plg, 11 years ago

feature 2965: replace custom mail functions by PHPMailer (version 5.2.7).
Based on patch by msakik.

function pwg_send_mail no longer used (all is done in pwg_mail)

new param $confsmtp_secure

work still in progress, some obsolete code must be removed

File size: 27.9 KB
Line 
1<?php
2/**
3 * PHPMailer RFC821 SMTP email transport class.
4 * Version 5.2.7
5 * PHP version 5.0.0
6 * @category  PHP
7 * @package   PHPMailer
8 * @link      https://github.com/PHPMailer/PHPMailer/
9 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
10 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
11 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
12 * @copyright 2013 Marcus Bointon
13 * @copyright 2004 - 2008 Andy Prevost
14 * @copyright 2010 - 2012 Jim Jagielski
15 * @license   http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
16 */
17
18/**
19 * PHPMailer RFC821 SMTP email transport class.
20 *
21 * Implements RFC 821 SMTP commands
22 * and provides some utility methods for sending mail to an SMTP server.
23 *
24 * PHP Version 5.0.0
25 *
26 * @category PHP
27 * @package  PHPMailer
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)
32 */
33
34class SMTP
35{
36    /**
37     * The PHPMailer SMTP Version number.
38     */
39    const VERSION = '5.2.7';
40
41    /**
42     * SMTP line break constant.
43     */
44    const CRLF = "\r\n";
45
46    /**
47     * The SMTP port to use if one is not specified.
48     */
49    const DEFAULT_SMTP_PORT = 25;
50
51    /**
52     * The PHPMailer SMTP Version number.
53     * @type string
54     * @deprecated This should be a constant
55     * @see SMTP::VERSION
56     */
57    public $Version = '5.2.7';
58
59    /**
60     * SMTP server port number.
61     * @type int
62     * @deprecated This is only ever ued as default value, so should be a constant
63     * @see SMTP::DEFAULT_SMTP_PORT
64     */
65    public $SMTP_PORT = 25;
66
67    /**
68     * SMTP reply line ending
69     * @type string
70     * @deprecated Use the class constant instead
71     * @see SMTP::CRLF
72     */
73    public $CRLF = "\r\n";
74
75    /**
76     * Debug output level.
77     * Options: 0 for no output, 1 for commands, 2 for data and commands
78     * @type int
79     */
80    public $do_debug = 0;
81
82    /**
83     * The function/method to use for debugging output.
84     * Options: 'echo', 'html' or 'error_log'
85     * @type string
86     */
87    public $Debugoutput = 'echo';
88
89    /**
90     * Whether to use VERP.
91     * @type bool
92     */
93    public $do_verp = false;
94
95    /**
96     * The SMTP timeout value for reads, in seconds.
97     * @type int
98     */
99    public $Timeout = 15;
100
101    /**
102     * The SMTP timelimit value for reads, in seconds.
103     * @type int
104     */
105    public $Timelimit = 30;
106
107    /**
108     * The socket for the server connection.
109     * @type resource
110     */
111    protected $smtp_conn;
112
113    /**
114     * Error message, if any, for the last call.
115     * @type string
116     */
117    protected $error = '';
118
119    /**
120     * The reply the server sent to us for HELO.
121     * @type string
122     */
123    protected $helo_rply = '';
124
125    /**
126     * The most recent reply received from the server.
127     * @type string
128     */
129    protected $last_reply = '';
130
131    /**
132     * Constructor.
133     * @access public
134     */
135    public function __construct()
136    {
137        $this->smtp_conn = 0;
138        $this->error = null;
139        $this->helo_rply = null;
140
141        $this->do_debug = 0;
142    }
143
144    /**
145     * Output debugging info via a user-selected method.
146     * @param string $str Debug string to output
147     * @return void
148     */
149    protected function edebug($str)
150    {
151        switch ($this->Debugoutput) {
152            case 'error_log':
153                //Don't output, just log
154                error_log($str);
155                break;
156            case 'html':
157                //Cleans up output a bit for a better looking, HTML-safe output
158                echo htmlentities(
159                    preg_replace('/[\r\n]+/', '', $str),
160                    ENT_QUOTES,
161                    'UTF-8'
162                )
163                . "<br>\n";
164                break;
165            case 'echo':
166            default:
167                //Just echoes whatever was received
168                echo $str;
169        }
170    }
171
172    /**
173     * 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
177     * @param array $options An array of options for stream_context_create()
178     * @access public
179     * @return bool
180     */
181    public function connect($host, $port = null, $timeout = 30, $options = array())
182    {
183        // Clear errors to avoid confusion
184        $this->error = null;
185
186        // Make sure we are __not__ connected
187        if ($this->connected()) {
188            // Already connected, generate error
189            $this->error = array('error' => 'Already connected to a server');
190            return false;
191        }
192
193        if (empty($port)) {
194            $port = self::DEFAULT_SMTP_PORT;
195        }
196
197        // Connect to the SMTP server
198        $errno = 0;
199        $errstr = '';
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(
203            $host . ":" . $port,
204            $errno,
205            $errstr,
206            $timeout,
207            STREAM_CLIENT_CONNECT,
208            $socket_context
209        );
210
211        // Verify we connected properly
212        if (empty($this->smtp_conn)) {
213            $this->error = array(
214                'error' => 'Failed to connect to server',
215                'errno' => $errno,
216                'errstr' => $errstr
217            );
218            if ($this->do_debug >= 1) {
219                $this->edebug(
220                    'SMTP -> ERROR: ' . $this->error['error']
221                    . ": $errstr ($errno)"
222                );
223            }
224            return false;
225        }
226
227        // SMTP server can take longer to respond, give longer timeout for first read
228        // Windows does not have support for this timeout function
229        if (substr(PHP_OS, 0, 3) != 'WIN') {
230            $max = ini_get('max_execution_time');
231            if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
232                @set_time_limit($timeout);
233            }
234            stream_set_timeout($this->smtp_conn, $timeout, 0);
235        }
236
237        // Get any announcement
238        $announce = $this->get_lines();
239
240        if ($this->do_debug >= 2) {
241            $this->edebug('SMTP -> FROM SERVER:' . $announce);
242        }
243
244        return true;
245    }
246
247    /**
248     * Initiate a TLS (encrypted) session.
249     * @access public
250     * @return bool
251     */
252    public function startTLS()
253    {
254        if (!$this->sendCommand("STARTTLS", "STARTTLS", 220)) {
255            return false;
256        }
257        // Begin encrypted connection
258        if (!stream_socket_enable_crypto(
259            $this->smtp_conn,
260            true,
261            STREAM_CRYPTO_METHOD_TLS_CLIENT
262        )
263        ) {
264            return false;
265        }
266        return true;
267    }
268
269    /**
270     * Perform SMTP authentication.
271     * Must be run after hello().
272     * @see hello()
273     * @param string $username    The user name
274     * @param string $password    The password
275     * @param string $authtype    The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)
276     * @param string $realm       The auth realm for NTLM
277     * @param string $workstation The auth workstation for NTLM
278     * @access public
279     * @return bool True if successfully authenticated.
280     */
281    public function authenticate(
282        $username,
283        $password,
284        $authtype = 'LOGIN',
285        $realm = '',
286        $workstation = ''
287    ) {
288        if (empty($authtype)) {
289            $authtype = 'LOGIN';
290        }
291
292        switch ($authtype) {
293            case 'PLAIN':
294                // Start authentication
295                if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
296                    return false;
297                }
298                // Send encoded username and password
299                if (!$this->sendCommand(
300                    'User & Password',
301                    base64_encode("\0" . $username . "\0" . $password),
302                    235
303                )
304                ) {
305                    return false;
306                }
307                break;
308            case 'LOGIN':
309                // Start authentication
310                if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
311                    return false;
312                }
313                if (!$this->sendCommand("Username", base64_encode($username), 334)) {
314                    return false;
315                }
316                if (!$this->sendCommand("Password", base64_encode($password), 235)) {
317                    return false;
318                }
319                break;
320            case 'NTLM':
321                /*
322                 * ntlm_sasl_client.php
323                 * Bundled with Permission
324                 *
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
328                 */
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) {
336                        $this->edebug(
337                            'You need to enable some modules in your php.ini file: '
338                            . $this->error['error']
339                        );
340                    }
341                    return false;
342                }
343                //msg1
344                $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
345
346                if (!$this->sendCommand(
347                    'AUTH NTLM',
348                    'AUTH NTLM ' . base64_encode($msg1),
349                    334
350                )
351                ) {
352                    return false;
353                }
354
355                //Though 0 based, there is a white space after the 3 digit number
356                //msg2
357                $challenge = substr($this->last_reply, 3);
358                $challenge = base64_decode($challenge);
359                $ntlm_res = $ntlm_client->NTLMResponse(
360                    substr($challenge, 24, 8),
361                    $password
362                );
363                //msg3
364                $msg3 = $ntlm_client->TypeMsg3(
365                    $ntlm_res,
366                    $username,
367                    $realm,
368                    $workstation
369                );
370                // send encoded username
371                return $this->sendCommand('Username', base64_encode($msg3), 235);
372                break;
373            case 'CRAM-MD5':
374                // Start authentication
375                if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
376                    return false;
377                }
378                // Get the challenge
379                $challenge = base64_decode(substr($this->last_reply, 4));
380
381                // Build the response
382                $response = $username . ' ' . $this->hmac($challenge, $password);
383
384                // send encoded credentials
385                return $this->sendCommand('Username', base64_encode($response), 235);
386                break;
387        }
388        return true;
389    }
390
391    /**
392     * Calculate an MD5 HMAC hash.
393     * Works like hash_hmac('md5', $data, $key)
394     * in case that function is not available
395     * @param string $data The data to hash
396     * @param string $key  The key to hash with
397     * @access protected
398     * @return string
399     */
400    protected function hmac($data, $key)
401    {
402        if (function_exists('hash_hmac')) {
403            return hash_hmac('md5', $data, $key);
404        }
405
406        // The following borrowed from
407        // http://php.net/manual/en/function.mhash.php#27225
408
409        // RFC 2104 HMAC implementation for php.
410        // Creates an md5 HMAC.
411        // Eliminates the need to install mhash to compute a HMAC
412        // Hacked by Lance Rushing
413
414        $b = 64; // byte length for md5
415        if (strlen($key) > $b) {
416            $key = pack('H*', md5($key));
417        }
418        $key = str_pad($key, $b, chr(0x00));
419        $ipad = str_pad('', $b, chr(0x36));
420        $opad = str_pad('', $b, chr(0x5c));
421        $k_ipad = $key ^ $ipad;
422        $k_opad = $key ^ $opad;
423
424        return md5($k_opad . pack('H*', md5($k_ipad . $data)));
425    }
426
427    /**
428     * Check connection state.
429     * @access public
430     * @return bool True if connected.
431     */
432    public function connected()
433    {
434        if (!empty($this->smtp_conn)) {
435            $sock_status = stream_get_meta_data($this->smtp_conn);
436            if ($sock_status['eof']) {
437                // the socket is valid but we are not connected
438                if ($this->do_debug >= 1) {
439                    $this->edebug(
440                        'SMTP -> NOTICE: EOF caught while checking if connected'
441                    );
442                }
443                $this->close();
444                return false;
445            }
446            return true; // everything looks good
447        }
448        return false;
449    }
450
451    /**
452     * Close the socket and clean up the state of the class.
453     * Don't use this function without first trying to use QUIT.
454     * @see quit()
455     * @access public
456     * @return void
457     */
458    public function close()
459    {
460        $this->error = null; // so there is no confusion
461        $this->helo_rply = null;
462        if (!empty($this->smtp_conn)) {
463            // close the connection and cleanup
464            fclose($this->smtp_conn);
465            $this->smtp_conn = 0;
466        }
467    }
468
469    /**
470     * Send an SMTP DATA command.
471     * Issues a data command and sends the msg_data to the server,
472     * finializing the mail transaction. $msg_data is the message
473     * that is to be send with the headers. Each header needs to be
474     * on a single line followed by a <CRLF> with the message headers
475     * and the message body being separated by and additional <CRLF>.
476     * Implements rfc 821: DATA <CRLF>
477     * @param string $msg_data Message data to send
478     * @access public
479     * @return bool
480     */
481    public function data($msg_data)
482    {
483        if (!$this->sendCommand('DATA', 'DATA', 354)) {
484            return false;
485        }
486
487        /* The server is ready to accept data!
488         * according to rfc821 we should not send more than 1000
489         * including the CRLF
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.
496         */
497
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);
502
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
509         * headers.
510         */
511
512        $field = substr($lines[0], 0, strpos($lines[0], ':'));
513        $in_headers = false;
514        if (!empty($field) && !strstr($field, ' ')) {
515            $in_headers = true;
516        }
517
518        //RFC 2822 section 2.1.1 limit
519        $max_line_length = 998;
520
521        foreach ($lines as $line) {
522            $lines_out = null;
523            if ($line == '' && $in_headers) {
524                $in_headers = false;
525            }
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), ' ');
529
530                // Patch to fix DOS attack
531                if (!$pos) {
532                    $pos = $max_line_length - 1;
533                    $lines_out[] = substr($line, 0, $pos);
534                    $line = substr($line, $pos);
535                } else {
536                    $lines_out[] = substr($line, 0, $pos);
537                    $line = substr($line, $pos + 1);
538                }
539
540                /* If processing headers add a LWSP-char to the front of new line
541                 * rfc822 on long msg headers
542                 */
543                if ($in_headers) {
544                    $line = "\t" . $line;
545                }
546            }
547            $lines_out[] = $line;
548
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;
554                    }
555                }
556                $this->client_send($line_out . self::CRLF);
557            }
558        }
559
560        // Message data has been sent, complete the command
561        return $this->sendCommand('DATA END', '.', 250);
562    }
563
564    /**
565     * Send an SMTP HELO or EHLO command.
566     * Used to identify the sending server to the receiving server.
567     * This makes sure that client and server are in a known state.
568     * Implements from RFC 821: HELO <SP> <domain> <CRLF>
569     * and RFC 2821 EHLO.
570     * @param string $host The host name or IP to connect to
571     * @access public
572     * @return bool
573     */
574    public function hello($host = '')
575    {
576        // Try extended hello first (RFC 2821)
577        if (!$this->sendHello('EHLO', $host)) {
578            if (!$this->sendHello('HELO', $host)) {
579                return false;
580            }
581        }
582
583        return true;
584    }
585
586    /**
587     * Send an SMTP HELO or EHLO command.
588     * Low-level implementation used by hello()
589     * @see hello()
590     * @param string $hello The HELO string
591     * @param string $host  The hostname to say we are
592     * @access protected
593     * @return bool
594     */
595    protected function sendHello($hello, $host)
596    {
597        $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
598        $this->helo_rply = $this->last_reply;
599        return $noerror;
600    }
601
602    /**
603     * Send an SMTP MAIL command.
604     * Starts a mail transaction from the email address specified in
605     * $from. Returns true if successful or false otherwise. If True
606     * the mail transaction is started and then one or more recipient
607     * commands may be called followed by a data command.
608     * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
609     * @param string $from Source address of this message
610     * @access public
611     * @return bool
612     */
613    public function mail($from)
614    {
615        $useVerp = ($this->do_verp ? ' XVERP' : '');
616        return $this->sendCommand(
617            'MAIL FROM',
618            'MAIL FROM:<' . $from . '>' . $useVerp,
619            250
620        );
621    }
622
623    /**
624     * Send an SMTP QUIT command.
625     * Closes the socket if there is no error or the $close_on_error argument is true.
626     * Implements from rfc 821: QUIT <CRLF>
627     * @param bool $close_on_error Should the connection close if an error occurs?
628     * @access public
629     * @return bool
630     */
631    public function quit($close_on_error = true)
632    {
633        $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
634        $e = $this->error; //Save any error
635        if ($noerror or $close_on_error) {
636            $this->close();
637            $this->error = $e; //Restore any error from the quit command
638        }
639        return $noerror;
640    }
641
642    /**
643     * Send an SMTP RCPT command.
644     * Sets the TO argument to $to.
645     * Returns true if the recipient was accepted false if it was rejected.
646     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
647     * @param string $to The address the message is being sent to
648     * @access public
649     * @return bool
650     */
651    public function recipient($to)
652    {
653        return $this->sendCommand(
654            'RCPT TO ',
655            'RCPT TO:<' . $to . '>',
656            array(250, 251)
657        );
658    }
659
660    /**
661     * Send an SMTP RSET command.
662     * Abort any transaction that is currently in progress.
663     * Implements rfc 821: RSET <CRLF>
664     * @access public
665     * @return bool True on success.
666     */
667    public function reset()
668    {
669        return $this->sendCommand('RSET', 'RSET', 250);
670    }
671
672    /**
673     * Send a command to an SMTP server and check its return code.
674     * @param string $command       The command name - not sent to the server
675     * @param string $commandstring The actual command to send
676     * @param int|array $expect     One or more expected integer success codes
677     * @access protected
678     * @return bool True on success.
679     */
680    protected function sendCommand($command, $commandstring, $expect)
681    {
682        if (!$this->connected()) {
683            $this->error = array(
684                "error" => "Called $command without being connected"
685            );
686            return false;
687        }
688        $this->client_send($commandstring . self::CRLF);
689
690        $reply = $this->get_lines();
691        $code = substr($reply, 0, 3);
692
693        if ($this->do_debug >= 2) {
694            $this->edebug('SMTP -> FROM SERVER:' . $reply);
695        }
696
697        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)
703            );
704            if ($this->do_debug >= 1) {
705                $this->edebug(
706                    'SMTP -> ERROR: ' . $this->error['error'] . ': ' . $reply
707                );
708            }
709            return false;
710        }
711
712        $this->last_reply = $reply;
713        $this->error = null;
714        return true;
715    }
716
717    /**
718     * Send an SMTP SAML command.
719     * Starts a mail transaction from the email address specified in $from.
720     * Returns true if successful or false otherwise. If True
721     * the mail transaction is started and then one or more recipient
722     * commands may be called followed by a data command. This command
723     * will send the message to the users terminal if they are logged
724     * in and send them an email.
725     * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
726     * @param string $from The address the message is from
727     * @access public
728     * @return bool
729     */
730    public function sendAndMail($from)
731    {
732        return $this->sendCommand("SAML", "SAML FROM:$from", 250);
733    }
734
735    /**
736     * Send an SMTP VRFY command.
737     * @param string $name The name to verify
738     * @access public
739     * @return bool
740     */
741    public function verify($name)
742    {
743        return $this->sendCommand("VRFY", "VRFY $name", array(250, 251));
744    }
745
746    /**
747     * Send an SMTP NOOP command.
748     * Used to keep keep-alives alive, doesn't actually do anything
749     * @access public
750     * @return bool
751     */
752    public function noop()
753    {
754        return $this->sendCommand("NOOP", "NOOP", 250);
755    }
756
757    /**
758     * Send an SMTP TURN command.
759     * 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
762     * Implements from rfc 821: TURN <CRLF>
763     * @access public
764     * @return bool
765     */
766    public function turn()
767    {
768        $this->error = array(
769            'error' => 'The SMTP TURN command is not implemented'
770        );
771        if ($this->do_debug >= 1) {
772            $this->edebug('SMTP -> NOTICE: ' . $this->error['error']);
773        }
774        return false;
775    }
776
777    /**
778     * Send raw data to the server.
779     * @param string $data The data to send
780     * @access public
781     * @return int|bool The number of bytes sent to the server or FALSE on error
782     */
783    public function client_send($data)
784    {
785        if ($this->do_debug >= 1) {
786            $this->edebug("CLIENT -> SMTP: $data");
787        }
788        return fwrite($this->smtp_conn, $data);
789    }
790
791    /**
792     * Get the latest error.
793     * @access public
794     * @return array
795     */
796    public function getError()
797    {
798        return $this->error;
799    }
800
801    /**
802     * Get the last reply from the server.
803     * @access public
804     * @return string
805     */
806    public function getLastReply()
807    {
808        return $this->last_reply;
809    }
810
811    /**
812     * Read the SMTP server's response.
813     * Either before eof or socket timeout occurs on the operation.
814     * With SMTP we can tell if we have more lines to read if the
815     * 4th character is '-' symbol. If it is a space then we don't
816     * need to read anything else.
817     * @access protected
818     * @return string
819     */
820    protected function get_lines()
821    {
822        $data = '';
823        $endtime = 0;
824        // If the connection is bad, give up now
825        if (!is_resource($this->smtp_conn)) {
826            return $data;
827        }
828        stream_set_timeout($this->smtp_conn, $this->Timeout);
829        if ($this->Timelimit > 0) {
830            $endtime = time() + $this->Timelimit;
831        }
832        while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
833            $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\"");
837            }
838            $data .= $str;
839            if ($this->do_debug >= 4) {
840                $this->edebug("SMTP -> get_lines(): \$data is \"$data\"");
841            }
842            // if 4th character is a space, we are done reading, break the loop
843            if (substr($str, 3, 1) == ' ') {
844                break;
845            }
846            // Timed-out? Log and break
847            $info = stream_get_meta_data($this->smtp_conn);
848            if ($info['timed_out']) {
849                if ($this->do_debug >= 4) {
850                    $this->edebug(
851                        'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)'
852                    );
853                }
854                break;
855            }
856            // Now check if reads took too long
857            if ($endtime) {
858                if (time() > $endtime) {
859                    if ($this->do_debug >= 4) {
860                        $this->edebug(
861                            'SMTP -> get_lines(): timelimit reached ('
862                            . $this->Timelimit . ' sec)'
863                        );
864                    }
865                    break;
866                }
867            }
868        }
869        return $data;
870    }
871
872    /**
873     * Enable or disable VERP address generation.
874     * @param bool $enabled
875     */
876    public function setVerp($enabled = false)
877    {
878        $this->do_verp = $enabled;
879    }
880
881    /**
882     * Get VERP address generation mode.
883     * @return bool
884     */
885    public function getVerp()
886    {
887        return $this->do_verp;
888    }
889
890    /**
891     * Set debug output method.
892     * @param string $method The function/method to use for debugging output.
893     */
894    public function setDebugOutput($method = 'echo')
895    {
896        $this->Debugoutput = $method;
897    }
898
899    /**
900     * Get debug output method.
901     * @return string
902     */
903    public function getDebugOutput()
904    {
905        return $this->Debugoutput;
906    }
907
908    /**
909     * Set debug output level.
910     * @param int $level
911     */
912    public function setDebugLevel($level = 0)
913    {
914        $this->do_debug = $level;
915    }
916
917    /**
918     * Get debug output level.
919     * @return int
920     */
921    public function getDebugLevel()
922    {
923        return $this->do_debug;
924    }
925
926    /**
927     * Set SMTP timeout.
928     * @param int $timeout
929     */
930    public function setTimeout($timeout = 0)
931    {
932        $this->Timeout = $timeout;
933    }
934
935    /**
936     * Get SMTP timeout.
937     * @return int
938     */
939    public function getTimeout()
940    {
941        return $this->Timeout;
942    }
943}
Note: See TracBrowser for help on using the repository browser.