source: trunk/phpgwapi/inc/class.smtp.php @ 2

Revision 2, 32.6 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

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