[ 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 */ 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Wed Aug 13 08:20:01 2025 | Cross-referenced by PHPXref |