PageRenderTime 51ms CodeModel.GetById 13ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/vendor/phpmailer/class.smtp.php

http://zoop.googlecode.com/
PHP | 1045 lines | 558 code | 139 blank | 348 comment | 118 complexity | d1200166732f0787bfa0aaedb23803d9 MD5 | raw file
   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
 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 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 ?>