source: companies/serpro/expressoMail1_2/inc/class.smtp.php @ 903

Revision 903, 32.8 KB checked in by niltonneto, 15 years ago (diff)

Importacao inicial do Expresso do Serpro

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
336                # Patch to fix DOS attack
337                if(!$pos) {
338                    $pos = $max_line_length - 1;
339                }
340
341                $lines_out[] = substr($line,0,$pos);
342                $line = substr($line,$pos + 1);
343                # if we are processing headers we need to
344                # add a LWSP-char to the front of the new line
345                # rfc 822 on long msg headers
346                if($in_headers) {
347                    $line = "\t" . $line;
348                }
349            }
350            $lines_out[] = $line;
351                        $messageCode = "";
352            # now send the lines to the server
353            while(list(,$line_out) = @each($lines_out)) {
354                if(strlen($line_out) > 0)
355                {
356                    if(substr($line_out, 0, 1) == ".") {
357                        $line_out = "." . $line_out;
358                    }
359                }
360                fputs($this->smtp_conn,$line_out . $this->CRLF);
361            }
362        }
363               
364        # ok all the message data has been sent so lets get this
365        # over with aleady
366        fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
367
368        $rply = $this->get_lines();
369        $code = substr($rply,0,3);
370
371        if($this->do_debug >= 2) {
372            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
373        }
374
375        if($code != 250) {
376            $this->error =
377                array("error" => "DATA not accepted from server",
378                      "smtp_code" => $code,
379                      "smtp_msg" => substr($rply,4));
380            if($this->do_debug >= 1) {
381                echo "SMTP -> ERROR: " . $this->error["error"] .
382                         ": " . $rply . $this->CRLF;
383            }
384            return false;
385        }
386        return $code == 250 ? substr($rply,-13) : true;
387    }
388
389    /**
390     * Expand takes the name and asks the server to list all the
391     * people who are members of the _list_. Expand will return
392     * back and array of the result or false if an error occurs.
393     * Each value in the array returned has the format of:
394     *     [ <full-name> <sp> ] <path>
395     * The definition of <path> is defined in rfc 821
396     *
397     * Implements rfc 821: EXPN <SP> <string> <CRLF>
398     *
399     * SMTP CODE SUCCESS: 250
400     * SMTP CODE FAILURE: 550
401     * SMTP CODE ERROR  : 500,501,502,504,421
402     * @access public
403     * @return string array
404     */
405    function Expand($name) {
406        $this->error = null; # so no confusion is caused
407
408        if(!$this->connected()) {
409            $this->error = array(
410                    "error" => "Called Expand() without being connected");
411            return false;
412        }
413
414        fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
415
416        $rply = $this->get_lines();
417        $code = substr($rply,0,3);
418
419        if($this->do_debug >= 2) {
420            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
421        }
422
423        if($code != 250) {
424            $this->error =
425                array("error" => "EXPN not accepted from server",
426                      "smtp_code" => $code,
427                      "smtp_msg" => substr($rply,4));
428            if($this->do_debug >= 1) {
429                echo "SMTP -> ERROR: " . $this->error["error"] .
430                         ": " . $rply . $this->CRLF;
431            }
432            return false;
433        }
434
435        # parse the reply and place in our array to return to user
436        $entries = explode($this->CRLF,$rply);
437        while(list(,$l) = @each($entries)) {
438            $list[] = substr($l,4);
439        }
440
441        return $list;
442    }
443
444    /**
445     * Sends the HELO command to the smtp server.
446     * This makes sure that we and the server are in
447     * the same known state.
448     *
449     * Implements from rfc 821: HELO <SP> <domain> <CRLF>
450     *
451     * SMTP CODE SUCCESS: 250
452     * SMTP CODE ERROR  : 500, 501, 504, 421
453     * @access public
454     * @return bool
455     */
456    function Hello($host="") {
457        $this->error = null; # so no confusion is caused
458
459        if(!$this->connected()) {
460            $this->error = array(
461                    "error" => "Called Hello() without being connected");
462            return false;
463        }
464
465        # if a hostname for the HELO wasn't specified determine
466        # a suitable one to send
467        if(empty($host)) {
468            # we need to determine some sort of appopiate default
469            # to send to the server
470            $host = "localhost";
471        }
472
473        // Send extended hello first (RFC 2821)
474        if(!$this->SendHello("EHLO", $host))
475        {
476            if(!$this->SendHello("HELO", $host))
477                return false;
478        }
479
480        return true;
481    }
482
483    /**
484     * Sends a HELO/EHLO command.
485     * @access private
486     * @return bool
487     */
488    function SendHello($hello, $host) {
489        fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
490
491        $rply = $this->get_lines();
492        $code = substr($rply,0,3);
493
494        if($this->do_debug >= 2) {
495            echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
496        }
497
498        if($code != 250) {
499            $this->error =
500                array("error" => $hello . " not accepted from server",
501                      "smtp_code" => $code,
502                      "smtp_msg" => substr($rply,4));
503            if($this->do_debug >= 1) {
504                echo "SMTP -> ERROR: " . $this->error["error"] .
505                         ": " . $rply . $this->CRLF;
506            }
507            return false;
508        }
509
510        $this->helo_rply = $rply;
511       
512        return true;
513    }
514
515    /**
516     * Gets help information on the keyword specified. If the keyword
517     * is not specified then returns generic help, ussually contianing
518     * A list of keywords that help is available on. This function
519     * returns the results back to the user. It is up to the user to
520     * handle the returned data. If an error occurs then false is
521     * returned with $this->error set appropiately.
522     *
523     * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
524     *
525     * SMTP CODE SUCCESS: 211,214
526     * SMTP CODE ERROR  : 500,501,502,504,421
527     * @access public
528     * @return string
529     */
530    function Help($keyword="") {
531        $this->error = null; # to avoid confusion
532
533        if(!$this->connected()) {
534            $this->error = array(
535                    "error" => "Called Help() without being connected");
536            return false;
537        }
538
539        $extra = "";
540        if(!empty($keyword)) {
541            $extra = " " . $keyword;
542        }
543
544        fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
545
546        $rply = $this->get_lines();
547        $code = substr($rply,0,3);
548
549        if($this->do_debug >= 2) {
550            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
551        }
552
553        if($code != 211 && $code != 214) {
554            $this->error =
555                array("error" => "HELP not accepted from server",
556                      "smtp_code" => $code,
557                      "smtp_msg" => substr($rply,4));
558            if($this->do_debug >= 1) {
559                echo "SMTP -> ERROR: " . $this->error["error"] .
560                         ": " . $rply . $this->CRLF;
561            }
562            return false;
563        }
564
565        return $rply;
566    }
567
568    /**
569     * Starts a mail transaction from the email address specified in
570     * $from. Returns true if successful or false otherwise. If True
571     * the mail transaction is started and then one or more Recipient
572     * commands may be called followed by a Data command.
573     *
574     * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
575     *
576     * SMTP CODE SUCCESS: 250
577     * SMTP CODE SUCCESS: 552,451,452
578     * SMTP CODE SUCCESS: 500,501,421
579     * @access public
580     * @return bool
581     */
582    function Mail($from) {
583        $this->error = null; # so no confusion is caused
584
585        if(!$this->connected()) {
586            $this->error = array(
587                    "error" => "Called Mail() without being connected");
588            return false;
589        }
590
591        fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);
592
593        $rply = $this->get_lines();
594        $code = substr($rply,0,3);
595
596        if($this->do_debug >= 2) {
597            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
598        }
599
600        if($code != 250) {
601            $this->error =
602                array("error" => "MAIL not accepted from server",
603                      "smtp_code" => $code,
604                      "smtp_msg" => substr($rply,4));
605            if($this->do_debug >= 1) {
606                echo "SMTP -> ERROR: " . $this->error["error"] .
607                         ": " . $rply . $this->CRLF;
608            }
609            return false;
610        }
611        return true;
612    }
613
614    /**
615     * Sends the command NOOP to the SMTP server.
616     *
617     * Implements from rfc 821: NOOP <CRLF>
618     *
619     * SMTP CODE SUCCESS: 250
620     * SMTP CODE ERROR  : 500, 421
621     * @access public
622     * @return bool
623     */
624    function Noop() {
625        $this->error = null; # so no confusion is caused
626
627        if(!$this->connected()) {
628            $this->error = array(
629                    "error" => "Called Noop() without being connected");
630            return false;
631        }
632
633        fputs($this->smtp_conn,"NOOP" . $this->CRLF);
634
635        $rply = $this->get_lines();
636        $code = substr($rply,0,3);
637
638        if($this->do_debug >= 2) {
639            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
640        }
641
642        if($code != 250) {
643            $this->error =
644                array("error" => "NOOP not accepted from server",
645                      "smtp_code" => $code,
646                      "smtp_msg" => substr($rply,4));
647            if($this->do_debug >= 1) {
648                echo "SMTP -> ERROR: " . $this->error["error"] .
649                         ": " . $rply . $this->CRLF;
650            }
651            return false;
652        }
653        return true;
654    }
655
656    /**
657     * Sends the quit command to the server and then closes the socket
658     * if there is no error or the $close_on_error argument is true.
659     *
660     * Implements from rfc 821: QUIT <CRLF>
661     *
662     * SMTP CODE SUCCESS: 221
663     * SMTP CODE ERROR  : 500
664     * @access public
665     * @return bool
666     */
667    function Quit($close_on_error=true) {
668        $this->error = null; # so there is no confusion
669
670        if(!$this->connected()) {
671            $this->error = array(
672                    "error" => "Called Quit() without being connected");
673            return false;
674        }
675
676        # send the quit command to the server
677        fputs($this->smtp_conn,"quit" . $this->CRLF);
678
679        # get any good-bye messages
680        $byemsg = $this->get_lines();
681
682        if($this->do_debug >= 2) {
683            echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
684        }
685
686        $rval = true;
687        $e = null;
688
689        $code = substr($byemsg,0,3);
690        if($code != 221) {
691            # use e as a tmp var cause Close will overwrite $this->error
692            $e = array("error" => "SMTP server rejected quit command",
693                       "smtp_code" => $code,
694                       "smtp_rply" => substr($byemsg,4));
695            $rval = false;
696            if($this->do_debug >= 1) {
697                echo "SMTP -> ERROR: " . $e["error"] . ": " .
698                         $byemsg . $this->CRLF;
699            }
700        }
701
702        if(empty($e) || $close_on_error) {
703            $this->Close();
704        }
705
706        return $rval;
707    }
708
709    /**
710     * Sends the command RCPT to the SMTP server with the TO: argument of $to.
711     * Returns true if the recipient was accepted false if it was rejected.
712     *
713     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
714     *
715     * SMTP CODE SUCCESS: 250,251
716     * SMTP CODE FAILURE: 550,551,552,553,450,451,452
717     * SMTP CODE ERROR  : 500,501,503,421
718     * @access public
719     * @return bool
720     */
721    function Recipient($to) {
722        $this->error = null; # so no confusion is caused
723
724        if(!$this->connected()) {
725            $this->error = array(
726                    "error" => "Called Recipient() without being connected");
727            return false;
728        }
729
730        fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
731
732        $rply = $this->get_lines();
733        $code = substr($rply,0,3);
734
735        if($this->do_debug >= 2) {
736            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
737        }
738
739        if($code != 250 && $code != 251) {
740            $this->error =
741                array("error" => "RCPT not accepted from server",
742                      "smtp_code" => $code,
743                      "smtp_msg" => substr($rply,4));
744            if($this->do_debug >= 1) {
745                echo "SMTP -> ERROR: " . $this->error["error"] .
746                         ": " . $rply . $this->CRLF;
747            }
748            return false;
749        }
750        return true;
751    }
752
753    /**
754     * Sends the RSET command to abort and transaction that is
755     * currently in progress. Returns true if successful false
756     * otherwise.
757     *
758     * Implements rfc 821: RSET <CRLF>
759     *
760     * SMTP CODE SUCCESS: 250
761     * SMTP CODE ERROR  : 500,501,504,421
762     * @access public
763     * @return bool
764     */
765    function Reset() {
766        $this->error = null; # so no confusion is caused
767
768        if(!$this->connected()) {
769            $this->error = array(
770                    "error" => "Called Reset() without being connected");
771            return false;
772        }
773
774        fputs($this->smtp_conn,"RSET" . $this->CRLF);
775
776        $rply = $this->get_lines();
777        $code = substr($rply,0,3);
778
779        if($this->do_debug >= 2) {
780            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
781        }
782
783        if($code != 250) {
784            $this->error =
785                array("error" => "RSET failed",
786                      "smtp_code" => $code,
787                      "smtp_msg" => substr($rply,4));
788            if($this->do_debug >= 1) {
789                echo "SMTP -> ERROR: " . $this->error["error"] .
790                         ": " . $rply . $this->CRLF;
791            }
792            return false;
793        }
794
795        return true;
796    }
797
798    /**
799     * Starts a mail transaction from the email address specified in
800     * $from. Returns true if successful or false otherwise. If True
801     * the mail transaction is started and then one or more Recipient
802     * commands may be called followed by a Data command. This command
803     * will send the message to the users terminal if they are logged
804     * in.
805     *
806     * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
807     *
808     * SMTP CODE SUCCESS: 250
809     * SMTP CODE SUCCESS: 552,451,452
810     * SMTP CODE SUCCESS: 500,501,502,421
811     * @access public
812     * @return bool
813     */
814    function Send($from) {
815        $this->error = null; # so no confusion is caused
816
817        if(!$this->connected()) {
818            $this->error = array(
819                    "error" => "Called Send() without being connected");
820            return false;
821        }
822
823        fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
824
825        $rply = $this->get_lines();
826        $code = substr($rply,0,3);
827
828        if($this->do_debug >= 2) {
829            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
830        }
831
832        if($code != 250) {
833            $this->error =
834                array("error" => "SEND not accepted from server",
835                      "smtp_code" => $code,
836                      "smtp_msg" => substr($rply,4));
837            if($this->do_debug >= 1) {
838                echo "SMTP -> ERROR: " . $this->error["error"] .
839                         ": " . $rply . $this->CRLF;
840            }
841            return false;
842        }
843        return true;
844    }
845
846    /**
847     * Starts a mail transaction from the email address specified in
848     * $from. Returns true if successful or false otherwise. If True
849     * the mail transaction is started and then one or more Recipient
850     * commands may be called followed by a Data command. This command
851     * will send the message to the users terminal if they are logged
852     * in and send them an email.
853     *
854     * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
855     *
856     * SMTP CODE SUCCESS: 250
857     * SMTP CODE SUCCESS: 552,451,452
858     * SMTP CODE SUCCESS: 500,501,502,421
859     * @access public
860     * @return bool
861     */
862    function SendAndMail($from) {
863        $this->error = null; # so no confusion is caused
864
865        if(!$this->connected()) {
866            $this->error = array(
867                "error" => "Called SendAndMail() without being connected");
868            return false;
869        }
870
871        fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
872
873        $rply = $this->get_lines();
874        $code = substr($rply,0,3);
875
876        if($this->do_debug >= 2) {
877            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
878        }
879
880        if($code != 250) {
881            $this->error =
882                array("error" => "SAML not accepted from server",
883                      "smtp_code" => $code,
884                      "smtp_msg" => substr($rply,4));
885            if($this->do_debug >= 1) {
886                echo "SMTP -> ERROR: " . $this->error["error"] .
887                         ": " . $rply . $this->CRLF;
888            }
889            return false;
890        }
891        return true;
892    }
893
894    /**
895     * Starts a mail transaction from the email address specified in
896     * $from. Returns true if successful or false otherwise. If True
897     * the mail transaction is started and then one or more Recipient
898     * commands may be called followed by a Data command. This command
899     * will send the message to the users terminal if they are logged
900     * in or mail it to them if they are not.
901     *
902     * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
903     *
904     * SMTP CODE SUCCESS: 250
905     * SMTP CODE SUCCESS: 552,451,452
906     * SMTP CODE SUCCESS: 500,501,502,421
907     * @access public
908     * @return bool
909     */
910    function SendOrMail($from) {
911        $this->error = null; # so no confusion is caused
912
913        if(!$this->connected()) {
914            $this->error = array(
915                "error" => "Called SendOrMail() without being connected");
916            return false;
917        }
918
919        fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
920
921        $rply = $this->get_lines();
922        $code = substr($rply,0,3);
923
924        if($this->do_debug >= 2) {
925            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
926        }
927
928        if($code != 250) {
929            $this->error =
930                array("error" => "SOML not accepted from server",
931                      "smtp_code" => $code,
932                      "smtp_msg" => substr($rply,4));
933            if($this->do_debug >= 1) {
934                echo "SMTP -> ERROR: " . $this->error["error"] .
935                         ": " . $rply . $this->CRLF;
936            }
937            return false;
938        }
939        return true;
940    }
941
942    /**
943     * This is an optional command for SMTP that this class does not
944     * support. This method is here to make the RFC821 Definition
945     * complete for this class and __may__ be implimented in the future
946     *
947     * Implements from rfc 821: TURN <CRLF>
948     *
949     * SMTP CODE SUCCESS: 250
950     * SMTP CODE FAILURE: 502
951     * SMTP CODE ERROR  : 500, 503
952     * @access public
953     * @return bool
954     */
955    function Turn() {
956        $this->error = array("error" => "This method, TURN, of the SMTP ".
957                                        "is not implemented");
958        if($this->do_debug >= 1) {
959            echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
960        }
961        return false;
962    }
963
964    /**
965     * Verifies that the name is recognized by the server.
966     * Returns false if the name could not be verified otherwise
967     * the response from the server is returned.
968     *
969     * Implements rfc 821: VRFY <SP> <string> <CRLF>
970     *
971     * SMTP CODE SUCCESS: 250,251
972     * SMTP CODE FAILURE: 550,551,553
973     * SMTP CODE ERROR  : 500,501,502,421
974     * @access public
975     * @return int
976     */
977    function Verify($name) {
978        $this->error = null; # so no confusion is caused
979
980        if(!$this->connected()) {
981            $this->error = array(
982                    "error" => "Called Verify() without being connected");
983            return false;
984        }
985
986        fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
987
988        $rply = $this->get_lines();
989        $code = substr($rply,0,3);
990
991        if($this->do_debug >= 2) {
992            echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
993        }
994
995        if($code != 250 && $code != 251) {
996            $this->error =
997                array("error" => "VRFY failed on name '$name'",
998                      "smtp_code" => $code,
999                      "smtp_msg" => substr($rply,4));
1000            if($this->do_debug >= 1) {
1001                echo "SMTP -> ERROR: " . $this->error["error"] .
1002                         ": " . $rply . $this->CRLF;
1003            }
1004            return false;
1005        }
1006        return $rply;
1007    }
1008
1009    /*******************************************************************
1010     *                       INTERNAL FUNCTIONS                       *
1011     ******************************************************************/
1012
1013    /**
1014     * Read in as many lines as possible
1015     * either before eof or socket timeout occurs on the operation.
1016     * With SMTP we can tell if we have more lines to read if the
1017     * 4th character is '-' symbol. If it is a space then we don't
1018     * need to read anything else.
1019     * @access private
1020     * @return string
1021     */
1022    function get_lines() {
1023        $data = "";
1024        while($str = fgets($this->smtp_conn,515)) {
1025            if($this->do_debug >= 4) {
1026                echo "SMTP -> get_lines(): \$data was \"$data\"" .
1027                         $this->CRLF;
1028                echo "SMTP -> get_lines(): \$str is \"$str\"" .
1029                         $this->CRLF;
1030            }
1031            $data .= $str;
1032            if($this->do_debug >= 4) {
1033                echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
1034            }
1035            # if the 4th character is a space then we are done reading
1036            # so just break the loop
1037            if(substr($str,3,1) == " ") { break; }
1038        }
1039        return $data;
1040    }
1041
1042}
1043
1044
1045 ?>
Note: See TracBrowser for help on using the repository browser.