| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 * @deprecated This constant will be removed in PHPMailer 8.0. Use `PHPMailer::VERSION` instead. 49 */ 50 const VERSION = '7.1.1'; 51 52 /** 53 * Default POP3 port number. 54 * 55 * @var int 56 */ 57 const DEFAULT_PORT = 110; 58 59 /** 60 * Default timeout in seconds. 61 * 62 * @var int 63 */ 64 const DEFAULT_TIMEOUT = 30; 65 66 /** 67 * POP3 class debug output mode. 68 * Debug output level. 69 * Options: 70 * @see POP3::DEBUG_OFF: No output 71 * @see POP3::DEBUG_SERVER: Server messages, connection/server errors 72 * @see POP3::DEBUG_CLIENT: Client and Server messages, connection/server errors 73 * 74 * @var int 75 */ 76 public $do_debug = self::DEBUG_OFF; 77 78 /** 79 * POP3 mail server hostname. 80 * 81 * @var string 82 */ 83 public $host; 84 85 /** 86 * POP3 port number. 87 * 88 * @var int 89 */ 90 public $port; 91 92 /** 93 * POP3 Timeout Value in seconds. 94 * 95 * @var int 96 */ 97 public $tval; 98 99 /** 100 * POP3 username. 101 * 102 * @var string 103 */ 104 public $username; 105 106 /** 107 * POP3 password. 108 * 109 * @var string 110 */ 111 public $password; 112 113 /** 114 * Resource handle for the POP3 connection socket. 115 * 116 * @var resource 117 */ 118 protected $pop_conn; 119 120 /** 121 * Are we connected? 122 * 123 * @var bool 124 */ 125 protected $connected = false; 126 127 /** 128 * Error container. 129 * 130 * @var array 131 */ 132 protected $errors = []; 133 134 /** 135 * Line break constant. 136 */ 137 const LE = "\r\n"; 138 139 /** 140 * Debug level for no output. 141 * 142 * @var int 143 */ 144 const DEBUG_OFF = 0; 145 146 /** 147 * Debug level to show server -> client messages 148 * also shows clients connection errors or errors from server 149 * 150 * @var int 151 */ 152 const DEBUG_SERVER = 1; 153 154 /** 155 * Debug level to show client -> server and server -> client messages. 156 * 157 * @var int 158 */ 159 const DEBUG_CLIENT = 2; 160 161 /** 162 * Simple static wrapper for all-in-one POP before SMTP. 163 * 164 * @param string $host The hostname to connect to 165 * @param int|bool $port The port number to connect to 166 * @param int|bool $timeout The timeout value 167 * @param string $username 168 * @param string $password 169 * @param int $debug_level 170 * 171 * @return bool 172 */ 173 public static function popBeforeSmtp( 174 $host, 175 $port = false, 176 $timeout = false, 177 $username = '', 178 $password = '', 179 $debug_level = 0 180 ) { 181 $pop = new self(); 182 183 return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level); 184 } 185 186 /** 187 * Authenticate with a POP3 server. 188 * A connect, login, disconnect sequence 189 * appropriate for POP-before SMTP authorisation. 190 * 191 * @param string $host The hostname to connect to 192 * @param int|bool $port The port number to connect to 193 * @param int|bool $timeout The timeout value 194 * @param string $username 195 * @param string $password 196 * @param int $debug_level 197 * 198 * @return bool 199 */ 200 public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0) 201 { 202 $this->host = $host; 203 //If no port value provided, use default 204 if (false === $port) { 205 $this->port = static::DEFAULT_PORT; 206 } else { 207 $this->port = (int) $port; 208 } 209 //If no timeout value provided, use default 210 if (false === $timeout) { 211 $this->tval = static::DEFAULT_TIMEOUT; 212 } else { 213 $this->tval = (int) $timeout; 214 } 215 $this->do_debug = (int) $debug_level; 216 $this->username = self::stripControls($username); 217 $this->password = self::stripControls($password); 218 //Reset the error log 219 $this->errors = []; 220 //Connect 221 $result = $this->connect($this->host, $this->port, $this->tval); 222 if ($result) { 223 $login_result = $this->login($this->username, $this->password); 224 if ($login_result) { 225 $this->disconnect(); 226 227 return true; 228 } 229 } 230 //We need to disconnect regardless of whether the login succeeded 231 $this->disconnect(); 232 233 return false; 234 } 235 236 /** 237 * Connect to a POP3 server. 238 * 239 * @param string $host 240 * @param int|bool $port 241 * @param int $tval 242 * 243 * @return bool 244 */ 245 public function connect($host, $port = false, $tval = 30) 246 { 247 //Are we already connected? 248 if ($this->connected) { 249 return true; 250 } 251 252 //On Windows this will raise a PHP Warning error if the hostname doesn't exist. 253 //Rather than suppress it with @fsockopen, capture it cleanly instead 254 set_error_handler(function () { 255 call_user_func_array([$this, 'catchWarning'], func_get_args()); 256 }); 257 258 if (false === $port) { 259 $port = static::DEFAULT_PORT; 260 } 261 262 //Connect to the POP3 server 263 $errno = 0; 264 $errstr = ''; 265 $this->pop_conn = fsockopen( 266 $host, //POP3 Host 267 $port, //Port # 268 $errno, //Error Number 269 $errstr, //Error Message 270 $tval 271 ); //Timeout (seconds) 272 //Restore the error handler 273 restore_error_handler(); 274 275 //Did we connect? 276 if (false === $this->pop_conn) { 277 //It would appear not... 278 $this->setError( 279 "Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr" 280 ); 281 282 return false; 283 } 284 285 //Increase the stream time-out 286 stream_set_timeout($this->pop_conn, $tval, 0); 287 288 //Get the POP3 server response 289 $pop3_response = $this->getResponse(); 290 //Check for the +OK 291 if ($this->checkResponse($pop3_response)) { 292 //The connection is established and the POP3 server is talking 293 $this->connected = true; 294 295 return true; 296 } 297 298 return false; 299 } 300 301 /** 302 * Log in to the POP3 server. 303 * Does not support APOP (RFC 2828, 4949). 304 * 305 * @param string $username 306 * @param string $password 307 * 308 * @return bool 309 */ 310 public function login($username = '', $password = '') 311 { 312 if (!$this->connected) { 313 $this->setError('Not connected to POP3 server'); 314 return false; 315 } 316 if (empty($username)) { 317 $username = $this->username; 318 } 319 if (empty($password)) { 320 $password = $this->password; 321 } 322 $username = self::stripControls($username); 323 $password = self::stripControls($password); 324 //Send the Username 325 $this->sendString("USER $username" . static::LE); 326 $pop3_response = $this->getResponse(); 327 if ($this->checkResponse($pop3_response)) { 328 //Send the Password 329 $this->sendString("PASS $password" . static::LE); 330 $pop3_response = $this->getResponse(); 331 if ($this->checkResponse($pop3_response)) { 332 return true; 333 } 334 } 335 336 return false; 337 } 338 339 /** 340 * Disconnect from the POP3 server. 341 */ 342 public function disconnect() 343 { 344 // If could not connect at all, no need to disconnect 345 if ($this->pop_conn === false) { 346 return; 347 } 348 349 $this->sendString('QUIT' . static::LE); 350 351 // RFC 1939 shows POP3 server sending a +OK response to the QUIT command. 352 // Try to get it. Ignore any failures here. 353 try { 354 $this->getResponse(); 355 } catch (Exception $e) { 356 //Do nothing 357 } 358 359 //The QUIT command may cause the daemon to exit, which will kill our connection 360 //So ignore errors here 361 try { 362 @fclose($this->pop_conn); 363 } catch (Exception $e) { 364 //Do nothing 365 } 366 367 // Clean up attributes. 368 $this->connected = false; 369 $this->pop_conn = false; 370 } 371 372 /** 373 * Get a response from the POP3 server. 374 * 375 * @param int $size The maximum number of bytes to retrieve 376 * 377 * @return string 378 */ 379 protected function getResponse($size = 128) 380 { 381 $response = fgets($this->pop_conn, $size); 382 if ($this->do_debug >= self::DEBUG_SERVER) { 383 echo 'Server -> Client: ', $response; 384 } 385 386 return $response; 387 } 388 389 /** 390 * Send raw data to the POP3 server. 391 * 392 * @param string $string 393 * 394 * @return int 395 */ 396 protected function sendString($string) 397 { 398 if ($this->pop_conn) { 399 if ($this->do_debug >= self::DEBUG_CLIENT) { //Show client messages when debug >= 2 400 echo 'Client -> Server: ', $string; 401 } 402 403 return fwrite($this->pop_conn, $string, strlen($string)); 404 } 405 406 return 0; 407 } 408 409 /** 410 * Checks the POP3 server response. 411 * Looks for +OK or -ERR. 412 * 413 * @param string $string 414 * 415 * @return bool 416 */ 417 protected function checkResponse($string) 418 { 419 if (strpos($string, '+OK') !== 0) { 420 $this->setError("Server reported an error: $string"); 421 422 return false; 423 } 424 425 return true; 426 } 427 428 /** 429 * Add an error to the internal error store. 430 * Also display debug output if it's enabled. 431 * 432 * @param string $error 433 */ 434 protected function setError($error) 435 { 436 $this->errors[] = $error; 437 if ($this->do_debug >= self::DEBUG_SERVER) { 438 echo '<pre>'; 439 foreach ($this->errors as $e) { 440 print_r($e); 441 } 442 echo '</pre>'; 443 } 444 } 445 446 /** 447 * Get an array of error messages, if any. 448 * 449 * @return array 450 */ 451 public function getErrors() 452 { 453 return $this->errors; 454 } 455 456 /** 457 * POP3 connection error handler. 458 * 459 * @param int $errno 460 * @param string $errstr 461 * @param string $errfile 462 * @param int $errline 463 */ 464 protected function catchWarning($errno, $errstr, $errfile, $errline) 465 { 466 $this->setError( 467 'Connecting to the POP3 server raised a PHP warning:' . 468 "errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline" 469 ); 470 } 471 472 /** 473 * Strip all control chars from a string. 474 * 475 * @param $string 476 * 477 * @return string 478 */ 479 protected static function stripControls($string) 480 { 481 return preg_replace('/[\x00-\x1F\x7F]/u', '', $string); 482 } 483 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Fri Aug 14 08:20:23 2026 | Cross-referenced by PHPXref |