]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/phpmailer/class.smtp.php
Release 6.5.3
[Github/sugarcrm.git] / include / phpmailer / class.smtp.php
1 <?php
2 /*~ class.smtp.php
3 .---------------------------------------------------------------------------.
4 |  Software: PHPMailer - PHP email class                                    |
5 |   Version: 5.2.1                                                          |
6 |      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
7 | ------------------------------------------------------------------------- |
8 |     Admin: Jim Jagielski (project admininistrator)                        |
9 |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
10 |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
11 |          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
12 |   Founder: Brent R. Matzelle (original founder)                           |
13 | Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved.              |
14 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
15 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
16 | ------------------------------------------------------------------------- |
17 |   License: Distributed under the Lesser General Public License (LGPL)     |
18 |            http://www.gnu.org/copyleft/lesser.html                        |
19 | This program is distributed in the hope that it will be useful - WITHOUT  |
20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
21 | FITNESS FOR A PARTICULAR PURPOSE.                                         |
22 '---------------------------------------------------------------------------'
23 */
24
25 /**
26  * PHPMailer - PHP SMTP email transport class
27  * NOTE: Designed for use with PHP version 5 and up
28  * @package PHPMailer
29  * @author Andy Prevost
30  * @author Marcus Bointon
31  * @copyright 2004 - 2008 Andy Prevost
32  * @author Jim Jagielski
33  * @copyright 2010 - 2012 Jim Jagielski
34  * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
35
36  */
37
38 /**
39  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
40  * commands except TURN which will always return a not implemented
41  * error. SMTP also provides some utility methods for sending mail
42  * to an SMTP server.
43  * original author: Chris Ryan
44  */
45
46 class SMTP {
47   /**
48    *  SMTP server port
49    *  @var int
50    */
51   public $SMTP_PORT = 25;
52
53   /**
54    *  SMTP reply line ending
55    *  @var string
56    */
57   public $CRLF = "\r\n";
58
59   /**
60    *  Sets whether debugging is turned on
61    *  @var bool
62    */
63   public $do_debug;       // the level of debug to perform
64
65   /**
66    *  Sets VERP use on/off (default is off)
67    *  @var bool
68    */
69   public $do_verp = false;
70
71   /**
72    * Sets the SMTP PHPMailer Version number
73    * @var string
74    */
75   public $Version         = '5.2.1';
76
77   /////////////////////////////////////////////////
78   // PROPERTIES, PRIVATE AND PROTECTED
79   /////////////////////////////////////////////////
80
81   private $smtp_conn; // the socket to the server
82   private $error;     // error if any on the last call
83   private $helo_rply; // the reply the server sent to us for HELO
84
85   /**
86    * Initialize the class so that the data is in a known state.
87    * @access public
88    * @return void
89    */
90   public function __construct() {
91     $this->smtp_conn = 0;
92     $this->error = null;
93     $this->helo_rply = null;
94
95     $this->do_debug = 0;
96   }
97
98   /////////////////////////////////////////////////
99   // CONNECTION FUNCTIONS
100   /////////////////////////////////////////////////
101
102   /**
103    * Connect to the server specified on the port specified.
104    * If the port is not specified use the default SMTP_PORT.
105    * If tval is specified then a connection will try and be
106    * established with the server for that number of seconds.
107    * If tval is not specified the default is 30 seconds to
108    * try on the connection.
109    *
110    * SMTP CODE SUCCESS: 220
111    * SMTP CODE FAILURE: 421
112    * @access public
113    * @return bool
114    */
115   public function Connect($host, $port = 0, $tval = 30) {
116     // set the error val to null so there is no confusion
117     $this->error = null;
118
119     // make sure we are __not__ connected
120     if($this->connected()) {
121       // already connected, generate error
122       $this->error = array("error" => "Already connected to a server");
123       return false;
124     }
125
126     if(empty($port)) {
127       $port = $this->SMTP_PORT;
128     }
129
130     // connect to the smtp server
131     $this->smtp_conn = @fsockopen($host,    // the host of the server
132                                  $port,    // the port to use
133                                  $errno,   // error number if any
134                                  $errstr,  // error message if any
135                                  $tval);   // give up after ? secs
136     // verify we connected properly
137     if(empty($this->smtp_conn)) {
138       $GLOBALS['log']->fatal("SMTP -> ERROR: Failed to connect to server. Code: $errno Reply: $errstr ");
139       if($this->do_debug >= 1) {
140         echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
141       }
142       return false;
143     }
144
145     // SMTP server can take longer to respond, give longer timeout for first read
146     // Windows does not have support for this timeout function
147     if(substr(PHP_OS, 0, 3) != "WIN")
148      socket_set_timeout($this->smtp_conn, $tval, 0);
149
150     // get any announcement
151     $announce = $this->get_lines();
152
153     if($this->do_debug >= 2) {
154       echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
155     }
156
157     return true;
158   }
159
160   /**
161    * Initiate a TLS communication with the server.
162    *
163    * SMTP CODE 220 Ready to start TLS
164    * SMTP CODE 501 Syntax error (no parameters allowed)
165    * SMTP CODE 454 TLS not available due to temporary reason
166    * @access public
167    * @return bool success
168    */
169   public function StartTLS() {
170     $this->error = null; # to avoid confusion
171
172     if(!$this->connected()) {
173       $this->error = array("error" => "Called StartTLS() without being connected");
174       return false;
175     }
176
177     fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
178
179     $rply = $this->get_lines();
180     $code = substr($rply,0,3);
181
182     if($this->do_debug >= 2) {
183       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
184     }
185
186     if($code != 220) {
187       $this->error =
188          array("error"     => "STARTTLS not accepted from server",
189                "smtp_code" => $code,
190                "smtp_msg"  => substr($rply,4));
191       if($this->do_debug >= 1) {
192         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
193       }
194       return false;
195     }
196
197     // Begin encrypted connection
198     if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
199       return false;
200     }
201
202     return true;
203   }
204
205   /**
206    * Performs SMTP authentication.  Must be run after running the
207    * Hello() method.  Returns true if successfully authenticated.
208    * @access public
209    * @return bool
210    */
211   public function Authenticate($username, $password) {
212     // Start authentication
213     fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
214
215     $rply = $this->get_lines();
216     $code = substr($rply,0,3);
217
218     if($code != 334) {
219       $GLOBALS['log']->fatal("SMTP -> ERROR:AUTH not accepted from server. Code: $code Reply: $rply");
220       if($this->do_debug >= 1) {
221         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
222       }
223       return false;
224     }
225
226     // Send encoded username
227     fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
228
229     $rply = $this->get_lines();
230     $code = substr($rply,0,3);
231
232     if($code != 334) {
233       $GLOBALS['log']->fatal("SMTP -> ERROR:Username not accepted from server. Code: $code Reply: $rply ");
234       if($this->do_debug >= 1) {
235         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
236       }
237       return false;
238     }
239
240     // Send encoded password
241     $password = from_html($password);
242     fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
243
244     $rply = $this->get_lines();
245     $code = substr($rply,0,3);
246
247     if($code != 235) {
248       $GLOBALS['log']->fatal("SMTP -> ERROR:Password not accepted from server. Code: $code Reply: $rply ");
249       if($this->do_debug >= 1) {
250         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
251       }
252       return false;
253     }
254
255     return true;
256   }
257
258   /**
259    * Returns true if connected to a server otherwise false
260    * @access public
261    * @return bool
262    */
263   public function Connected() {
264     if(!empty($this->smtp_conn)) {
265       $sock_status = socket_get_status($this->smtp_conn);
266       if($sock_status["eof"]) {
267         // the socket is valid but we are not connected
268         if($this->do_debug >= 1) {
269             echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
270         }
271         $this->Close();
272         return false;
273       }
274       return true; // everything looks good
275     }
276     return false;
277   }
278
279   /**
280    * Closes the socket and cleans up the state of the class.
281    * It is not considered good to use this function without
282    * first trying to use QUIT.
283    * @access public
284    * @return void
285    */
286   public function Close() {
287     $this->error = null; // so there is no confusion
288     $this->helo_rply = null;
289     if(!empty($this->smtp_conn)) {
290       // close the connection and cleanup
291       fclose($this->smtp_conn);
292       $this->smtp_conn = 0;
293     }
294   }
295
296   /////////////////////////////////////////////////
297   // SMTP COMMANDS
298   /////////////////////////////////////////////////
299
300   /**
301    * Issues a data command and sends the msg_data to the server
302    * finializing the mail transaction. $msg_data is the message
303    * that is to be send with the headers. Each header needs to be
304    * on a single line followed by a <CRLF> with the message headers
305    * and the message body being seperated by and additional <CRLF>.
306    *
307    * Implements rfc 821: DATA <CRLF>
308    *
309    * SMTP CODE INTERMEDIATE: 354
310    *     [data]
311    *     <CRLF>.<CRLF>
312    *     SMTP CODE SUCCESS: 250
313    *     SMTP CODE FAILURE: 552,554,451,452
314    * SMTP CODE FAILURE: 451,554
315    * SMTP CODE ERROR  : 500,501,503,421
316    * @access public
317    * @return bool
318    */
319   public function Data($msg_data) {
320     $this->error = null; // so no confusion is caused
321
322     if(!$this->connected()) {
323       $this->error = array(
324               "error" => "Called Data() without being connected");
325       return false;
326     }
327
328     fputs($this->smtp_conn,"DATA" . $this->CRLF);
329
330     $rply = $this->get_lines();
331     $code = substr($rply,0,3);
332
333     if($this->do_debug >= 2) {
334       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
335     }
336
337     if($code != 354) {
338       $this->error =
339         array("error" => "DATA command not accepted from server",
340               "smtp_code" => $code,
341               "smtp_msg" => substr($rply,4));
342       if($this->do_debug >= 1) {
343         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
344       }
345       return false;
346     }
347
348     /* the server is ready to accept data!
349      * according to rfc 821 we should not send more than 1000
350      * including the CRLF
351      * characters on a single line so we will break the data up
352      * into lines by \r and/or \n then if needed we will break
353      * each of those into smaller lines to fit within the limit.
354      * in addition we will be looking for lines that start with
355      * a period '.' and append and additional period '.' to that
356      * line. NOTE: this does not count towards limit.
357      */
358
359     // normalize the line breaks so we know the explode works
360     $msg_data = str_replace("\r\n","\n",$msg_data);
361     $msg_data = str_replace("\r","\n",$msg_data);
362     $lines = explode("\n",$msg_data);
363
364     /* we need to find a good way to determine is headers are
365      * in the msg_data or if it is a straight msg body
366      * currently I am assuming rfc 822 definitions of msg headers
367      * and if the first field of the first line (':' sperated)
368      * does not contain a space then it _should_ be a header
369      * and we can process all lines before a blank "" line as
370      * headers.
371      */
372
373     $field = substr($lines[0],0,strpos($lines[0],":"));
374     $in_headers = false;
375     if(!empty($field) && !strstr($field," ")) {
376       $in_headers = true;
377     }
378
379     $max_line_length = 998; // used below; set here for ease in change
380
381     while(list(,$line) = @each($lines)) {
382       $lines_out = null;
383       if($line == "" && $in_headers) {
384         $in_headers = false;
385       }
386       // ok we need to break this line up into several smaller lines
387       while(strlen($line) > $max_line_length) {
388         $pos = strrpos(substr($line,0,$max_line_length)," ");
389
390         // Patch to fix DOS attack
391         if(!$pos) {
392           $pos = $max_line_length - 1;
393           $lines_out[] = substr($line,0,$pos);
394           $line = substr($line,$pos);
395         } else {
396           $lines_out[] = substr($line,0,$pos);
397           $line = substr($line,$pos + 1);
398         }
399
400         /* if processing headers add a LWSP-char to the front of new line
401          * rfc 822 on long msg headers
402          */
403         if($in_headers) {
404           $line = "\t" . $line;
405         }
406       }
407       $lines_out[] = $line;
408
409       // send the lines to the server
410       while(list(,$line_out) = @each($lines_out)) {
411         if(strlen($line_out) > 0)
412         {
413           if(substr($line_out, 0, 1) == ".") {
414             $line_out = "." . $line_out;
415           }
416         }
417         fputs($this->smtp_conn,$line_out . $this->CRLF);
418       }
419     }
420
421     // message data has been sent
422     fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
423
424     $rply = $this->get_lines();
425     $code = substr($rply,0,3);
426
427     if($this->do_debug >= 2) {
428       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
429     }
430
431     if($code != 250) {
432       $this->error =
433         array("error" => "DATA not accepted from server",
434               "smtp_code" => $code,
435               "smtp_msg" => substr($rply,4));
436       if($this->do_debug >= 1) {
437         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
438       }
439       return false;
440     }
441     return true;
442   }
443
444   /**
445    * Sends the HELO command to the smtp server.
446    * This makes sure that we and the server are in
447    * the same known state.
448    *
449    * Implements from rfc 821: HELO <SP> <domain> <CRLF>
450    *
451    * SMTP CODE SUCCESS: 250
452    * SMTP CODE ERROR  : 500, 501, 504, 421
453    * @access public
454    * @return bool
455    */
456   public function Hello($host = '') {
457     $this->error = null; // so no confusion is caused
458
459     if(!$this->connected()) {
460       $this->error = array(
461             "error" => "Called Hello() without being connected");
462       return false;
463     }
464
465     // if hostname for HELO was not specified send default
466     if(empty($host)) {
467       // determine appropriate default to send to server
468       $host = "localhost";
469     }
470
471     // Send extended hello first (RFC 2821)
472     if(!$this->SendHello("EHLO", $host)) {
473       if(!$this->SendHello("HELO", $host)) {
474         return false;
475       }
476     }
477
478     return true;
479   }
480
481   /**
482    * Sends a HELO/EHLO command.
483    * @access private
484    * @return bool
485    */
486   private function SendHello($hello, $host) {
487     fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
488
489     $rply = $this->get_lines();
490     $code = substr($rply,0,3);
491
492     if($this->do_debug >= 2) {
493       echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
494     }
495
496     if($code != 250) {
497       $this->error =
498         array("error" => $hello . " not accepted from server",
499               "smtp_code" => $code,
500               "smtp_msg" => substr($rply,4));
501       if($this->do_debug >= 1) {
502         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
503       }
504       return false;
505     }
506
507     $this->helo_rply = $rply;
508
509     return true;
510   }
511
512   /**
513    * Starts a mail transaction from the email address specified in
514    * $from. Returns true if successful or false otherwise. If True
515    * the mail transaction is started and then one or more Recipient
516    * commands may be called followed by a Data command.
517    *
518    * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
519    *
520    * SMTP CODE SUCCESS: 250
521    * SMTP CODE SUCCESS: 552,451,452
522    * SMTP CODE SUCCESS: 500,501,421
523    * @access public
524    * @return bool
525    */
526   public function Mail($from) {
527     $this->error = null; // so no confusion is caused
528
529     if(!$this->connected()) {
530       $this->error = array(
531               "error" => "Called Mail() without being connected");
532       return false;
533     }
534
535     $useVerp = ($this->do_verp ? "XVERP" : "");
536     fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
537
538     $rply = $this->get_lines();
539     $code = substr($rply,0,3);
540
541     if($this->do_debug >= 2) {
542       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
543     }
544
545     if($code != 250) {
546       $this->error =
547         array("error" => "MAIL not accepted from server",
548               "smtp_code" => $code,
549               "smtp_msg" => substr($rply,4));
550       if($this->do_debug >= 1) {
551         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
552       }
553       return false;
554     }
555     return true;
556   }
557
558   /**
559    * Sends the quit command to the server and then closes the socket
560    * if there is no error or the $close_on_error argument is true.
561    *
562    * Implements from rfc 821: QUIT <CRLF>
563    *
564    * SMTP CODE SUCCESS: 221
565    * SMTP CODE ERROR  : 500
566    * @access public
567    * @return bool
568    */
569   public function Quit($close_on_error = true) {
570     $this->error = null; // so there is no confusion
571
572     if(!$this->connected()) {
573       $this->error = array(
574               "error" => "Called Quit() without being connected");
575       return false;
576     }
577
578     // send the quit command to the server
579     fputs($this->smtp_conn,"quit" . $this->CRLF);
580
581     // get any good-bye messages
582     $byemsg = $this->get_lines();
583
584     if($this->do_debug >= 2) {
585       echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
586     }
587
588     $rval = true;
589     $e = null;
590
591     $code = substr($byemsg,0,3);
592     if($code != 221) {
593       // use e as a tmp var cause Close will overwrite $this->error
594       $e = array("error" => "SMTP server rejected quit command",
595                  "smtp_code" => $code,
596                  "smtp_rply" => substr($byemsg,4));
597       $rval = false;
598       if($this->do_debug >= 1) {
599         echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
600       }
601     }
602
603     if(empty($e) || $close_on_error) {
604       $this->Close();
605     }
606
607     return $rval;
608   }
609
610   /**
611    * Sends the command RCPT to the SMTP server with the TO: argument of $to.
612    * Returns true if the recipient was accepted false if it was rejected.
613    *
614    * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
615    *
616    * SMTP CODE SUCCESS: 250,251
617    * SMTP CODE FAILURE: 550,551,552,553,450,451,452
618    * SMTP CODE ERROR  : 500,501,503,421
619    * @access public
620    * @return bool
621    */
622   public function Recipient($to) {
623     $this->error = null; // so no confusion is caused
624
625     if(!$this->connected()) {
626       $this->error = array(
627               "error" => "Called Recipient() without being connected");
628       return false;
629     }
630
631     fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
632
633     $rply = $this->get_lines();
634     $code = substr($rply,0,3);
635
636     if($this->do_debug >= 2) {
637       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
638     }
639
640     if($code != 250 && $code != 251) {
641       $GLOBALS['log']->fatal("SMTP -> ERROR: RCPT not accepted from server. Code: $code Reply: $rply ");
642       if($this->do_debug >= 1) {
643         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
644       }
645       return false;
646     }
647     return true;
648   }
649
650   /**
651    * Sends the RSET command to abort and transaction that is
652    * currently in progress. Returns true if successful false
653    * otherwise.
654    *
655    * Implements rfc 821: RSET <CRLF>
656    *
657    * SMTP CODE SUCCESS: 250
658    * SMTP CODE ERROR  : 500,501,504,421
659    * @access public
660    * @return bool
661    */
662   public function Reset() {
663     $this->error = null; // so no confusion is caused
664
665     if(!$this->connected()) {
666       $this->error = array(
667               "error" => "Called Reset() without being connected");
668       return false;
669     }
670
671     fputs($this->smtp_conn,"RSET" . $this->CRLF);
672
673     $rply = $this->get_lines();
674     $code = substr($rply,0,3);
675
676     if($this->do_debug >= 2) {
677       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
678     }
679
680     if($code != 250) {
681       $this->error =
682         array("error" => "RSET failed",
683               "smtp_code" => $code,
684               "smtp_msg" => substr($rply,4));
685       if($this->do_debug >= 1) {
686         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
687       }
688       return false;
689     }
690
691     return true;
692   }
693
694   /**
695    * Starts a mail transaction from the email address specified in
696    * $from. Returns true if successful or false otherwise. If True
697    * the mail transaction is started and then one or more Recipient
698    * commands may be called followed by a Data command. This command
699    * will send the message to the users terminal if they are logged
700    * in and send them an email.
701    *
702    * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
703    *
704    * SMTP CODE SUCCESS: 250
705    * SMTP CODE SUCCESS: 552,451,452
706    * SMTP CODE SUCCESS: 500,501,502,421
707    * @access public
708    * @return bool
709    */
710   public function SendAndMail($from) {
711     $this->error = null; // so no confusion is caused
712
713     if(!$this->connected()) {
714       $this->error = array(
715           "error" => "Called SendAndMail() without being connected");
716       return false;
717     }
718
719     fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
720
721     $rply = $this->get_lines();
722     $code = substr($rply,0,3);
723
724     if($this->do_debug >= 2) {
725       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
726     }
727
728     if($code != 250) {
729       $this->error =
730         array("error" => "SAML not accepted from server",
731               "smtp_code" => $code,
732               "smtp_msg" => substr($rply,4));
733       if($this->do_debug >= 1) {
734         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
735       }
736       return false;
737     }
738     return true;
739   }
740
741   /**
742    * This is an optional command for SMTP that this class does not
743    * support. This method is here to make the RFC821 Definition
744    * complete for this class and __may__ be implimented in the future
745    *
746    * Implements from rfc 821: TURN <CRLF>
747    *
748    * SMTP CODE SUCCESS: 250
749    * SMTP CODE FAILURE: 502
750    * SMTP CODE ERROR  : 500, 503
751    * @access public
752    * @return bool
753    */
754   public function Turn() {
755     $this->error = array("error" => "This method, TURN, of the SMTP ".
756                                     "is not implemented");
757     if($this->do_debug >= 1) {
758       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
759     }
760     return false;
761   }
762
763   /**
764   * Get the current error
765   * @access public
766   * @return array
767   */
768   public function getError() {
769     return $this->error;
770   }
771
772   /////////////////////////////////////////////////
773   // INTERNAL FUNCTIONS
774   /////////////////////////////////////////////////
775
776   /**
777    * Read in as many lines as possible
778    * either before eof or socket timeout occurs on the operation.
779    * With SMTP we can tell if we have more lines to read if the
780    * 4th character is '-' symbol. If it is a space then we don't
781    * need to read anything else.
782    * @access private
783    * @return string
784    */
785   private function get_lines() {
786     $data = "";
787     while(!feof($this->smtp_conn)) {
788       $str = @fgets($this->smtp_conn,515);
789       if($this->do_debug >= 4) {
790         echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
791         echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
792       }
793       $data .= $str;
794       if($this->do_debug >= 4) {
795         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
796       }
797       // if 4th character is a space, we are done reading, break the loop
798       if(substr($str,3,1) == " ") { break; }
799     }
800     return $data;
801   }
802
803 }
804
805 ?>