renamed lib-local.php -> lib-lfdb.php because it really loads the "legendary"
[core.git] / inc / main / third_party / php_mailer / class.smtp.php
1 <?php
2 /*~ class.smtp.php
3 .---------------------------------------------------------------------------.
4 |  Software: PHPMailer - PHP email class                                    |
5 |   Version: 2.3                                                            |
6 |   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
7 |      Info: http://phpmailer.sourceforge.net                               |
8 |   Support: http://sourceforge.net/projects/phpmailer/                     |
9 | ------------------------------------------------------------------------- |
10 |    Author: Andy Prevost (project admininistrator)                         |
11 |    Author: Brent R. Matzelle (original founder)                           |
12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved.               |
13 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
14 | ------------------------------------------------------------------------- |
15 |   License: Distributed under the Lesser General Public License (LGPL)     |
16 |            http://www.gnu.org/copyleft/lesser.html                        |
17 | This program is distributed in the hope that it will be useful - WITHOUT  |
18 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
19 | FITNESS FOR A PARTICULAR PURPOSE.                                         |
20 | ------------------------------------------------------------------------- |
21 | We offer a number of paid services (www.codeworxtech.com):                |
22 | - Web Hosting on highly optimized fast and secure servers                 |
23 | - Technology Consulting                                                   |
24 | - Oursourcing (highly qualified programmers and graphic designers)        |
25 '---------------------------------------------------------------------------'
26
27 /**
28  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
29  * commands except TURN which will always return a not implemented
30  * error. SMTP also provides some utility methods for sending mail
31  * to an SMTP server.
32  * @package PHPMailer
33  * @author Chris Ryan
34  */
35
36 class SMTP {
37   /**
38    *  SMTP server port
39    *  @var int
40    */
41   public $SMTP_PORT = 25;
42
43   /**
44    *  SMTP reply line ending
45    *  @var string
46    */
47   public $CRLF = "\r\n";
48
49   /**
50    *  Sets whether debugging is turned on
51    *  @var bool
52    */
53   public $do_debug;       // the level of debug to perform
54
55   /**
56    *  Sets VERP use on/off (default is off)
57    *  @var bool
58    */
59   public $do_verp = false;
60
61   /**#@+
62    * @access private
63    */
64   private $smtp_conn;      // the socket to the server
65   private $error;          // error if any on the last call
66   private $helo_rply;      // the reply the server sent to us for HELO
67   /**#@-*/
68
69   /**
70    * Initialize the class so that the data is in a known state.
71    * @access public
72    * @return void
73    */
74   public function __construct() {
75     $this->smtp_conn = 0;
76     $this->error = null;
77     $this->helo_rply = null;
78
79     $this->do_debug = 0;
80   }
81
82   /*************************************************************
83    *                    CONNECTION FUNCTIONS                  *
84    ***********************************************************/
85
86   /**
87    * Connect to the server specified on the port specified.
88    * If the port is not specified use the default SMTP_PORT.
89    * If tval is specified then a connection will try and be
90    * established with the server for that number of seconds.
91    * If tval is not specified the default is 30 seconds to
92    * try on the connection.
93    *
94    * SMTP CODE SUCCESS: 220
95    * SMTP CODE FAILURE: 421
96    * @access public
97    * @return bool
98    */
99   public function Connect($host,$port=0,$tval=30) {
100     /* set the error val to null so there is no confusion */
101     $this->error = null;
102
103     /* make sure we are __not__ connected */
104     if($this->connected()) {
105       /* ok we are connected! what should we do?
106        * for now we will just give an error saying we
107        * are already connected
108        */
109       $this->error = array("error" => "Already connected to a server");
110       return false;
111     }
112
113     if(empty($port)) {
114       $port = $this->SMTP_PORT;
115     }
116
117     /* connect to the smtp server */
118     $this->smtp_conn = fsockopen($host,    // the host of the server
119                                  $port,    // the port to use
120                                  $errno,   // error number if any
121                                  $errstr,  // error message if any
122                                  $tval);   // give up after ? secs
123     /* verify we connected properly */
124     if(empty($this->smtp_conn)) {
125       $this->error = array("error" => "Failed to connect to server",
126                            "errno" => $errno,
127                            "errstr" => $errstr);
128       if($this->do_debug >= 1) {
129         echo "SMTP -> ERROR: " . $this->error["error"] .
130                  ": $errstr ($errno)" . $this->CRLF;
131       }
132       return false;
133     }
134
135     /* sometimes the SMTP server takes a little longer to respond
136      * so we will give it a longer timeout for the first read
137      * - Windows still does not have support for this timeout function
138      */
139     if(substr(PHP_OS, 0, 3) != "WIN")
140      socket_set_timeout($this->smtp_conn, $tval, 0);
141
142     /* get any announcement stuff */
143     $announce = $this->get_lines();
144
145     /* set the timeout  of any socket functions at 1/10 of a second */
146     //if(function_exists("socket_set_timeout"))
147     //   socket_set_timeout($this->smtp_conn, 0, 100000);
148
149     if($this->do_debug >= 2) {
150       echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
151     }
152
153     return true;
154   }
155
156   /**
157    * Initiate a TSL communication with the server.
158    *
159    * SMTP CODE 220 Ready to start TLS
160    * SMTP CODE 501 Syntax error (no parameters allowed)
161    * SMTP CODE 454 TLS not available due to temporary reason
162    * @access public
163    * @return bool success
164    */
165   public function StartTLS() {
166     $this->error = null; # to avoid confusion
167
168     if(!$this->connected()) {
169       $this->error = array("error" => "Called StartTLS() without being connected");
170       return false;
171     }
172
173     fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
174
175     $rply = $this->get_lines();
176     $code = substr($rply,0,3);
177
178     if($this->do_debug >= 2) {
179       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
180     }
181
182     if($code != 220) {
183       $this->error =
184          array("error"     => "STARTTLS not accepted from server",
185                "smtp_code" => $code,
186                "smtp_msg"  => substr($rply,4));
187       if($this->do_debug >= 1) {
188         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF;
189       }
190       return false;
191     }
192
193     //Begin encrypted connection
194     if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
195       return false;
196     }
197
198     return true;
199   }
200
201   /**
202    * Performs SMTP authentication.  Must be run after running the
203    * Hello() method.  Returns true if successfully authenticated.
204    * @access public
205    * @return bool
206    */
207   public function Authenticate($username, $password) {
208     // Start authentication
209     fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
210
211     $rply = $this->get_lines();
212     $code = substr($rply,0,3);
213
214     if($code != 334) {
215       $this->error =
216         array("error" => "AUTH not accepted from server",
217               "smtp_code" => $code,
218               "smtp_msg" => substr($rply,4));
219       if($this->do_debug >= 1) {
220         echo "SMTP -> ERROR: " . $this->error["error"] .
221                  ": " . $rply . $this->CRLF;
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       $this->error =
234         array("error" => "Username not accepted from server",
235               "smtp_code" => $code,
236               "smtp_msg" => substr($rply,4));
237       if($this->do_debug >= 1) {
238         echo "SMTP -> ERROR: " . $this->error["error"] .
239                  ": " . $rply . $this->CRLF;
240       }
241       return false;
242     }
243
244     // Send encoded password
245     fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
246
247     $rply = $this->get_lines();
248     $code = substr($rply,0,3);
249
250     if($code != 235) {
251       $this->error =
252         array("error" => "Password not accepted from server",
253               "smtp_code" => $code,
254               "smtp_msg" => substr($rply,4));
255       if($this->do_debug >= 1) {
256         echo "SMTP -> ERROR: " . $this->error["error"] .
257                  ": " . $rply . $this->CRLF;
258       }
259       return false;
260     }
261
262     return true;
263   }
264
265   /**
266    * Returns true if connected to a server otherwise false
267    * @access public
268    * @return bool
269    */
270   public function Connected() {
271     if(!empty($this->smtp_conn)) {
272       $sock_status = socket_get_status($this->smtp_conn);
273       if($sock_status["eof"]) {
274         // hmm this is an odd situation... the socket is
275         // valid but we are not connected anymore
276         if($this->do_debug >= 1) {
277             echo "SMTP -> NOTICE:" . $this->CRLF .
278                  "EOF caught while checking if connected";
279         }
280         $this->Close();
281         return false;
282       }
283       return true; // everything looks good
284     }
285     return false;
286   }
287
288   /**
289    * Closes the socket and cleans up the state of the class.
290    * It is not considered good to use this function without
291    * first trying to use QUIT.
292    * @access public
293    * @return void
294    */
295   public function Close() {
296     $this->error = null; // so there is no confusion
297     $this->helo_rply = null;
298     if(!empty($this->smtp_conn)) {
299       // close the connection and cleanup
300       fclose($this->smtp_conn);
301       $this->smtp_conn = 0;
302     }
303   }
304
305   /***************************************************************
306    *                        SMTP COMMANDS                       *
307    *************************************************************/
308
309   /**
310    * Issues a data command and sends the msg_data to the server
311    * finializing the mail transaction. $msg_data is the message
312    * that is to be send with the headers. Each header needs to be
313    * on a single line followed by a <CRLF> with the message headers
314    * and the message body being seperated by and additional <CRLF>.
315    *
316    * Implements rfc 821: DATA <CRLF>
317    *
318    * SMTP CODE INTERMEDIATE: 354
319    *     [data]
320    *     <CRLF>.<CRLF>
321    *     SMTP CODE SUCCESS: 250
322    *     SMTP CODE FAILURE: 552,554,451,452
323    * SMTP CODE FAILURE: 451,554
324    * SMTP CODE ERROR  : 500,501,503,421
325    * @access public
326    * @return bool
327    */
328   public function Data($msg_data) {
329     $this->error = null; // so no confusion is caused
330
331     if(!$this->connected()) {
332       $this->error = array(
333               "error" => "Called Data() without being connected");
334       return false;
335     }
336
337     fputs($this->smtp_conn,"DATA" . $this->CRLF);
338
339     $rply = $this->get_lines();
340     $code = substr($rply,0,3);
341
342     if($this->do_debug >= 2) {
343       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
344     }
345
346     if($code != 354) {
347       $this->error =
348         array("error" => "DATA command not accepted from server",
349               "smtp_code" => $code,
350               "smtp_msg" => substr($rply,4));
351       if($this->do_debug >= 1) {
352         echo "SMTP -> ERROR: " . $this->error["error"] .
353                  ": " . $rply . $this->CRLF;
354       }
355       return false;
356     }
357
358     /* the server is ready to accept data!
359      * according to rfc 821 we should not send more than 1000
360      * including the CRLF
361      * characters on a single line so we will break the data up
362      * into lines by \r and/or \n then if needed we will break
363      * each of those into smaller lines to fit within the limit.
364      * in addition we will be looking for lines that start with
365      * a period '.' and append and additional period '.' to that
366      * line. NOTE: this does not count towards are limit.
367      */
368
369     // normalize the line breaks so we know the explode works
370     $msg_data = str_replace("\r\n","\n",$msg_data);
371     $msg_data = str_replace("\r","\n",$msg_data);
372     $lines = explode("\n",$msg_data);
373
374     /* we need to find a good way to determine is headers are
375      * in the msg_data or if it is a straight msg body
376      * currently I am assuming rfc 822 definitions of msg headers
377      * and if the first field of the first line (':' sperated)
378      * does not contain a space then it _should_ be a header
379      * and we can process all lines before a blank "" line as
380      * headers.
381      */
382     $field = substr($lines[0],0,strpos($lines[0],":"));
383     $in_headers = false;
384     if(!empty($field) && !strstr($field," ")) {
385       $in_headers = true;
386     }
387
388     $max_line_length = 998; // used below; set here for ease in change
389
390     while(list(,$line) = @each($lines)) {
391       $lines_out = null;
392       if($line == "" && $in_headers) {
393         $in_headers = false;
394       }
395       // ok we need to break this line up into several smaller lines
396       while(strlen($line) > $max_line_length) {
397         $pos = strrpos(substr($line,0,$max_line_length)," ");
398
399         // Patch to fix DOS attack
400         if(!$pos) {
401           $pos = $max_line_length - 1;
402           $lines_out[] = substr($line,0,$pos);
403           $line = substr($line,$pos);
404         } else {
405           $lines_out[] = substr($line,0,$pos);
406           $line = substr($line,$pos + 1);
407         }
408
409         /* if we are processing headers we need to
410          * add a LWSP-char to the front of the new line
411          * rfc 822 on long msg headers
412          */
413         if($in_headers) {
414           $line = "\t" . $line;
415         }
416       }
417       $lines_out[] = $line;
418
419       // now send the lines to the server
420       while(list(,$line_out) = @each($lines_out)) {
421         if(strlen($line_out) > 0)
422         {
423           if(substr($line_out, 0, 1) == ".") {
424             $line_out = "." . $line_out;
425           }
426         }
427         fputs($this->smtp_conn,$line_out . $this->CRLF);
428       }
429     }
430
431     // ok all the message data has been sent so lets get this
432     // over with aleady
433     fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
434
435     $rply = $this->get_lines();
436     $code = substr($rply,0,3);
437
438     if($this->do_debug >= 2) {
439       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
440     }
441
442     if($code != 250) {
443       $this->error =
444         array("error" => "DATA not accepted from server",
445               "smtp_code" => $code,
446               "smtp_msg" => substr($rply,4));
447       if($this->do_debug >= 1) {
448         echo "SMTP -> ERROR: " . $this->error["error"] .
449                  ": " . $rply . $this->CRLF;
450       }
451       return false;
452     }
453     return true;
454   }
455
456   /**
457    * Expand takes the name and asks the server to list all the
458    * people who are members of the _list_. Expand will return
459    * back and array of the result or false if an error occurs.
460    * Each value in the array returned has the format of:
461    *     [ <full-name> <sp> ] <path>
462    * The definition of <path> is defined in rfc 821
463    *
464    * Implements rfc 821: EXPN <SP> <string> <CRLF>
465    *
466    * SMTP CODE SUCCESS: 250
467    * SMTP CODE FAILURE: 550
468    * SMTP CODE ERROR  : 500,501,502,504,421
469    * @access public
470    * @return string array
471    */
472   public function Expand($name) {
473     $this->error = null; // so no confusion is caused
474
475     if(!$this->connected()) {
476       $this->error = array(
477             "error" => "Called Expand() without being connected");
478       return false;
479     }
480
481     fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
482
483     $rply = $this->get_lines();
484     $code = substr($rply,0,3);
485
486     if($this->do_debug >= 2) {
487       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
488     }
489
490     if($code != 250) {
491       $this->error =
492         array("error" => "EXPN not accepted from server",
493               "smtp_code" => $code,
494               "smtp_msg" => substr($rply,4));
495       if($this->do_debug >= 1) {
496         echo "SMTP -> ERROR: " . $this->error["error"] .
497                  ": " . $rply . $this->CRLF;
498       }
499       return false;
500     }
501
502     // parse the reply and place in our array to return to user
503     $entries = explode($this->CRLF,$rply);
504     while(list(,$l) = @each($entries)) {
505       $list[] = substr($l,4);
506     }
507
508     return $list;
509   }
510
511   /**
512    * Sends the HELO command to the smtp server.
513    * This makes sure that we and the server are in
514    * the same known state.
515    *
516    * Implements from rfc 821: HELO <SP> <domain> <CRLF>
517    *
518    * SMTP CODE SUCCESS: 250
519    * SMTP CODE ERROR  : 500, 501, 504, 421
520    * @access public
521    * @return bool
522    */
523   public function Hello($host="") {
524     $this->error = null; // so no confusion is caused
525
526     if(!$this->connected()) {
527       $this->error = array(
528             "error" => "Called Hello() without being connected");
529       return false;
530     }
531
532     // if a hostname for the HELO was not specified determine
533     //a suitable one to send
534     if(empty($host)) {
535       // we need to determine some sort of appopiate default
536       // to send to the server
537       $host = "localhost";
538     }
539
540     // Send extended hello first (RFC 2821)
541     if(!$this->SendHello("EHLO", $host))
542     {
543       if(!$this->SendHello("HELO", $host))
544           return false;
545     }
546
547     return true;
548   }
549
550   /**
551    * Sends a HELO/EHLO command.
552    * @access private
553    * @return bool
554    */
555   private function SendHello($hello, $host) {
556     fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
557
558     $rply = $this->get_lines();
559     $code = substr($rply,0,3);
560
561     if($this->do_debug >= 2) {
562       echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
563     }
564
565     if($code != 250) {
566       $this->error =
567         array("error" => $hello . " not accepted from server",
568               "smtp_code" => $code,
569               "smtp_msg" => substr($rply,4));
570       if($this->do_debug >= 1) {
571         echo "SMTP -> ERROR: " . $this->error["error"] .
572                  ": " . $rply . $this->CRLF;
573       }
574       return false;
575     }
576
577     $this->helo_rply = $rply;
578
579     return true;
580   }
581
582   /**
583    * Gets help information on the keyword specified. If the keyword
584    * is not specified then returns generic help, ussually contianing
585    * A list of keywords that help is available on. This function
586    * returns the results back to the user. It is up to the user to
587    * handle the returned data. If an error occurs then false is
588    * returned with $this->error set appropiately.
589    *
590    * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
591    *
592    * SMTP CODE SUCCESS: 211,214
593    * SMTP CODE ERROR  : 500,501,502,504,421
594    * @access public
595    * @return string
596    */
597   public function Help($keyword="") {
598     $this->error = null; // to avoid confusion
599
600     if(!$this->connected()) {
601       $this->error = array(
602               "error" => "Called Help() without being connected");
603       return false;
604     }
605
606     $extra = "";
607     if(!empty($keyword)) {
608       $extra = " " . $keyword;
609     }
610
611     fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
612
613     $rply = $this->get_lines();
614     $code = substr($rply,0,3);
615
616     if($this->do_debug >= 2) {
617       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
618     }
619
620     if($code != 211 && $code != 214) {
621       $this->error =
622         array("error" => "HELP not accepted from server",
623               "smtp_code" => $code,
624               "smtp_msg" => substr($rply,4));
625       if($this->do_debug >= 1) {
626         echo "SMTP -> ERROR: " . $this->error["error"] .
627                  ": " . $rply . $this->CRLF;
628       }
629       return false;
630     }
631
632     return $rply;
633   }
634
635   /**
636    * Starts a mail transaction from the email address specified in
637    * $from. Returns true if successful or false otherwise. If True
638    * the mail transaction is started and then one or more Recipient
639    * commands may be called followed by a Data command.
640    *
641    * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
642    *
643    * SMTP CODE SUCCESS: 250
644    * SMTP CODE SUCCESS: 552,451,452
645    * SMTP CODE SUCCESS: 500,501,421
646    * @access public
647    * @return bool
648    */
649   public function Mail($from) {
650     $this->error = null; // so no confusion is caused
651
652     if(!$this->connected()) {
653       $this->error = array(
654               "error" => "Called Mail() without being connected");
655       return false;
656     }
657
658     $useVerp = ($this->do_verp ? "XVERP" : "");
659     fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
660
661     $rply = $this->get_lines();
662     $code = substr($rply,0,3);
663
664     if($this->do_debug >= 2) {
665       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
666     }
667
668     if($code != 250) {
669       $this->error =
670         array("error" => "MAIL not accepted from server",
671               "smtp_code" => $code,
672               "smtp_msg" => substr($rply,4));
673       if($this->do_debug >= 1) {
674         echo "SMTP -> ERROR: " . $this->error["error"] .
675                  ": " . $rply . $this->CRLF;
676       }
677       return false;
678     }
679     return true;
680   }
681
682   /**
683    * Sends the command NOOP to the SMTP server.
684    *
685    * Implements from rfc 821: NOOP <CRLF>
686    *
687    * SMTP CODE SUCCESS: 250
688    * SMTP CODE ERROR  : 500, 421
689    * @access public
690    * @return bool
691    */
692   public function Noop() {
693     $this->error = null; // so no confusion is caused
694
695     if(!$this->connected()) {
696       $this->error = array(
697               "error" => "Called Noop() without being connected");
698       return false;
699     }
700
701     fputs($this->smtp_conn,"NOOP" . $this->CRLF);
702
703     $rply = $this->get_lines();
704     $code = substr($rply,0,3);
705
706     if($this->do_debug >= 2) {
707       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
708     }
709
710     if($code != 250) {
711       $this->error =
712         array("error" => "NOOP not accepted from server",
713               "smtp_code" => $code,
714               "smtp_msg" => substr($rply,4));
715       if($this->do_debug >= 1) {
716         echo "SMTP -> ERROR: " . $this->error["error"] .
717                  ": " . $rply . $this->CRLF;
718       }
719       return false;
720     }
721     return true;
722   }
723
724   /**
725    * Sends the quit command to the server and then closes the socket
726    * if there is no error or the $close_on_error argument is true.
727    *
728    * Implements from rfc 821: QUIT <CRLF>
729    *
730    * SMTP CODE SUCCESS: 221
731    * SMTP CODE ERROR  : 500
732    * @access public
733    * @return bool
734    */
735   public function Quit($close_on_error=true) {
736     $this->error = null; // so there is no confusion
737
738     if(!$this->connected()) {
739       $this->error = array(
740               "error" => "Called Quit() without being connected");
741       return false;
742     }
743
744     // send the quit command to the server
745     fputs($this->smtp_conn,"quit" . $this->CRLF);
746
747     // get any good-bye messages
748     $byemsg = $this->get_lines();
749
750     if($this->do_debug >= 2) {
751       echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
752     }
753
754     $rval = true;
755     $e = null;
756
757     $code = substr($byemsg,0,3);
758     if($code != 221) {
759       // use e as a tmp var cause Close will overwrite $this->error
760       $e = array("error" => "SMTP server rejected quit command",
761                  "smtp_code" => $code,
762                  "smtp_rply" => substr($byemsg,4));
763       $rval = false;
764       if($this->do_debug >= 1) {
765         echo "SMTP -> ERROR: " . $e["error"] . ": " .
766                  $byemsg . $this->CRLF;
767       }
768     }
769
770     if(empty($e) || $close_on_error) {
771       $this->Close();
772     }
773
774     return $rval;
775   }
776
777   /**
778    * Sends the command RCPT to the SMTP server with the TO: argument of $to.
779    * Returns true if the recipient was accepted false if it was rejected.
780    *
781    * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
782    *
783    * SMTP CODE SUCCESS: 250,251
784    * SMTP CODE FAILURE: 550,551,552,553,450,451,452
785    * SMTP CODE ERROR  : 500,501,503,421
786    * @access public
787    * @return bool
788    */
789   public function Recipient($to) {
790     $this->error = null; // so no confusion is caused
791
792     if(!$this->connected()) {
793       $this->error = array(
794               "error" => "Called Recipient() without being connected");
795       return false;
796     }
797
798     fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
799
800     $rply = $this->get_lines();
801     $code = substr($rply,0,3);
802
803     if($this->do_debug >= 2) {
804       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
805     }
806
807     if($code != 250 && $code != 251) {
808       $this->error =
809         array("error" => "RCPT not accepted from server",
810               "smtp_code" => $code,
811               "smtp_msg" => substr($rply,4));
812       if($this->do_debug >= 1) {
813         echo "SMTP -> ERROR: " . $this->error["error"] .
814                  ": " . $rply . $this->CRLF;
815       }
816       return false;
817     }
818     return true;
819   }
820
821   /**
822    * Sends the RSET command to abort and transaction that is
823    * currently in progress. Returns true if successful false
824    * otherwise.
825    *
826    * Implements rfc 821: RSET <CRLF>
827    *
828    * SMTP CODE SUCCESS: 250
829    * SMTP CODE ERROR  : 500,501,504,421
830    * @access public
831    * @return bool
832    */
833   public function Reset() {
834     $this->error = null; // so no confusion is caused
835
836     if(!$this->connected()) {
837       $this->error = array(
838               "error" => "Called Reset() without being connected");
839       return false;
840     }
841
842     fputs($this->smtp_conn,"RSET" . $this->CRLF);
843
844     $rply = $this->get_lines();
845     $code = substr($rply,0,3);
846
847     if($this->do_debug >= 2) {
848       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
849     }
850
851     if($code != 250) {
852       $this->error =
853         array("error" => "RSET failed",
854               "smtp_code" => $code,
855               "smtp_msg" => substr($rply,4));
856       if($this->do_debug >= 1) {
857         echo "SMTP -> ERROR: " . $this->error["error"] .
858                  ": " . $rply . $this->CRLF;
859       }
860       return false;
861     }
862
863     return true;
864   }
865
866   /**
867    * Starts a mail transaction from the email address specified in
868    * $from. Returns true if successful or false otherwise. If True
869    * the mail transaction is started and then one or more Recipient
870    * commands may be called followed by a Data command. This command
871    * will send the message to the users terminal if they are logged
872    * in.
873    *
874    * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
875    *
876    * SMTP CODE SUCCESS: 250
877    * SMTP CODE SUCCESS: 552,451,452
878    * SMTP CODE SUCCESS: 500,501,502,421
879    * @access public
880    * @return bool
881    */
882   public function Send($from) {
883     $this->error = null; // so no confusion is caused
884
885     if(!$this->connected()) {
886       $this->error = array(
887               "error" => "Called Send() without being connected");
888       return false;
889     }
890
891     fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
892
893     $rply = $this->get_lines();
894     $code = substr($rply,0,3);
895
896     if($this->do_debug >= 2) {
897       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
898     }
899
900     if($code != 250) {
901       $this->error =
902         array("error" => "SEND not accepted from server",
903               "smtp_code" => $code,
904               "smtp_msg" => substr($rply,4));
905       if($this->do_debug >= 1) {
906         echo "SMTP -> ERROR: " . $this->error["error"] .
907                  ": " . $rply . $this->CRLF;
908       }
909       return false;
910     }
911     return true;
912   }
913
914   /**
915    * Starts a mail transaction from the email address specified in
916    * $from. Returns true if successful or false otherwise. If True
917    * the mail transaction is started and then one or more Recipient
918    * commands may be called followed by a Data command. This command
919    * will send the message to the users terminal if they are logged
920    * in and send them an email.
921    *
922    * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
923    *
924    * SMTP CODE SUCCESS: 250
925    * SMTP CODE SUCCESS: 552,451,452
926    * SMTP CODE SUCCESS: 500,501,502,421
927    * @access public
928    * @return bool
929    */
930   public function SendAndMail($from) {
931     $this->error = null; // so no confusion is caused
932
933     if(!$this->connected()) {
934       $this->error = array(
935           "error" => "Called SendAndMail() without being connected");
936       return false;
937     }
938
939     fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
940
941     $rply = $this->get_lines();
942     $code = substr($rply,0,3);
943
944     if($this->do_debug >= 2) {
945       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
946     }
947
948     if($code != 250) {
949       $this->error =
950         array("error" => "SAML not accepted from server",
951               "smtp_code" => $code,
952               "smtp_msg" => substr($rply,4));
953       if($this->do_debug >= 1) {
954         echo "SMTP -> ERROR: " . $this->error["error"] .
955                  ": " . $rply . $this->CRLF;
956       }
957       return false;
958     }
959     return true;
960   }
961
962   /**
963    * Starts a mail transaction from the email address specified in
964    * $from. Returns true if successful or false otherwise. If True
965    * the mail transaction is started and then one or more Recipient
966    * commands may be called followed by a Data command. This command
967    * will send the message to the users terminal if they are logged
968    * in or mail it to them if they are not.
969    *
970    * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
971    *
972    * SMTP CODE SUCCESS: 250
973    * SMTP CODE SUCCESS: 552,451,452
974    * SMTP CODE SUCCESS: 500,501,502,421
975    * @access public
976    * @return bool
977    */
978   public function SendOrMail($from) {
979     $this->error = null; // so no confusion is caused
980
981     if(!$this->connected()) {
982       $this->error = array(
983           "error" => "Called SendOrMail() without being connected");
984       return false;
985     }
986
987     fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
988
989     $rply = $this->get_lines();
990     $code = substr($rply,0,3);
991
992     if($this->do_debug >= 2) {
993       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
994     }
995
996     if($code != 250) {
997       $this->error =
998         array("error" => "SOML not accepted from server",
999               "smtp_code" => $code,
1000               "smtp_msg" => substr($rply,4));
1001       if($this->do_debug >= 1) {
1002         echo "SMTP -> ERROR: " . $this->error["error"] .
1003                  ": " . $rply . $this->CRLF;
1004       }
1005       return false;
1006     }
1007     return true;
1008   }
1009
1010   /**
1011    * This is an optional command for SMTP that this class does not
1012    * support. This method is here to make the RFC821 Definition
1013    * complete for this class and __may__ be implimented in the future
1014    *
1015    * Implements from rfc 821: TURN <CRLF>
1016    *
1017    * SMTP CODE SUCCESS: 250
1018    * SMTP CODE FAILURE: 502
1019    * SMTP CODE ERROR  : 500, 503
1020    * @access public
1021    * @return bool
1022    */
1023   public function Turn() {
1024     $this->error = array("error" => "This method, TURN, of the SMTP ".
1025                                     "is not implemented");
1026     if($this->do_debug >= 1) {
1027       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
1028     }
1029     return false;
1030   }
1031
1032   /**
1033    * Verifies that the name is recognized by the server.
1034    * Returns false if the name could not be verified otherwise
1035    * the response from the server is returned.
1036    *
1037    * Implements rfc 821: VRFY <SP> <string> <CRLF>
1038    *
1039    * SMTP CODE SUCCESS: 250,251
1040    * SMTP CODE FAILURE: 550,551,553
1041    * SMTP CODE ERROR  : 500,501,502,421
1042    * @access public
1043    * @return int
1044    */
1045   public function Verify($name) {
1046     $this->error = null; // so no confusion is caused
1047
1048     if(!$this->connected()) {
1049       $this->error = array(
1050               "error" => "Called Verify() without being connected");
1051       return false;
1052     }
1053
1054     fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
1055
1056     $rply = $this->get_lines();
1057     $code = substr($rply,0,3);
1058
1059     if($this->do_debug >= 2) {
1060       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
1061     }
1062
1063     if($code != 250 && $code != 251) {
1064       $this->error =
1065         array("error" => "VRFY failed on name '$name'",
1066               "smtp_code" => $code,
1067               "smtp_msg" => substr($rply,4));
1068       if($this->do_debug >= 1) {
1069         echo "SMTP -> ERROR: " . $this->error["error"] .
1070                  ": " . $rply . $this->CRLF;
1071       }
1072       return false;
1073     }
1074     return $rply;
1075   }
1076
1077   /*******************************************************************
1078    *                       INTERNAL FUNCTIONS                       *
1079    ******************************************************************/
1080
1081   /**
1082    * Read in as many lines as possible
1083    * either before eof or socket timeout occurs on the operation.
1084    * With SMTP we can tell if we have more lines to read if the
1085    * 4th character is '-' symbol. If it is a space then we don't
1086    * need to read anything else.
1087    * @access private
1088    * @return string
1089    */
1090   private function get_lines() {
1091     $data = "";
1092     while($str = @fgets($this->smtp_conn,515)) {
1093       if($this->do_debug >= 4) {
1094         echo "SMTP -> get_lines(): \$data was \"$data\"" .
1095                  $this->CRLF;
1096         echo "SMTP -> get_lines(): \$str is \"$str\"" .
1097                  $this->CRLF;
1098       }
1099       $data .= $str;
1100       if($this->do_debug >= 4) {
1101         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
1102       }
1103       // if the 4th character is a space then we are done reading
1104       // so just break the loop
1105       if(substr($str,3,1) == " ") { break; }
1106     }
1107     return $data;
1108   }
1109
1110 }
1111
1112 ?>