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

Revision 1040, 33.3 KB checked in by amuller, 15 years ago (diff)

Ticket #559 - Atualização de download de arquivos e sessão

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