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