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

Revision 1059, 33.0 KB checked in by amuller, 15 years ago (diff)

Ticket #559 - Removendo inclusão de header.inc.php nas classes e colocando no controler

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