source: trunk/expressoMail1_2/inc/class.smtp.php @ 1036

Revision 1036, 33.2 KB checked in by amuller, 15 years ago (diff)

Ticket #559 - Atualização de segurança

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