[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/PHPMailer/ -> POP3.php (source)

   1  <?php
   2  
   3  /**
   4   * PHPMailer POP-Before-SMTP Authentication Class.
   5   * PHP Version 5.5.
   6   *
   7   * @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
   8   *
   9   * @author    Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  10   * @author    Jim Jagielski (jimjag) <jimjag@gmail.com>
  11   * @author    Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  12   * @author    Brent R. Matzelle (original founder)
  13   * @copyright 2012 - 2020 Marcus Bointon
  14   * @copyright 2010 - 2012 Jim Jagielski
  15   * @copyright 2004 - 2009 Andy Prevost
  16   * @license   https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
  17   * @note      This program is distributed in the hope that it will be useful - WITHOUT
  18   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19   * FITNESS FOR A PARTICULAR PURPOSE.
  20   */
  21  
  22  namespace PHPMailer\PHPMailer;
  23  
  24  /**
  25   * PHPMailer POP-Before-SMTP Authentication Class.
  26   * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
  27   * 1) This class does not support APOP authentication.
  28   * 2) Opening and closing lots of POP3 connections can be quite slow. If you need
  29   *   to send a batch of emails then just perform the authentication once at the start,
  30   *   and then loop through your mail sending script. Providing this process doesn't
  31   *   take longer than the verification period lasts on your POP3 server, you should be fine.
  32   * 3) This is really ancient technology; you should only need to use it to talk to very old systems.
  33   * 4) This POP3 class is deliberately lightweight and incomplete, implementing just
  34   *   enough to do authentication.
  35   *   If you want a more complete class there are other POP3 classes for PHP available.
  36   *
  37   * @author Richard Davey (original author) <rich@corephp.co.uk>
  38   * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  39   * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
  40   * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  41   */
  42  class POP3
  43  {
  44      /**
  45       * The POP3 PHPMailer Version number.
  46       *
  47       * @var string
  48       */
  49      const VERSION = '6.10.0';
  50  
  51      /**
  52       * Default POP3 port number.
  53       *
  54       * @var int
  55       */
  56      const DEFAULT_PORT = 110;
  57  
  58      /**
  59       * Default timeout in seconds.
  60       *
  61       * @var int
  62       */
  63      const DEFAULT_TIMEOUT = 30;
  64  
  65      /**
  66       * POP3 class debug output mode.
  67       * Debug output level.
  68       * Options:
  69       * @see POP3::DEBUG_OFF: No output
  70       * @see POP3::DEBUG_SERVER: Server messages, connection/server errors
  71       * @see POP3::DEBUG_CLIENT: Client and Server messages, connection/server errors
  72       *
  73       * @var int
  74       */
  75      public $do_debug = self::DEBUG_OFF;
  76  
  77      /**
  78       * POP3 mail server hostname.
  79       *
  80       * @var string
  81       */
  82      public $host;
  83  
  84      /**
  85       * POP3 port number.
  86       *
  87       * @var int
  88       */
  89      public $port;
  90  
  91      /**
  92       * POP3 Timeout Value in seconds.
  93       *
  94       * @var int
  95       */
  96      public $tval;
  97  
  98      /**
  99       * POP3 username.
 100       *
 101       * @var string
 102       */
 103      public $username;
 104  
 105      /**
 106       * POP3 password.
 107       *
 108       * @var string
 109       */
 110      public $password;
 111  
 112      /**
 113       * Resource handle for the POP3 connection socket.
 114       *
 115       * @var resource
 116       */
 117      protected $pop_conn;
 118  
 119      /**
 120       * Are we connected?
 121       *
 122       * @var bool
 123       */
 124      protected $connected = false;
 125  
 126      /**
 127       * Error container.
 128       *
 129       * @var array
 130       */
 131      protected $errors = [];
 132  
 133      /**
 134       * Line break constant.
 135       */
 136      const LE = "\r\n";
 137  
 138      /**
 139       * Debug level for no output.
 140       *
 141       * @var int
 142       */
 143      const DEBUG_OFF = 0;
 144  
 145      /**
 146       * Debug level to show server -> client messages
 147       * also shows clients connection errors or errors from server
 148       *
 149       * @var int
 150       */
 151      const DEBUG_SERVER = 1;
 152  
 153      /**
 154       * Debug level to show client -> server and server -> client messages.
 155       *
 156       * @var int
 157       */
 158      const DEBUG_CLIENT = 2;
 159  
 160      /**
 161       * Simple static wrapper for all-in-one POP before SMTP.
 162       *
 163       * @param string   $host        The hostname to connect to
 164       * @param int|bool $port        The port number to connect to
 165       * @param int|bool $timeout     The timeout value
 166       * @param string   $username
 167       * @param string   $password
 168       * @param int      $debug_level
 169       *
 170       * @return bool
 171       */
 172      public static function popBeforeSmtp(
 173          $host,
 174          $port = false,
 175          $timeout = false,
 176          $username = '',
 177          $password = '',
 178          $debug_level = 0
 179      ) {
 180          $pop = new self();
 181  
 182          return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
 183      }
 184  
 185      /**
 186       * Authenticate with a POP3 server.
 187       * A connect, login, disconnect sequence
 188       * appropriate for POP-before SMTP authorisation.
 189       *
 190       * @param string   $host        The hostname to connect to
 191       * @param int|bool $port        The port number to connect to
 192       * @param int|bool $timeout     The timeout value
 193       * @param string   $username
 194       * @param string   $password
 195       * @param int      $debug_level
 196       *
 197       * @return bool
 198       */
 199      public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
 200      {
 201          $this->host = $host;
 202          //If no port value provided, use default
 203          if (false === $port) {
 204              $this->port = static::DEFAULT_PORT;
 205          } else {
 206              $this->port = (int) $port;
 207          }
 208          //If no timeout value provided, use default
 209          if (false === $timeout) {
 210              $this->tval = static::DEFAULT_TIMEOUT;
 211          } else {
 212              $this->tval = (int) $timeout;
 213          }
 214          $this->do_debug = $debug_level;
 215          $this->username = $username;
 216          $this->password = $password;
 217          //Reset the error log
 218          $this->errors = [];
 219          //Connect
 220          $result = $this->connect($this->host, $this->port, $this->tval);
 221          if ($result) {
 222              $login_result = $this->login($this->username, $this->password);
 223              if ($login_result) {
 224                  $this->disconnect();
 225  
 226                  return true;
 227              }
 228          }
 229          //We need to disconnect regardless of whether the login succeeded
 230          $this->disconnect();
 231  
 232          return false;
 233      }
 234  
 235      /**
 236       * Connect to a POP3 server.
 237       *
 238       * @param string   $host
 239       * @param int|bool $port
 240       * @param int      $tval
 241       *
 242       * @return bool
 243       */
 244      public function connect($host, $port = false, $tval = 30)
 245      {
 246          //Are we already connected?
 247          if ($this->connected) {
 248              return true;
 249          }
 250  
 251          //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
 252          //Rather than suppress it with @fsockopen, capture it cleanly instead
 253          set_error_handler(function () {
 254              call_user_func_array([$this, 'catchWarning'], func_get_args());
 255          });
 256  
 257          if (false === $port) {
 258              $port = static::DEFAULT_PORT;
 259          }
 260  
 261          //Connect to the POP3 server
 262          $errno = 0;
 263          $errstr = '';
 264          $this->pop_conn = fsockopen(
 265              $host, //POP3 Host
 266              $port, //Port #
 267              $errno, //Error Number
 268              $errstr, //Error Message
 269              $tval
 270          ); //Timeout (seconds)
 271          //Restore the error handler
 272          restore_error_handler();
 273  
 274          //Did we connect?
 275          if (false === $this->pop_conn) {
 276              //It would appear not...
 277              $this->setError(
 278                  "Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
 279              );
 280  
 281              return false;
 282          }
 283  
 284          //Increase the stream time-out
 285          stream_set_timeout($this->pop_conn, $tval, 0);
 286  
 287          //Get the POP3 server response
 288          $pop3_response = $this->getResponse();
 289          //Check for the +OK
 290          if ($this->checkResponse($pop3_response)) {
 291              //The connection is established and the POP3 server is talking
 292              $this->connected = true;
 293  
 294              return true;
 295          }
 296  
 297          return false;
 298      }
 299  
 300      /**
 301       * Log in to the POP3 server.
 302       * Does not support APOP (RFC 2828, 4949).
 303       *
 304       * @param string $username
 305       * @param string $password
 306       *
 307       * @return bool
 308       */
 309      public function login($username = '', $password = '')
 310      {
 311          if (!$this->connected) {
 312              $this->setError('Not connected to POP3 server');
 313              return false;
 314          }
 315          if (empty($username)) {
 316              $username = $this->username;
 317          }
 318          if (empty($password)) {
 319              $password = $this->password;
 320          }
 321  
 322          //Send the Username
 323          $this->sendString("USER $username" . static::LE);
 324          $pop3_response = $this->getResponse();
 325          if ($this->checkResponse($pop3_response)) {
 326              //Send the Password
 327              $this->sendString("PASS $password" . static::LE);
 328              $pop3_response = $this->getResponse();
 329              if ($this->checkResponse($pop3_response)) {
 330                  return true;
 331              }
 332          }
 333  
 334          return false;
 335      }
 336  
 337      /**
 338       * Disconnect from the POP3 server.
 339       */
 340      public function disconnect()
 341      {
 342          // If could not connect at all, no need to disconnect
 343          if ($this->pop_conn === false) {
 344              return;
 345          }
 346  
 347          $this->sendString('QUIT' . static::LE);
 348  
 349          // RFC 1939 shows POP3 server sending a +OK response to the QUIT command.
 350          // Try to get it.  Ignore any failures here.
 351          try {
 352              $this->getResponse();
 353          } catch (Exception $e) {
 354              //Do nothing
 355          }
 356  
 357          //The QUIT command may cause the daemon to exit, which will kill our connection
 358          //So ignore errors here
 359          try {
 360              @fclose($this->pop_conn);
 361          } catch (Exception $e) {
 362              //Do nothing
 363          }
 364  
 365          // Clean up attributes.
 366          $this->connected = false;
 367          $this->pop_conn  = false;
 368      }
 369  
 370      /**
 371       * Get a response from the POP3 server.
 372       *
 373       * @param int $size The maximum number of bytes to retrieve
 374       *
 375       * @return string
 376       */
 377      protected function getResponse($size = 128)
 378      {
 379          $response = fgets($this->pop_conn, $size);
 380          if ($this->do_debug >= self::DEBUG_SERVER) {
 381              echo 'Server -> Client: ', $response;
 382          }
 383  
 384          return $response;
 385      }
 386  
 387      /**
 388       * Send raw data to the POP3 server.
 389       *
 390       * @param string $string
 391       *
 392       * @return int
 393       */
 394      protected function sendString($string)
 395      {
 396          if ($this->pop_conn) {
 397              if ($this->do_debug >= self::DEBUG_CLIENT) { //Show client messages when debug >= 2
 398                  echo 'Client -> Server: ', $string;
 399              }
 400  
 401              return fwrite($this->pop_conn, $string, strlen($string));
 402          }
 403  
 404          return 0;
 405      }
 406  
 407      /**
 408       * Checks the POP3 server response.
 409       * Looks for for +OK or -ERR.
 410       *
 411       * @param string $string
 412       *
 413       * @return bool
 414       */
 415      protected function checkResponse($string)
 416      {
 417          if (strpos($string, '+OK') !== 0) {
 418              $this->setError("Server reported an error: $string");
 419  
 420              return false;
 421          }
 422  
 423          return true;
 424      }
 425  
 426      /**
 427       * Add an error to the internal error store.
 428       * Also display debug output if it's enabled.
 429       *
 430       * @param string $error
 431       */
 432      protected function setError($error)
 433      {
 434          $this->errors[] = $error;
 435          if ($this->do_debug >= self::DEBUG_SERVER) {
 436              echo '<pre>';
 437              foreach ($this->errors as $e) {
 438                  print_r($e);
 439              }
 440              echo '</pre>';
 441          }
 442      }
 443  
 444      /**
 445       * Get an array of error messages, if any.
 446       *
 447       * @return array
 448       */
 449      public function getErrors()
 450      {
 451          return $this->errors;
 452      }
 453  
 454      /**
 455       * POP3 connection error handler.
 456       *
 457       * @param int    $errno
 458       * @param string $errstr
 459       * @param string $errfile
 460       * @param int    $errline
 461       */
 462      protected function catchWarning($errno, $errstr, $errfile, $errline)
 463      {
 464          $this->setError(
 465              'Connecting to the POP3 server raised a PHP warning:' .
 466              "errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
 467          );
 468      }
 469  }


Generated : Wed Aug 13 08:20:01 2025 Cross-referenced by PHPXref