[ Index ]

PHP Cross Reference of MyBB 1.6.7

title

Body

[close]

/inc/mailhandlers/ -> smtp.php (source)

   1  <?php
   2  /**
   3   * MyBB 1.6
   4   * Copyright 2010 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://mybb.com
   7   * License: http://mybb.com/about/license
   8   *
   9   * $Id: smtp.php 5297 2010-12-28 22:01:14Z Tomm $
  10   */
  11  
  12   // Disallow direct access to this file for security reasons
  13  if(!defined("IN_MYBB"))
  14  {
  15      die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");
  16  }
  17  
  18  /**
  19   * SMTP mail handler class.
  20   */
  21   
  22  if(!defined('MYBB_SSL'))
  23  {
  24      define('MYBB_SSL', 1);
  25  }
  26  
  27  if(!defined('MYBB_TLS'))
  28  {
  29      define('MYBB_TLS', 2);
  30  }
  31  
  32  class SmtpMail extends MailHandler
  33  {
  34      /**
  35       * The SMTP connection.
  36       *
  37       * @var resource
  38       */
  39      public $connection;
  40  
  41      /**
  42       * SMTP username.
  43       *
  44       * @var string
  45       */
  46      public $username = '';
  47  
  48      /**
  49       * SMTP password.
  50       *
  51       * @var string
  52       */
  53      public $password = '';
  54  
  55      /**
  56       * Hello string sent to the smtp server with either HELO or EHLO.
  57       *
  58       * @var string
  59       */
  60      public $helo = 'localhost';
  61  
  62      /**
  63       * User authenticated or not.
  64       *
  65       * @var boolean
  66       */
  67      public $authenticated = false;
  68  
  69      /**
  70       * How long before timeout.
  71       *
  72       * @var integer
  73       */
  74      public $timeout = 5;
  75  
  76      /**
  77       * SMTP status.
  78       *
  79       * @var integer
  80       */
  81      public $status = 0;
  82  
  83      /**
  84       * SMTP default port.
  85       *
  86       * @var integer
  87       */
  88      public $port = 25;
  89      
  90      /**
  91       * SMTP default secure port.
  92       *
  93       * @var integer
  94       */
  95      public $secure_port = 465;
  96  
  97      /**
  98       * SMTP host.
  99       *
 100       * @var string
 101       */
 102      public $host = '';
 103      
 104      /**
 105       * The last received response from the SMTP server.
 106       *
 107       * @var string
 108       */
 109      public $data = '';
 110      
 111      /**
 112       * The last received response code from the SMTP server.
 113       *
 114       * @var string
 115       */
 116      public $code = 0;
 117      
 118      /**
 119       * The last received error message from the SMTP server.
 120       *
 121       * @var string
 122       */
 123      public $last_error = '';
 124      
 125      /**
 126       * Are we keeping the connection to the SMTP server alive?
 127       *
 128       * @var boolean
 129       */
 130      public $keep_alive = false;
 131  
 132  	function __construct()
 133      {
 134          global $mybb;
 135  
 136          $protocol = '';
 137          switch($mybb->settings['secure_smtp'])
 138          {
 139              case MYBB_SSL:
 140                  $protocol = 'ssl://';
 141                  break;
 142              case MYBB_TLS:
 143                  $protocol = 'tls://';
 144                  break;
 145          }
 146  
 147          if(empty($mybb->settings['smtp_host']))
 148          {
 149              $this->host = @ini_get('SMTP');
 150          }
 151          else
 152          {
 153              $this->host = $mybb->settings['smtp_host'];
 154          }
 155          
 156          $this->helo = $this->host;
 157  
 158          $this->host = $protocol . $this->host;
 159  
 160          if(empty($mybb->settings['smtp_port']) && !empty($protocol) && !@ini_get('smtp_port'))
 161          {
 162              $this->port = $this->secure_port;
 163          }
 164          else if(empty($mybb->settings['smtp_port']) && @ini_get('smtp_port'))
 165          {
 166              $this->port = @ini_get('smtp_port');
 167          }
 168          else if(!empty($mybb->settings['smtp_port']))
 169          {
 170              $this->port = $mybb->settings['smtp_port'];
 171          }
 172      
 173          $this->password = $mybb->settings['smtp_pass'];
 174          $this->username = $mybb->settings['smtp_user'];
 175      }
 176  
 177      /**
 178       * Sends the email.
 179       *
 180       * @return true/false whether or not the email got sent or not.
 181       */
 182  	function send()
 183      {
 184          global $lang, $mybb;
 185  
 186          if(!$this->connected())
 187          {
 188              $this->connect();
 189          }
 190          
 191          if($this->connected())
 192          {
 193              if(!$this->send_data('MAIL FROM:<'.$this->from.'>', '250'))
 194              {
 195                  $this->fatal_error("The mail server does not understand the MAIL FROM command. Reason: ".$this->get_error());
 196                  return false;
 197              }
 198              
 199              // Loop through recipients
 200              $emails = explode(',', $this->to);
 201              foreach($emails as $to)
 202              {
 203                  $to = trim($to);
 204                  if(!$this->send_data('RCPT TO:<'.$to.'>', '250'))
 205                  {
 206                      $this->fatal_error("The mail server does not understand the RCPT TO command. Reason: ".$this->get_error());
 207                      return false;
 208                  }
 209              }
 210  
 211              if($this->send_data('DATA', '354'))
 212              {
 213                  $this->send_data('Date: ' . gmdate('r'));
 214                  $this->send_data('To: ' . $this->to);
 215                  
 216                  $this->send_data('Subject: ' . $this->subject);
 217  
 218                  // Only send additional headers if we've got any
 219                  if(trim($this->headers))
 220                  {
 221                      $this->send_data(trim($this->headers));
 222                  }
 223                  
 224                  $this->send_data("");
 225  
 226                  // Queue the actual message
 227                  $this->message = str_replace("\n.", "\n..", $this->message);
 228                  $this->send_data($this->message);
 229              }
 230              else
 231              {
 232                  $this->fatal_error("The mail server did not understand the DATA command");
 233                  return false;
 234              }
 235  
 236              $this->send_data('.', '250');
 237  
 238              if(!$this->keep_alive)
 239              {
 240                  $this->close();
 241              }
 242              return true;
 243          }
 244          else
 245          {
 246              return false;
 247          }
 248      }
 249  
 250      /**
 251       * Connect to the SMTP server.
 252       *
 253       * @return boolean True if connection was successful
 254       */
 255  	function connect()
 256      {
 257          global $lang, $mybb;
 258  
 259          $this->connection = @fsockopen($this->host, $this->port, $error_number, $error_string, $this->timeout);
 260          
 261          // DIRECTORY_SEPARATOR checks if running windows
 262          if(function_exists('stream_set_timeout') && DIRECTORY_SEPARATOR != '\\')
 263          {
 264              @stream_set_timeout($this->connection, $this->timeout, 0);
 265          }
 266  
 267          if(is_resource($this->connection))
 268          {
 269              $this->status = 1;
 270              $this->get_data();
 271              if(!$this->check_status('220'))
 272              {
 273                  $this->fatal_error("The mail server is not ready, it did not respond with a 220 status message.");
 274                  return false;
 275              }
 276  
 277              if(!empty($this->username) && !empty($this->password))
 278              {
 279                  $data = $this->send_data('EHLO ' . $this->helo, '250');
 280                  if(!$data)
 281                  {
 282                      $this->fatal_error("The server did not understand the EHLO command");
 283                      return false;
 284                  }
 285                  preg_match("#250-AUTH( |=)(.+)$#mi", $data, $matches);
 286                  if(!$this->auth($matches[2]))
 287                  {
 288                      $this->fatal_error("MyBB was unable to authenticate you against the SMTP server");
 289                      return false;
 290                  }
 291              }
 292              else
 293              {
 294                  if(!$this->send_data('HELO ' . $this->helo, '250'))
 295                  {
 296                      $this->fatal_error("The server did not understand the HELO command");
 297                      return false;
 298                  }
 299              }
 300              return true;
 301          }
 302          else
 303          {
 304              $this->fatal_error("Unable to connect to the mail server with the given details.<br /><br />{$error_number}: {$error_string}");
 305              return false;
 306          }
 307      }
 308      
 309      /**
 310       * Authenticate against the SMTP server.
 311       *
 312       * @param string A list of authentication methods supported by the server
 313       * @return boolean True on success
 314       */
 315  	function auth($auth_methods)
 316      {
 317          global $lang, $mybb;
 318          
 319          $auth_methods = explode(" ", $auth_methods);
 320          
 321          if(in_array("LOGIN", $auth_methods))
 322          {
 323              if(!$this->send_data("AUTH LOGIN", 334))
 324              {
 325                  if($this->code == 503)
 326                  {
 327                      return true;
 328                  }
 329                  $this->fatal_error("The SMTP server did not respond correctly to the AUTH LOGIN command");
 330                  return false;
 331              }
 332              
 333              if(!$this->send_data(base64_encode($this->username), '334'))
 334              {
 335                  $this->fatal_error("The SMTP server rejected the supplied SMTP username. Reason: ".$this->get_error());
 336                  return false;
 337              }
 338              
 339              if(!$this->send_data(base64_encode($this->password), '235'))
 340              {
 341                  $this->fatal_error("The SMTP server rejected the supplied SMTP password. Reason: ".$this->get_error());
 342                  return false;
 343              }
 344          }
 345          else if(in_array("PLAIN", $auth_methods))
 346          {
 347              if(!$this->send_data("AUTH PLAIN", '334'))
 348              {
 349                  if($this->code == 503)
 350                  {
 351                      return true;
 352                  }
 353                  $this->fatal_error("The SMTP server did not respond correctly to the AUTH PLAIN command");
 354                  return false;
 355              }
 356              $auth = base64_encode(chr(0).$this->username.chr(0).$this->password);
 357              if(!$this->send_data($auth, 235))
 358              {
 359                  $this->fatal_error("The SMTP server rejected the supplied login username and password. Reason: ".$this->get_error());
 360                  return false;
 361              }
 362          }
 363          else
 364          {
 365              $this->fatal_error("The SMTP server does not support any of the AUTH methods that MyBB supports");
 366              return false;
 367          }
 368  
 369          // Still here, we're authenticated
 370          return true;
 371      }
 372  
 373      /**
 374       * Fetch data from the SMTP server.
 375       *
 376       * @return string The data from the SMTP server
 377       */
 378  	function get_data()
 379      {
 380          $string = '';
 381  
 382          while((($line = fgets($this->connection, 515)) !== false))
 383          {
 384              $string .= $line;
 385              if(substr($line, 3, 1) == ' ')
 386              {
 387                  break;
 388              }
 389          }
 390          $this->data = $string;
 391          $this->code = substr(trim($this->data), 0, 3);
 392          return $string;
 393      }
 394  
 395      /**
 396       * Check if we're currently connected to an SMTP server
 397       *
 398       * @return boolean true if connected
 399       */
 400  	function connected()
 401      {
 402          if($this->status == 1)
 403          {
 404              return true;
 405          }
 406          return false;
 407      }
 408  
 409      /**
 410       * Send data through to the SMTP server.
 411       *
 412       * @param string The data to be sent
 413       * @param int The response code expected back from the server (if we have one)
 414       * @return boolean True on success
 415       */
 416  	function send_data($data, $status_num = false)
 417      {
 418          if($this->connected())
 419          {
 420              if(fwrite($this->connection, $data."\r\n"))
 421              {
 422                  if($status_num != false)
 423                  {
 424                      $rec = $this->get_data();
 425                      if($this->check_status($status_num))
 426                      {
 427                          return $rec;
 428                      }
 429                      else
 430                      {
 431                          $this->set_error($rec);
 432                          return false;
 433                      }
 434                  }
 435                  return true;
 436              }
 437              else
 438              {
 439                  $this->fatal_error("Unable to send the data to the SMTP server");
 440                  return false;
 441              }
 442          }
 443          return false;
 444      }
 445  
 446      /**
 447       * Checks if the received status code matches the one we expect.
 448       *
 449       * @param int The status code we expected back from the server
 450       * @param boolean True if it matches
 451       */
 452  	function check_status($status_num)
 453      {
 454          if($this->code == $status_num)
 455          {
 456              return $this->data;
 457          }
 458          else
 459          {
 460              return false;
 461          }
 462      }
 463      
 464      /**
 465       * Close the connection to the SMTP server.
 466       */
 467  	function close()
 468      {
 469          if($this->status == 1)
 470          {
 471              $this->send_data('QUIT');
 472              fclose($this->connection);
 473              $this->status = 0;
 474          }
 475      }
 476      
 477      /**
 478       * Get the last error message response from the SMTP server
 479       *
 480       * @return string The error message response from the SMTP server
 481       */
 482  	function get_error()
 483      {
 484          if(!$this->last_error)
 485          {
 486              $this->last_error = "N/A";
 487          }
 488          
 489          return $this->last_error;
 490      }
 491      
 492      /**
 493       * Set the last error message response from the SMTP server
 494       *
 495       * @param string The error message response
 496       */
 497  	function set_error($error)
 498      {
 499          $this->last_error = $error;
 500      }
 501  }
 502  ?>


Generated: Sat Mar 31 17:55:03 2012 Cross-referenced by PHPXref 0.7.1