[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/ -> class-smtp.php (source)

   1  <?php
   2  /*~ class.smtp.php
   3  .---------------------------------------------------------------------------.
   4  |  Software: PHPMailer - PHP email class                                    |
   5  |   Version: 5.2.4                                                          |
   6  |      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
   7  | ------------------------------------------------------------------------- |
   8  |     Admin: Jim Jagielski (project admininistrator)                        |
   9  |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
  10  |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
  11  |          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
  12  |   Founder: Brent R. Matzelle (original founder)                           |
  13  | Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved.              |
  14  | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
  15  | Copyright (c) 2001-2003, Brent R. Matzelle                                |
  16  | ------------------------------------------------------------------------- |
  17  |   License: Distributed under the Lesser General Public License (LGPL)     |
  18  |            http://www.gnu.org/copyleft/lesser.html                        |
  19  | This program is distributed in the hope that it will be useful - WITHOUT  |
  20  | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
  21  | FITNESS FOR A PARTICULAR PURPOSE.                                         |
  22  '---------------------------------------------------------------------------'
  23  */
  24  
  25  /**
  26   * PHPMailer - PHP SMTP email transport class
  27   * NOTE: Designed for use with PHP version 5 and up
  28   * @package PHPMailer
  29   * @author Andy Prevost
  30   * @author Marcus Bointon
  31   * @copyright 2004 - 2008 Andy Prevost
  32   * @author Jim Jagielski
  33   * @copyright 2010 - 2012 Jim Jagielski
  34   * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
  35   */
  36  
  37  /**
  38   * PHP RFC821 SMTP client
  39   *
  40   * Implements all the RFC 821 SMTP commands except TURN which will always return a not implemented error.
  41   * SMTP also provides some utility methods for sending mail to an SMTP server.
  42   * @author Chris Ryan
  43   * @package PHPMailer
  44   */
  45  
  46  class SMTP {
  47    /**
  48     *  SMTP server port
  49     *  @var int
  50     */
  51    public $SMTP_PORT = 25;
  52  
  53    /**
  54     *  SMTP reply line ending (don't change)
  55     *  @var string
  56     */
  57    public $CRLF = "\r\n";
  58  
  59    /**
  60     *  Sets whether debugging is turned on
  61     *  @var bool
  62     */
  63    public $do_debug;       // the level of debug to perform
  64  
  65    /**
  66     * Sets the function/method to use for debugging output.
  67     * Right now we only honor "echo" or "error_log"
  68     * @var string
  69     */
  70    public $Debugoutput     = "echo";
  71  
  72    /**
  73     *  Sets VERP use on/off (default is off)
  74     *  @var bool
  75     */
  76    public $do_verp = false;
  77  
  78    /**
  79     * Sets the SMTP timeout value for reads, in seconds
  80     * @var int
  81     */
  82    public $Timeout         = 15;
  83  
  84    /**
  85     * Sets the SMTP timelimit value for reads, in seconds
  86     * @var int
  87     */
  88    public $Timelimit       = 30;
  89  
  90    /**
  91     * Sets the SMTP PHPMailer Version number
  92     * @var string
  93     */
  94    public $Version         = '5.2.4';
  95  
  96    /////////////////////////////////////////////////
  97    // PROPERTIES, PRIVATE AND PROTECTED
  98    /////////////////////////////////////////////////
  99  
 100    /**
 101     * @var resource The socket to the server
 102     */
 103    private $smtp_conn;
 104    /**
 105     * @var string Error message, if any, for the last call
 106     */
 107    private $error;
 108    /**
 109     * @var string The reply the server sent to us for HELO
 110     */
 111    private $helo_rply;
 112  
 113    /**
 114     * Outputs debugging info via user-defined method
 115     * @param string $str
 116     */
 117    private function edebug($str) {
 118      if ($this->Debugoutput == "error_log") {
 119          error_log($str);
 120      } else {
 121          echo $str;
 122      }
 123    }
 124  
 125    /**
 126     * Initialize the class so that the data is in a known state.
 127     * @access public
 128     * @return SMTP
 129     */
 130    public function __construct() {
 131      $this->smtp_conn = 0;
 132      $this->error = null;
 133      $this->helo_rply = null;
 134  
 135      $this->do_debug = 0;
 136    }
 137  
 138    /////////////////////////////////////////////////
 139    // CONNECTION FUNCTIONS
 140    /////////////////////////////////////////////////
 141  
 142    /**
 143     * Connect to the server specified on the port specified.
 144     * If the port is not specified use the default SMTP_PORT.
 145     * If tval is specified then a connection will try and be
 146     * established with the server for that number of seconds.
 147     * If tval is not specified the default is 30 seconds to
 148     * try on the connection.
 149     *
 150     * SMTP CODE SUCCESS: 220
 151     * SMTP CODE FAILURE: 421
 152     * @access public
 153     * @param string $host
 154     * @param int $port
 155     * @param int $tval
 156     * @return bool
 157     */
 158    public function Connect($host, $port = 0, $tval = 30) {
 159      // set the error val to null so there is no confusion
 160      $this->error = null;
 161  
 162      // make sure we are __not__ connected
 163      if($this->connected()) {
 164        // already connected, generate error
 165        $this->error = array("error" => "Already connected to a server");
 166        return false;
 167      }
 168  
 169      if(empty($port)) {
 170        $port = $this->SMTP_PORT;
 171      }
 172  
 173      // connect to the smtp server
 174      $this->smtp_conn = @fsockopen($host,    // the host of the server
 175                                   $port,    // the port to use
 176                                   $errno,   // error number if any
 177                                   $errstr,  // error message if any
 178                                   $tval);   // give up after ? secs
 179      // verify we connected properly
 180      if(empty($this->smtp_conn)) {
 181        $this->error = array("error" => "Failed to connect to server",
 182                             "errno" => $errno,
 183                             "errstr" => $errstr);
 184        if($this->do_debug >= 1) {
 185          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />');
 186        }
 187        return false;
 188      }
 189  
 190      // SMTP server can take longer to respond, give longer timeout for first read
 191      // Windows does not have support for this timeout function
 192      if(substr(PHP_OS, 0, 3) != "WIN") {
 193       $max = ini_get('max_execution_time');
 194       if ($max != 0 && $tval > $max) { // don't bother if unlimited
 195        @set_time_limit($tval);
 196       }
 197       stream_set_timeout($this->smtp_conn, $tval, 0);
 198      }
 199  
 200      // get any announcement
 201      $announce = $this->get_lines();
 202  
 203      if($this->do_debug >= 2) {
 204        $this->edebug("SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />');
 205      }
 206  
 207      return true;
 208    }
 209  
 210    /**
 211     * Initiate a TLS communication with the server.
 212     *
 213     * SMTP CODE 220 Ready to start TLS
 214     * SMTP CODE 501 Syntax error (no parameters allowed)
 215     * SMTP CODE 454 TLS not available due to temporary reason
 216     * @access public
 217     * @return bool success
 218     */
 219    public function StartTLS() {
 220      $this->error = null; # to avoid confusion
 221  
 222      if(!$this->connected()) {
 223        $this->error = array("error" => "Called StartTLS() without being connected");
 224        return false;
 225      }
 226  
 227      fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
 228  
 229      $rply = $this->get_lines();
 230      $code = substr($rply,0,3);
 231  
 232      if($this->do_debug >= 2) {
 233        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 234      }
 235  
 236      if($code != 220) {
 237        $this->error =
 238           array("error"     => "STARTTLS not accepted from server",
 239                 "smtp_code" => $code,
 240                 "smtp_msg"  => substr($rply,4));
 241        if($this->do_debug >= 1) {
 242          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 243        }
 244        return false;
 245      }
 246  
 247      // Begin encrypted connection
 248      if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
 249        return false;
 250      }
 251  
 252      return true;
 253    }
 254  
 255    /**
 256     * Performs SMTP authentication.  Must be run after running the
 257     * Hello() method.  Returns true if successfully authenticated.
 258     * @access public
 259     * @param string $username
 260     * @param string $password
 261     * @param string $authtype
 262     * @param string $realm
 263     * @param string $workstation
 264     * @return bool
 265     */
 266    public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') {
 267      if (empty($authtype)) {
 268        $authtype = 'LOGIN';
 269      }
 270  
 271      switch ($authtype) {
 272        case 'PLAIN':
 273          // Start authentication
 274          fputs($this->smtp_conn,"AUTH PLAIN" . $this->CRLF);
 275      
 276          $rply = $this->get_lines();
 277          $code = substr($rply,0,3);
 278      
 279          if($code != 334) {
 280            $this->error =
 281              array("error" => "AUTH not accepted from server",
 282                    "smtp_code" => $code,
 283                    "smtp_msg" => substr($rply,4));
 284            if($this->do_debug >= 1) {
 285              $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 286            }
 287            return false;
 288          }
 289          // Send encoded username and password
 290          fputs($this->smtp_conn, base64_encode("\0".$username."\0".$password) . $this->CRLF);
 291  
 292          $rply = $this->get_lines();
 293          $code = substr($rply,0,3);
 294      
 295          if($code != 235) {
 296            $this->error =
 297              array("error" => "Authentication not accepted from server",
 298                    "smtp_code" => $code,
 299                    "smtp_msg" => substr($rply,4));
 300            if($this->do_debug >= 1) {
 301              $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 302            }
 303            return false;
 304          }
 305          break;
 306        case 'LOGIN':
 307          // Start authentication
 308          fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
 309      
 310          $rply = $this->get_lines();
 311          $code = substr($rply,0,3);
 312      
 313          if($code != 334) {
 314            $this->error =
 315              array("error" => "AUTH not accepted from server",
 316                    "smtp_code" => $code,
 317                    "smtp_msg" => substr($rply,4));
 318            if($this->do_debug >= 1) {
 319              $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 320            }
 321            return false;
 322          }
 323      
 324          // Send encoded username
 325          fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
 326      
 327          $rply = $this->get_lines();
 328          $code = substr($rply,0,3);
 329      
 330          if($code != 334) {
 331            $this->error =
 332              array("error" => "Username not accepted from server",
 333                    "smtp_code" => $code,
 334                    "smtp_msg" => substr($rply,4));
 335            if($this->do_debug >= 1) {
 336              $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 337            }
 338            return false;
 339          }
 340      
 341          // Send encoded password
 342          fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
 343      
 344          $rply = $this->get_lines();
 345          $code = substr($rply,0,3);
 346      
 347          if($code != 235) {
 348            $this->error =
 349              array("error" => "Password not accepted from server",
 350                    "smtp_code" => $code,
 351                    "smtp_msg" => substr($rply,4));
 352            if($this->do_debug >= 1) {
 353              $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 354            }
 355            return false;
 356          }
 357          break;
 358        case 'NTLM':
 359          /*
 360           * ntlm_sasl_client.php
 361           ** Bundled with Permission
 362           **
 363           ** How to telnet in windows: http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
 364           ** PROTOCOL Documentation http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
 365           */
 366          require_once('ntlm_sasl_client.php');
 367          $temp = new stdClass();
 368          $ntlm_client = new ntlm_sasl_client_class;
 369          if(! $ntlm_client->Initialize($temp)){//let's test if every function its available
 370              $this->error = array("error" => $temp->error);
 371              if($this->do_debug >= 1) {
 372                  $this->edebug("You need to enable some modules in your php.ini file: " . $this->error["error"] . $this->CRLF);
 373              }
 374              return false;
 375          }
 376          $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1
 377          
 378          fputs($this->smtp_conn,"AUTH NTLM " . base64_encode($msg1) . $this->CRLF);
 379  
 380          $rply = $this->get_lines();
 381          $code = substr($rply,0,3);
 382          
 383  
 384          if($code != 334) {
 385              $this->error =
 386                  array("error" => "AUTH not accepted from server",
 387                        "smtp_code" => $code,
 388                        "smtp_msg" => substr($rply,4));
 389              if($this->do_debug >= 1) {
 390                  $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF);
 391              }
 392              return false;
 393          }
 394          
 395          $challange = substr($rply,3);//though 0 based, there is a white space after the 3 digit number....//msg2
 396          $challange = base64_decode($challange);
 397          $ntlm_res = $ntlm_client->NTLMResponse(substr($challange,24,8),$password);
 398          $msg3 = $ntlm_client->TypeMsg3($ntlm_res,$username,$realm,$workstation);//msg3
 399          // Send encoded username
 400          fputs($this->smtp_conn, base64_encode($msg3) . $this->CRLF);
 401  
 402          $rply = $this->get_lines();
 403          $code = substr($rply,0,3);
 404  
 405          if($code != 235) {
 406              $this->error =
 407                  array("error" => "Could not authenticate",
 408                        "smtp_code" => $code,
 409                        "smtp_msg" => substr($rply,4));
 410              if($this->do_debug >= 1) {
 411                  $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF);
 412              }
 413              return false;
 414          }
 415          break;
 416      }
 417      return true;
 418    }
 419  
 420    /**
 421     * Returns true if connected to a server otherwise false
 422     * @access public
 423     * @return bool
 424     */
 425    public function Connected() {
 426      if(!empty($this->smtp_conn)) {
 427        $sock_status = socket_get_status($this->smtp_conn);
 428        if($sock_status["eof"]) {
 429          // the socket is valid but we are not connected
 430          if($this->do_debug >= 1) {
 431              $this->edebug("SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected");
 432          }
 433          $this->Close();
 434          return false;
 435        }
 436        return true; // everything looks good
 437      }
 438      return false;
 439    }
 440  
 441    /**
 442     * Closes the socket and cleans up the state of the class.
 443     * It is not considered good to use this function without
 444     * first trying to use QUIT.
 445     * @access public
 446     * @return void
 447     */
 448    public function Close() {
 449      $this->error = null; // so there is no confusion
 450      $this->helo_rply = null;
 451      if(!empty($this->smtp_conn)) {
 452        // close the connection and cleanup
 453        fclose($this->smtp_conn);
 454        $this->smtp_conn = 0;
 455      }
 456    }
 457  
 458    /////////////////////////////////////////////////
 459    // SMTP COMMANDS
 460    /////////////////////////////////////////////////
 461  
 462    /**
 463     * Issues a data command and sends the msg_data to the server
 464     * finializing the mail transaction. $msg_data is the message
 465     * that is to be send with the headers. Each header needs to be
 466     * on a single line followed by a <CRLF> with the message headers
 467     * and the message body being seperated by and additional <CRLF>.
 468     *
 469     * Implements rfc 821: DATA <CRLF>
 470     *
 471     * SMTP CODE INTERMEDIATE: 354
 472     *     [data]
 473     *     <CRLF>.<CRLF>
 474     *     SMTP CODE SUCCESS: 250
 475     *     SMTP CODE FAILURE: 552,554,451,452
 476     * SMTP CODE FAILURE: 451,554
 477     * SMTP CODE ERROR  : 500,501,503,421
 478     * @access public
 479     * @param string $msg_data
 480     * @return bool
 481     */
 482    public function Data($msg_data) {
 483      $this->error = null; // so no confusion is caused
 484  
 485      if(!$this->connected()) {
 486        $this->error = array(
 487                "error" => "Called Data() without being connected");
 488        return false;
 489      }
 490  
 491      fputs($this->smtp_conn,"DATA" . $this->CRLF);
 492  
 493      $rply = $this->get_lines();
 494      $code = substr($rply,0,3);
 495  
 496      if($this->do_debug >= 2) {
 497        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 498      }
 499  
 500      if($code != 354) {
 501        $this->error =
 502          array("error" => "DATA command not accepted from server",
 503                "smtp_code" => $code,
 504                "smtp_msg" => substr($rply,4));
 505        if($this->do_debug >= 1) {
 506          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 507        }
 508        return false;
 509      }
 510  
 511      /* the server is ready to accept data!
 512       * according to rfc 821 we should not send more than 1000
 513       * including the CRLF
 514       * characters on a single line so we will break the data up
 515       * into lines by \r and/or \n then if needed we will break
 516       * each of those into smaller lines to fit within the limit.
 517       * in addition we will be looking for lines that start with
 518       * a period '.' and append and additional period '.' to that
 519       * line. NOTE: this does not count towards limit.
 520       */
 521  
 522      // normalize the line breaks so we know the explode works
 523      $msg_data = str_replace("\r\n","\n",$msg_data);
 524      $msg_data = str_replace("\r","\n",$msg_data);
 525      $lines = explode("\n",$msg_data);
 526  
 527      /* we need to find a good way to determine is headers are
 528       * in the msg_data or if it is a straight msg body
 529       * currently I am assuming rfc 822 definitions of msg headers
 530       * and if the first field of the first line (':' sperated)
 531       * does not contain a space then it _should_ be a header
 532       * and we can process all lines before a blank "" line as
 533       * headers.
 534       */
 535  
 536      $field = substr($lines[0],0,strpos($lines[0],":"));
 537      $in_headers = false;
 538      if(!empty($field) && !strstr($field," ")) {
 539        $in_headers = true;
 540      }
 541  
 542      $max_line_length = 998; // used below; set here for ease in change
 543  
 544      while(list(,$line) = @each($lines)) {
 545        $lines_out = null;
 546        if($line == "" && $in_headers) {
 547          $in_headers = false;
 548        }
 549        // ok we need to break this line up into several smaller lines
 550        while(strlen($line) > $max_line_length) {
 551          $pos = strrpos(substr($line,0,$max_line_length)," ");
 552  
 553          // Patch to fix DOS attack
 554          if(!$pos) {
 555            $pos = $max_line_length - 1;
 556            $lines_out[] = substr($line,0,$pos);
 557            $line = substr($line,$pos);
 558          } else {
 559            $lines_out[] = substr($line,0,$pos);
 560            $line = substr($line,$pos + 1);
 561          }
 562  
 563          /* if processing headers add a LWSP-char to the front of new line
 564           * rfc 822 on long msg headers
 565           */
 566          if($in_headers) {
 567            $line = "\t" . $line;
 568          }
 569        }
 570        $lines_out[] = $line;
 571  
 572        // send the lines to the server
 573        while(list(,$line_out) = @each($lines_out)) {
 574          if(strlen($line_out) > 0)
 575          {
 576            if(substr($line_out, 0, 1) == ".") {
 577              $line_out = "." . $line_out;
 578            }
 579          }
 580          fputs($this->smtp_conn,$line_out . $this->CRLF);
 581        }
 582      }
 583  
 584      // message data has been sent
 585      fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
 586  
 587      $rply = $this->get_lines();
 588      $code = substr($rply,0,3);
 589  
 590      if($this->do_debug >= 2) {
 591        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 592      }
 593  
 594      if($code != 250) {
 595        $this->error =
 596          array("error" => "DATA not accepted from server",
 597                "smtp_code" => $code,
 598                "smtp_msg" => substr($rply,4));
 599        if($this->do_debug >= 1) {
 600          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 601        }
 602        return false;
 603      }
 604      return true;
 605    }
 606  
 607    /**
 608     * Sends the HELO command to the smtp server.
 609     * This makes sure that we and the server are in
 610     * the same known state.
 611     *
 612     * Implements from rfc 821: HELO <SP> <domain> <CRLF>
 613     *
 614     * SMTP CODE SUCCESS: 250
 615     * SMTP CODE ERROR  : 500, 501, 504, 421
 616     * @access public
 617     * @param string $host
 618     * @return bool
 619     */
 620    public function Hello($host = '') {
 621      $this->error = null; // so no confusion is caused
 622  
 623      if(!$this->connected()) {
 624        $this->error = array(
 625              "error" => "Called Hello() without being connected");
 626        return false;
 627      }
 628  
 629      // if hostname for HELO was not specified send default
 630      if(empty($host)) {
 631        // determine appropriate default to send to server
 632        $host = "localhost";
 633      }
 634  
 635      // Send extended hello first (RFC 2821)
 636      if(!$this->SendHello("EHLO", $host)) {
 637        if(!$this->SendHello("HELO", $host)) {
 638          return false;
 639        }
 640      }
 641  
 642      return true;
 643    }
 644  
 645    /**
 646     * Sends a HELO/EHLO command.
 647     * @access private
 648     * @param string $hello
 649     * @param string $host
 650     * @return bool
 651     */
 652    private function SendHello($hello, $host) {
 653      fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
 654  
 655      $rply = $this->get_lines();
 656      $code = substr($rply,0,3);
 657  
 658      if($this->do_debug >= 2) {
 659        $this->edebug("SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />');
 660      }
 661  
 662      if($code != 250) {
 663        $this->error =
 664          array("error" => $hello . " not accepted from server",
 665                "smtp_code" => $code,
 666                "smtp_msg" => substr($rply,4));
 667        if($this->do_debug >= 1) {
 668          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 669        }
 670        return false;
 671      }
 672  
 673      $this->helo_rply = $rply;
 674  
 675      return true;
 676    }
 677  
 678    /**
 679     * Starts a mail transaction from the email address specified in
 680     * $from. Returns true if successful or false otherwise. If True
 681     * the mail transaction is started and then one or more Recipient
 682     * commands may be called followed by a Data command.
 683     *
 684     * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
 685     *
 686     * SMTP CODE SUCCESS: 250
 687     * SMTP CODE SUCCESS: 552,451,452
 688     * SMTP CODE SUCCESS: 500,501,421
 689     * @access public
 690     * @param string $from
 691     * @return bool
 692     */
 693    public function Mail($from) {
 694      $this->error = null; // so no confusion is caused
 695  
 696      if(!$this->connected()) {
 697        $this->error = array(
 698                "error" => "Called Mail() without being connected");
 699        return false;
 700      }
 701  
 702      $useVerp = ($this->do_verp ? " XVERP" : "");
 703      fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
 704  
 705      $rply = $this->get_lines();
 706      $code = substr($rply,0,3);
 707  
 708      if($this->do_debug >= 2) {
 709        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 710      }
 711  
 712      if($code != 250) {
 713        $this->error =
 714          array("error" => "MAIL not accepted from server",
 715                "smtp_code" => $code,
 716                "smtp_msg" => substr($rply,4));
 717        if($this->do_debug >= 1) {
 718          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 719        }
 720        return false;
 721      }
 722      return true;
 723    }
 724  
 725    /**
 726     * Sends the quit command to the server and then closes the socket
 727     * if there is no error or the $close_on_error argument is true.
 728     *
 729     * Implements from rfc 821: QUIT <CRLF>
 730     *
 731     * SMTP CODE SUCCESS: 221
 732     * SMTP CODE ERROR  : 500
 733     * @access public
 734     * @param bool $close_on_error
 735     * @return bool
 736     */
 737    public function Quit($close_on_error = true) {
 738      $this->error = null; // so there is no confusion
 739  
 740      if(!$this->connected()) {
 741        $this->error = array(
 742                "error" => "Called Quit() without being connected");
 743        return false;
 744      }
 745  
 746      // send the quit command to the server
 747      fputs($this->smtp_conn,"quit" . $this->CRLF);
 748  
 749      // get any good-bye messages
 750      $byemsg = $this->get_lines();
 751  
 752      if($this->do_debug >= 2) {
 753        $this->edebug("SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />');
 754      }
 755  
 756      $rval = true;
 757      $e = null;
 758  
 759      $code = substr($byemsg,0,3);
 760      if($code != 221) {
 761        // use e as a tmp var cause Close will overwrite $this->error
 762        $e = array("error" => "SMTP server rejected quit command",
 763                   "smtp_code" => $code,
 764                   "smtp_rply" => substr($byemsg,4));
 765        $rval = false;
 766        if($this->do_debug >= 1) {
 767          $this->edebug("SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />');
 768        }
 769      }
 770  
 771      if(empty($e) || $close_on_error) {
 772        $this->Close();
 773      }
 774  
 775      return $rval;
 776    }
 777  
 778    /**
 779     * Sends the command RCPT to the SMTP server with the TO: argument of $to.
 780     * Returns true if the recipient was accepted false if it was rejected.
 781     *
 782     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
 783     *
 784     * SMTP CODE SUCCESS: 250,251
 785     * SMTP CODE FAILURE: 550,551,552,553,450,451,452
 786     * SMTP CODE ERROR  : 500,501,503,421
 787     * @access public
 788     * @param string $to
 789     * @return bool
 790     */
 791    public function Recipient($to) {
 792      $this->error = null; // so no confusion is caused
 793  
 794      if(!$this->connected()) {
 795        $this->error = array(
 796                "error" => "Called Recipient() without being connected");
 797        return false;
 798      }
 799  
 800      fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
 801  
 802      $rply = $this->get_lines();
 803      $code = substr($rply,0,3);
 804  
 805      if($this->do_debug >= 2) {
 806        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 807      }
 808  
 809      if($code != 250 && $code != 251) {
 810        $this->error =
 811          array("error" => "RCPT not accepted from server",
 812                "smtp_code" => $code,
 813                "smtp_msg" => substr($rply,4));
 814        if($this->do_debug >= 1) {
 815          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 816        }
 817        return false;
 818      }
 819      return true;
 820    }
 821  
 822    /**
 823     * Sends the RSET command to abort and transaction that is
 824     * currently in progress. Returns true if successful false
 825     * otherwise.
 826     *
 827     * Implements rfc 821: RSET <CRLF>
 828     *
 829     * SMTP CODE SUCCESS: 250
 830     * SMTP CODE ERROR  : 500,501,504,421
 831     * @access public
 832     * @return bool
 833     */
 834    public function Reset() {
 835      $this->error = null; // so no confusion is caused
 836  
 837      if(!$this->connected()) {
 838        $this->error = array(
 839                "error" => "Called Reset() without being connected");
 840        return false;
 841      }
 842  
 843      fputs($this->smtp_conn,"RSET" . $this->CRLF);
 844  
 845      $rply = $this->get_lines();
 846      $code = substr($rply,0,3);
 847  
 848      if($this->do_debug >= 2) {
 849        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 850      }
 851  
 852      if($code != 250) {
 853        $this->error =
 854          array("error" => "RSET failed",
 855                "smtp_code" => $code,
 856                "smtp_msg" => substr($rply,4));
 857        if($this->do_debug >= 1) {
 858          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 859        }
 860        return false;
 861      }
 862  
 863      return true;
 864    }
 865  
 866    /**
 867     * Starts a mail transaction from the email address specified in
 868     * $from. Returns true if successful or false otherwise. If True
 869     * the mail transaction is started and then one or more Recipient
 870     * commands may be called followed by a Data command. This command
 871     * will send the message to the users terminal if they are logged
 872     * in and send them an email.
 873     *
 874     * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
 875     *
 876     * SMTP CODE SUCCESS: 250
 877     * SMTP CODE SUCCESS: 552,451,452
 878     * SMTP CODE SUCCESS: 500,501,502,421
 879     * @access public
 880     * @param string $from
 881     * @return bool
 882     */
 883    public function SendAndMail($from) {
 884      $this->error = null; // so no confusion is caused
 885  
 886      if(!$this->connected()) {
 887        $this->error = array(
 888            "error" => "Called SendAndMail() without being connected");
 889        return false;
 890      }
 891  
 892      fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
 893  
 894      $rply = $this->get_lines();
 895      $code = substr($rply,0,3);
 896  
 897      if($this->do_debug >= 2) {
 898        $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
 899      }
 900  
 901      if($code != 250) {
 902        $this->error =
 903          array("error" => "SAML not accepted from server",
 904                "smtp_code" => $code,
 905                "smtp_msg" => substr($rply,4));
 906        if($this->do_debug >= 1) {
 907          $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
 908        }
 909        return false;
 910      }
 911      return true;
 912    }
 913  
 914    /**
 915     * This is an optional command for SMTP that this class does not
 916     * support. This method is here to make the RFC821 Definition
 917     * complete for this class and __may__ be implimented in the future
 918     *
 919     * Implements from rfc 821: TURN <CRLF>
 920     *
 921     * SMTP CODE SUCCESS: 250
 922     * SMTP CODE FAILURE: 502
 923     * SMTP CODE ERROR  : 500, 503
 924     * @access public
 925     * @return bool
 926     */
 927    public function Turn() {
 928      $this->error = array("error" => "This method, TURN, of the SMTP ".
 929                                      "is not implemented");
 930      if($this->do_debug >= 1) {
 931        $this->edebug("SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />');
 932      }
 933      return false;
 934    }
 935  
 936    /**
 937    * Get the current error
 938    * @access public
 939    * @return array
 940    */
 941    public function getError() {
 942      return $this->error;
 943    }
 944  
 945    /////////////////////////////////////////////////
 946    // INTERNAL FUNCTIONS
 947    /////////////////////////////////////////////////
 948  
 949    /**
 950     * Read in as many lines as possible
 951     * either before eof or socket timeout occurs on the operation.
 952     * With SMTP we can tell if we have more lines to read if the
 953     * 4th character is '-' symbol. If it is a space then we don't
 954     * need to read anything else.
 955     * @access private
 956     * @return string
 957     */
 958    private function get_lines() {
 959      $data = "";
 960      $endtime = 0;
 961      /* If for some reason the fp is bad, don't inf loop */
 962      if (!is_resource($this->smtp_conn)) {
 963        return $data;
 964      }
 965      stream_set_timeout($this->smtp_conn, $this->Timeout);
 966      if ($this->Timelimit > 0) {
 967        $endtime = time() + $this->Timelimit;
 968      }
 969      while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
 970        $str = @fgets($this->smtp_conn,515);
 971        if($this->do_debug >= 4) {
 972          $this->edebug("SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />');
 973          $this->edebug("SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />');
 974        }
 975        $data .= $str;
 976        if($this->do_debug >= 4) {
 977          $this->edebug("SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />');
 978        }
 979        // if 4th character is a space, we are done reading, break the loop
 980        if(substr($str,3,1) == " ") { break; }
 981        // Timed-out? Log and break
 982        $info = stream_get_meta_data($this->smtp_conn);
 983        if ($info['timed_out']) {
 984          if($this->do_debug >= 4) {
 985            $this->edebug("SMTP -> get_lines(): timed-out (" . $this->Timeout . " seconds) <br />");
 986          }
 987          break;
 988        }
 989        // Now check if reads took too long
 990        if ($endtime) {
 991          if (time() > $endtime) {
 992            if($this->do_debug >= 4) {
 993              $this->edebug("SMTP -> get_lines(): timelimit reached (" . $this->Timelimit . " seconds) <br />");
 994            }
 995            break;
 996          }
 997        }
 998      }
 999      return $data;
1000    }
1001  
1002  }
1003  ?>


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu