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

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

Ticket #559 - Correção de problema, usando caminho relativo

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