Ticket #28909: 28909.3.diff
File 28909.3.diff, 126.6 KB (added by , 10 years ago) |
---|
-
wp-includes/class-smtp.php
1 1 <?php 2 2 /** 3 3 * PHPMailer RFC821 SMTP email transport class. 4 * Version 5.2.7 5 * PHP version 5.0.0 6 * @category PHP 7 * @package PHPMailer 8 * @link https://github.com/PHPMailer/PHPMailer/ 9 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk> 4 * PHP Version 5 5 * @package PHPMailer 6 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project 7 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 10 8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 11 9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 12 * @ copyright 2013 Marcus Bointon13 * @copyright 20 04 - 2008 Andy Prevost10 * @author Brent R. Matzelle (original founder) 11 * @copyright 2014 Marcus Bointon 14 12 * @copyright 2010 - 2012 Jim Jagielski 15 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 13 * @copyright 2004 - 2009 Andy Prevost 14 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 15 * @note This program is distributed in the hope that it will be useful - WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. 16 18 */ 17 19 18 20 /** 19 21 * PHPMailer RFC821 SMTP email transport class. 20 * 21 * Implements RFC 821 SMTP commands 22 * and provides some utility methods for sending mail to an SMTP server. 23 * 24 * PHP Version 5.0.0 25 * 26 * @category PHP 27 * @package PHPMailer 28 * @link https://github.com/PHPMailer/PHPMailer/blob/master/class.smtp.php 29 * @author Chris Ryan <unknown@example.com> 30 * @author Marcus Bointon <phpmailer@synchromedia.co.uk> 31 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 22 * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. 23 * @package PHPMailer 24 * @author Chris Ryan <unknown@example.com> 25 * @author Marcus Bointon <phpmailer@synchromedia.co.uk> 32 26 */ 33 34 27 class SMTP 35 28 { 36 29 /** 37 * The PHPMailer SMTP Version number. 30 * The PHPMailer SMTP version number. 31 * @type string 38 32 */ 39 const VERSION = '5.2. 7';33 const VERSION = '5.2.9'; 40 34 41 35 /** 42 36 * SMTP line break constant. 37 * @type string 43 38 */ 44 39 const CRLF = "\r\n"; 45 40 46 41 /** 47 42 * The SMTP port to use if one is not specified. 43 * @type integer 48 44 */ 49 45 const DEFAULT_SMTP_PORT = 25; 50 46 51 47 /** 48 * The maximum line length allowed by RFC 2822 section 2.1.1 49 * @type integer 50 */ 51 const MAX_LINE_LENGTH = 998; 52 53 /** 54 * Debug level for no output 55 */ 56 const DEBUG_OFF = 0; 57 58 /** 59 * Debug level to show client -> server messages 60 */ 61 const DEBUG_CLIENT = 1; 62 63 /** 64 * Debug level to show client -> server and server -> client messages 65 */ 66 const DEBUG_SERVER = 2; 67 68 /** 69 * Debug level to show connection status, client -> server and server -> client messages 70 */ 71 const DEBUG_CONNECTION = 3; 72 73 /** 74 * Debug level to show all messages 75 */ 76 const DEBUG_LOWLEVEL = 4; 77 78 /** 52 79 * The PHPMailer SMTP Version number. 53 80 * @type string 54 * @deprecated This should be a constant81 * @deprecated Use the `VERSION` constant instead 55 82 * @see SMTP::VERSION 56 83 */ 57 public $Version = '5.2. 7';84 public $Version = '5.2.9'; 58 85 59 86 /** 60 87 * SMTP server port number. 61 * @type int 62 * @deprecated This is only ever u ed as default value, so should be a constant88 * @type integer 89 * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead 63 90 * @see SMTP::DEFAULT_SMTP_PORT 64 91 */ 65 92 public $SMTP_PORT = 25; 66 93 67 94 /** 68 * SMTP reply line ending 95 * SMTP reply line ending. 69 96 * @type string 70 * @deprecated Use the classconstant instead97 * @deprecated Use the `CRLF` constant instead 71 98 * @see SMTP::CRLF 72 99 */ 73 100 public $CRLF = "\r\n"; … … 74 101 75 102 /** 76 103 * Debug output level. 77 * Options: 0 for no output, 1 for commands, 2 for data and commands 78 * @type int 104 * Options: 105 * * self::DEBUG_OFF (`0`) No debug output, default 106 * * self::DEBUG_CLIENT (`1`) Client commands 107 * * self::DEBUG_SERVER (`2`) Client commands and server responses 108 * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status 109 * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages 110 * @type integer 79 111 */ 80 public $do_debug = 0;112 public $do_debug = self::DEBUG_OFF; 81 113 82 114 /** 83 * The function/method to use for debugging output. 84 * Options: 'echo', 'html' or 'error_log' 85 * @type string 115 * How to handle debug output. 116 * Options: 117 * * `echo` Output plain-text as-is, appropriate for CLI 118 * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output 119 * * `error_log` Output to error log as configured in php.ini 120 * 121 * Alternatively, you can provide a callable expecting two params: a message string and the debug level: 122 * <code> 123 * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; 124 * </code> 125 * @type string|callable 86 126 */ 87 127 public $Debugoutput = 'echo'; 88 128 89 129 /** 90 130 * Whether to use VERP. 91 * @type bool 131 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path 132 * @link http://www.postfix.org/VERP_README.html Info on VERP 133 * @type boolean 92 134 */ 93 135 public $do_verp = false; 94 136 95 137 /** 96 * The SMTP timeout value for reads, in seconds. 97 * @type int 138 * The timeout value for connection, in seconds. 139 * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 140 * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. 141 * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 142 * @type integer 98 143 */ 99 public $Timeout = 15;144 public $Timeout = 300; 100 145 101 146 /** 102 147 * The SMTP timelimit value for reads, in seconds. 103 * @type int 148 * @type integer 104 149 */ 105 150 public $Timelimit = 30; 106 151 … … 112 157 113 158 /** 114 159 * Error message, if any, for the last call. 115 * @type string160 * @type array 116 161 */ 117 protected $error = '';162 protected $error = array(); 118 163 119 164 /** 120 165 * The reply the server sent to us for HELO. 121 * @type string 166 * If null, no HELO string has yet been received. 167 * @type string|null 122 168 */ 123 protected $helo_rply = '';169 protected $helo_rply = null; 124 170 125 171 /** 126 172 * The most recent reply received from the server. … … 129 175 protected $last_reply = ''; 130 176 131 177 /** 132 * Constructor.133 * @access public134 */135 public function __construct()136 {137 $this->smtp_conn = 0;138 $this->error = null;139 $this->helo_rply = null;140 141 $this->do_debug = 0;142 }143 144 /**145 178 * Output debugging info via a user-selected method. 179 * @see SMTP::$Debugoutput 180 * @see SMTP::$do_debug 146 181 * @param string $str Debug string to output 182 * @param integer $level The debug level of this message; see DEBUG_* constants 147 183 * @return void 148 184 */ 149 protected function edebug($str )185 protected function edebug($str, $level = 0) 150 186 { 187 if ($level > $this->do_debug) { 188 return; 189 } 190 if (is_callable($this->Debugoutput)) { 191 call_user_func($this->Debugoutput, $str, $this->do_debug); 192 return; 193 } 151 194 switch ($this->Debugoutput) { 152 195 case 'error_log': 153 196 //Don't output, just log … … 164 207 break; 165 208 case 'echo': 166 209 default: 167 //Just echoes whatever was received 168 echo $str; 210 //Normalize line breaks 211 $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); 212 echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( 213 "\n", 214 "\n \t ", 215 trim($str) 216 )."\n"; 169 217 } 170 218 } 171 219 172 220 /** 173 221 * Connect to an SMTP server. 174 * @param string $host 175 * @param int $portThe port number to connect to176 * @param int $timeout How long to wait for the connection to open222 * @param string $host SMTP server IP or host name 223 * @param integer $port The port number to connect to 224 * @param integer $timeout How long to wait for the connection to open 177 225 * @param array $options An array of options for stream_context_create() 178 226 * @access public 179 * @return bool 227 * @return boolean 180 228 */ 181 229 public function connect($host, $port = null, $timeout = 30, $options = array()) 182 230 { 231 static $streamok; 232 //This is enabled by default since 5.0.0 but some providers disable it 233 //Check this once and cache the result 234 if (is_null($streamok)) { 235 $streamok = function_exists('stream_socket_client'); 236 } 183 237 // Clear errors to avoid confusion 184 $this->error = null; 185 238 $this->error = array(); 186 239 // Make sure we are __not__ connected 187 240 if ($this->connected()) { 188 241 // Already connected, generate error … … 189 242 $this->error = array('error' => 'Already connected to a server'); 190 243 return false; 191 244 } 192 193 245 if (empty($port)) { 194 246 $port = self::DEFAULT_SMTP_PORT; 195 247 } 196 197 248 // Connect to the SMTP server 249 $this->edebug( 250 "Connection: opening to $host:$port, t=$timeout, opt=".var_export($options, true), 251 self::DEBUG_CONNECTION 252 ); 198 253 $errno = 0; 199 254 $errstr = ''; 200 $socket_context = stream_context_create($options); 201 //Suppress errors; connection failures are handled at a higher level 202 $this->smtp_conn = @stream_socket_client( 203 $host . ":" . $port, 204 $errno, 205 $errstr, 206 $timeout, 207 STREAM_CLIENT_CONNECT, 208 $socket_context 209 ); 210 255 if ($streamok) { 256 $socket_context = stream_context_create($options); 257 //Suppress errors; connection failures are handled at a higher level 258 $this->smtp_conn = @stream_socket_client( 259 $host . ":" . $port, 260 $errno, 261 $errstr, 262 $timeout, 263 STREAM_CLIENT_CONNECT, 264 $socket_context 265 ); 266 } else { 267 //Fall back to fsockopen which should work in more places, but is missing some features 268 $this->edebug( 269 "Connection: stream_socket_client not available, falling back to fsockopen", 270 self::DEBUG_CONNECTION 271 ); 272 $this->smtp_conn = fsockopen( 273 $host, 274 $port, 275 $errno, 276 $errstr, 277 $timeout 278 ); 279 } 211 280 // Verify we connected properly 212 if ( empty($this->smtp_conn)) {281 if (!is_resource($this->smtp_conn)) { 213 282 $this->error = array( 214 283 'error' => 'Failed to connect to server', 215 284 'errno' => $errno, 216 285 'errstr' => $errstr 217 286 ); 218 if ($this->do_debug >= 1) { 219 $this->edebug( 220 'SMTP -> ERROR: ' . $this->error['error'] 221 . ": $errstr ($errno)" 222 ); 223 } 287 $this->edebug( 288 'SMTP ERROR: ' . $this->error['error'] 289 . ": $errstr ($errno)", 290 self::DEBUG_CLIENT 291 ); 224 292 return false; 225 293 } 226 294 $this->edebug('Connection: opened', self::DEBUG_CONNECTION); 227 295 // SMTP server can take longer to respond, give longer timeout for first read 228 296 // Windows does not have support for this timeout function 229 297 if (substr(PHP_OS, 0, 3) != 'WIN') { … … 233 301 } 234 302 stream_set_timeout($this->smtp_conn, $timeout, 0); 235 303 } 236 237 304 // Get any announcement 238 305 $announce = $this->get_lines(); 239 240 if ($this->do_debug >= 2) { 241 $this->edebug('SMTP -> FROM SERVER:' . $announce); 242 } 243 306 $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER); 244 307 return true; 245 308 } 246 309 … … 247 310 /** 248 311 * Initiate a TLS (encrypted) session. 249 312 * @access public 250 * @return bool 313 * @return boolean 251 314 */ 252 315 public function startTLS() 253 316 { 254 if (!$this->sendCommand( "STARTTLS", "STARTTLS", 220)) {317 if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { 255 318 return false; 256 319 } 257 320 // Begin encrypted connection … … 259 322 $this->smtp_conn, 260 323 true, 261 324 STREAM_CRYPTO_METHOD_TLS_CLIENT 262 ) 263 ) { 325 )) { 264 326 return false; 265 327 } 266 328 return true; … … 276 338 * @param string $realm The auth realm for NTLM 277 339 * @param string $workstation The auth workstation for NTLM 278 340 * @access public 279 * @return bool True if successfully authenticated.341 * @return boolean True if successfully authenticated. 280 342 */ 281 343 public function authenticate( 282 344 $username, … … 288 350 if (empty($authtype)) { 289 351 $authtype = 'LOGIN'; 290 352 } 291 292 353 switch ($authtype) { 293 354 case 'PLAIN': 294 355 // Start authentication … … 332 393 //Check that functions are available 333 394 if (!$ntlm_client->Initialize($temp)) { 334 395 $this->error = array('error' => $temp->error); 335 if ($this->do_debug >= 1) { 336 $this->edebug( 337 'You need to enable some modules in your php.ini file: ' 338 . $this->error['error'] 339 ); 340 } 396 $this->edebug( 397 'You need to enable some modules in your php.ini file: ' 398 . $this->error['error'], 399 self::DEBUG_CLIENT 400 ); 341 401 return false; 342 402 } 343 403 //msg1 … … 351 411 ) { 352 412 return false; 353 413 } 354 355 414 //Though 0 based, there is a white space after the 3 digit number 356 415 //msg2 357 416 $challenge = substr($this->last_reply, 3); … … 369 428 ); 370 429 // send encoded username 371 430 return $this->sendCommand('Username', base64_encode($msg3), 235); 372 break;373 431 case 'CRAM-MD5': 374 432 // Start authentication 375 433 if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { … … 383 441 384 442 // send encoded credentials 385 443 return $this->sendCommand('Username', base64_encode($response), 235); 386 break;387 444 } 388 445 return true; 389 446 } … … 411 468 // Eliminates the need to install mhash to compute a HMAC 412 469 // by Lance Rushing 413 470 414 $b = 64; // byte length for md5415 if (strlen($key) > $b ) {471 $bytelen = 64; // byte length for md5 472 if (strlen($key) > $bytelen) { 416 473 $key = pack('H*', md5($key)); 417 474 } 418 $key = str_pad($key, $b , chr(0x00));419 $ipad = str_pad('', $b , chr(0x36));420 $opad = str_pad('', $b , chr(0x5c));475 $key = str_pad($key, $bytelen, chr(0x00)); 476 $ipad = str_pad('', $bytelen, chr(0x36)); 477 $opad = str_pad('', $bytelen, chr(0x5c)); 421 478 $k_ipad = $key ^ $ipad; 422 479 $k_opad = $key ^ $opad; 423 480 … … 427 484 /** 428 485 * Check connection state. 429 486 * @access public 430 * @return bool True if connected.487 * @return boolean True if connected. 431 488 */ 432 489 public function connected() 433 490 { 434 if ( !empty($this->smtp_conn)) {491 if (is_resource($this->smtp_conn)) { 435 492 $sock_status = stream_get_meta_data($this->smtp_conn); 436 493 if ($sock_status['eof']) { 437 // the socket is valid but we are not connected 438 if ($this->do_debug >= 1) { 439 $this->edebug( 440 'SMTP -> NOTICE: EOF caught while checking if connected' 441 ); 442 } 494 // The socket is valid but we are not connected 495 $this->edebug( 496 'SMTP NOTICE: EOF caught while checking if connected', 497 self::DEBUG_CLIENT 498 ); 443 499 $this->close(); 444 500 return false; 445 501 } … … 457 513 */ 458 514 public function close() 459 515 { 460 $this->error = null; // so there is no confusion516 $this->error = array(); 461 517 $this->helo_rply = null; 462 if ( !empty($this->smtp_conn)) {518 if (is_resource($this->smtp_conn)) { 463 519 // close the connection and cleanup 464 520 fclose($this->smtp_conn); 465 $this->smtp_conn = 0; 521 $this->smtp_conn = null; //Makes for cleaner serialization 522 $this->edebug('Connection: closed', self::DEBUG_CONNECTION); 466 523 } 467 524 } 468 525 … … 476 533 * Implements rfc 821: DATA <CRLF> 477 534 * @param string $msg_data Message data to send 478 535 * @access public 479 * @return bool 536 * @return boolean 480 537 */ 481 538 public function data($msg_data) 482 539 { … … 483 540 if (!$this->sendCommand('DATA', 'DATA', 354)) { 484 541 return false; 485 542 } 486 487 543 /* The server is ready to accept data! 488 * according to rfc821 we should not send more than 1000 489 * including the CRLF 490 * characters on a single line so we will break the data up 491 * into lines by \r and/or \n then if needed we will break 492 * each of those into smaller lines to fit within the limit. 493 * in addition we will be looking for lines that start with 494 * a period '.' and append and additional period '.' to that 495 * line. NOTE: this does not count towards limit. 544 * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) 545 * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into 546 * smaller lines to fit within the limit. 547 * We will also look for lines that start with a '.' and prepend an additional '.'. 548 * NOTE: this does not count towards line-length limit. 496 549 */ 497 550 498 // Normalize the line breaks before exploding 499 $msg_data = str_replace("\r\n", "\n", $msg_data); 500 $msg_data = str_replace("\r", "\n", $msg_data); 501 $lines = explode("\n", $msg_data); 551 // Normalize line breaks before exploding 552 $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data)); 502 553 503 /* We need to find a good way to determine if headers are 504 * in the msg_data or if it is a straight msg body 505 * currently I am assuming rfc822 definitions of msg headers 506 * and if the first field of the first line (':' separated) 507 * does not contain a space then it _should_ be a header 508 * and we can process all lines before a blank "" line as 509 * headers. 554 /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field 555 * of the first line (':' separated) does not contain a space then it _should_ be a header and we will 556 * process all lines before a blank line as headers. 510 557 */ 511 558 512 559 $field = substr($lines[0], 0, strpos($lines[0], ':')); 513 560 $in_headers = false; 514 if (!empty($field) && !strstr($field, ' ')) {561 if (!empty($field) && strpos($field, ' ') === false) { 515 562 $in_headers = true; 516 563 } 517 564 518 //RFC 2822 section 2.1.1 limit519 $max_line_length = 998;520 521 565 foreach ($lines as $line) { 522 $lines_out = null;523 if ($ line == '' && $in_headers) {566 $lines_out = array(); 567 if ($in_headers and $line == '') { 524 568 $in_headers = false; 525 569 } 526 570 // ok we need to break this line up into several smaller lines 527 while (strlen($line) > $max_line_length) { 528 $pos = strrpos(substr($line, 0, $max_line_length), ' '); 529 530 // Patch to fix DOS attack 531 if (!$pos) { 532 $pos = $max_line_length - 1; 571 //This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len) 572 while (isset($line[self::MAX_LINE_LENGTH])) { 573 //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on 574 //so as to avoid breaking in the middle of a word 575 $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); 576 if (!$pos) { //Deliberately matches both false and 0 577 //No nice break found, add a hard break 578 $pos = self::MAX_LINE_LENGTH - 1; 533 579 $lines_out[] = substr($line, 0, $pos); 534 580 $line = substr($line, $pos); 535 581 } else { 582 //Break at the found point 536 583 $lines_out[] = substr($line, 0, $pos); 584 //Move along by the amount we dealt with 537 585 $line = substr($line, $pos + 1); 538 586 } 539 540 587 /* If processing headers add a LWSP-char to the front of new line 541 * rfc822 on long msg headers588 * RFC822 section 3.1.1 542 589 */ 543 590 if ($in_headers) { 544 591 $line = "\t" . $line; … … 546 593 } 547 594 $lines_out[] = $line; 548 595 549 // send the lines to the server 550 while (list(, $line_out) = @each($lines_out)) { 551 if (strlen($line_out) > 0) { 552 if (substr($line_out, 0, 1) == '.') { 553 $line_out = '.' . $line_out; 554 } 596 // Send the lines to the server 597 foreach ($lines_out as $line_out) { 598 //RFC2821 section 4.5.2 599 if (!empty($line_out) and $line_out[0] == '.') { 600 $line_out = '.' . $line_out; 555 601 } 556 602 $this->client_send($line_out . self::CRLF); 557 603 } … … 565 611 * Send an SMTP HELO or EHLO command. 566 612 * Used to identify the sending server to the receiving server. 567 613 * This makes sure that client and server are in a known state. 568 * Implements fromRFC 821: HELO <SP> <domain> <CRLF>614 * Implements RFC 821: HELO <SP> <domain> <CRLF> 569 615 * and RFC 2821 EHLO. 570 616 * @param string $host The host name or IP to connect to 571 617 * @access public 572 * @return bool 618 * @return boolean 573 619 */ 574 620 public function hello($host = '') 575 621 { 576 622 // Try extended hello first (RFC 2821) 577 if (!$this->sendHello('EHLO', $host)) { 578 if (!$this->sendHello('HELO', $host)) { 579 return false; 580 } 581 } 582 583 return true; 623 return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); 584 624 } 585 625 586 626 /** … … 588 628 * Low-level implementation used by hello() 589 629 * @see hello() 590 630 * @param string $hello The HELO string 591 * @param string $host 631 * @param string $host The hostname to say we are 592 632 * @access protected 593 * @return bool 633 * @return boolean 594 634 */ 595 635 protected function sendHello($hello, $host) 596 636 { … … 608 648 * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> 609 649 * @param string $from Source address of this message 610 650 * @access public 611 * @return bool 651 * @return boolean 612 652 */ 613 653 public function mail($from) 614 654 { … … 624 664 * Send an SMTP QUIT command. 625 665 * Closes the socket if there is no error or the $close_on_error argument is true. 626 666 * Implements from rfc 821: QUIT <CRLF> 627 * @param bool $close_on_error Should the connection close if an error occurs?667 * @param boolean $close_on_error Should the connection close if an error occurs? 628 668 * @access public 629 * @return bool 669 * @return boolean 630 670 */ 631 671 public function quit($close_on_error = true) 632 672 { 633 673 $noerror = $this->sendCommand('QUIT', 'QUIT', 221); 634 $e = $this->error; //Save any error674 $err = $this->error; //Save any error 635 675 if ($noerror or $close_on_error) { 636 676 $this->close(); 637 $this->error = $e ; //Restore any error from the quit command677 $this->error = $err; //Restore any error from the quit command 638 678 } 639 679 return $noerror; 640 680 } … … 641 681 642 682 /** 643 683 * Send an SMTP RCPT command. 644 * Sets the TO argument to $to .684 * Sets the TO argument to $toaddr. 645 685 * Returns true if the recipient was accepted false if it was rejected. 646 686 * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> 647 * @param string $to The address the message is being sent to687 * @param string $toaddr The address the message is being sent to 648 688 * @access public 649 * @return bool 689 * @return boolean 650 690 */ 651 public function recipient($to )691 public function recipient($toaddr) 652 692 { 653 693 return $this->sendCommand( 654 'RCPT TO 655 'RCPT TO:<' . $to . '>',694 'RCPT TO', 695 'RCPT TO:<' . $toaddr . '>', 656 696 array(250, 251) 657 697 ); 658 698 } … … 662 702 * Abort any transaction that is currently in progress. 663 703 * Implements rfc 821: RSET <CRLF> 664 704 * @access public 665 * @return bool True on success.705 * @return boolean True on success. 666 706 */ 667 707 public function reset() 668 708 { … … 673 713 * Send a command to an SMTP server and check its return code. 674 714 * @param string $command The command name - not sent to the server 675 715 * @param string $commandstring The actual command to send 676 * @param int |array $expect One or more expected integer success codes716 * @param integer|array $expect One or more expected integer success codes 677 717 * @access protected 678 * @return bool True on success.718 * @return boolean True on success. 679 719 */ 680 720 protected function sendCommand($command, $commandstring, $expect) 681 721 { 682 722 if (!$this->connected()) { 683 723 $this->error = array( 684 "error"=> "Called $command without being connected"724 'error' => "Called $command without being connected" 685 725 ); 686 726 return false; 687 727 } 688 728 $this->client_send($commandstring . self::CRLF); 689 729 690 $ reply = $this->get_lines();691 $code = substr($ reply, 0, 3);730 $this->last_reply = $this->get_lines(); 731 $code = substr($this->last_reply, 0, 3); 692 732 693 if ($this->do_debug >= 2) { 694 $this->edebug('SMTP -> FROM SERVER:' . $reply); 695 } 733 $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); 696 734 697 735 if (!in_array($code, (array)$expect)) { 698 $this->last_reply = null;699 736 $this->error = array( 700 "error"=> "$command command failed",701 "smtp_code"=> $code,702 "detail" => substr($reply, 4)737 'error' => "$command command failed", 738 'smtp_code' => $code, 739 'detail' => substr($this->last_reply, 4) 703 740 ); 704 if ($this->do_debug >= 1) { 705 $this->edebug( 706 'SMTP -> ERROR: ' . $this->error['error'] . ': ' . $reply 707 ); 708 } 741 $this->edebug( 742 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply, 743 self::DEBUG_CLIENT 744 ); 709 745 return false; 710 746 } 711 747 712 $this->last_reply = $reply; 713 $this->error = null; 748 $this->error = array(); 714 749 return true; 715 750 } 716 751 … … 725 760 * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> 726 761 * @param string $from The address the message is from 727 762 * @access public 728 * @return bool 763 * @return boolean 729 764 */ 730 765 public function sendAndMail($from) 731 766 { 732 return $this->sendCommand( "SAML", "SAML FROM:$from", 250);767 return $this->sendCommand('SAML', "SAML FROM:$from", 250); 733 768 } 734 769 735 770 /** … … 736 771 * Send an SMTP VRFY command. 737 772 * @param string $name The name to verify 738 773 * @access public 739 * @return bool 774 * @return boolean 740 775 */ 741 776 public function verify($name) 742 777 { 743 return $this->sendCommand( "VRFY", "VRFY $name", array(250, 251));778 return $this->sendCommand('VRFY', "VRFY $name", array(250, 251)); 744 779 } 745 780 746 781 /** … … 747 782 * Send an SMTP NOOP command. 748 783 * Used to keep keep-alives alive, doesn't actually do anything 749 784 * @access public 750 * @return bool 785 * @return boolean 751 786 */ 752 787 public function noop() 753 788 { 754 return $this->sendCommand( "NOOP", "NOOP", 250);789 return $this->sendCommand('NOOP', 'NOOP', 250); 755 790 } 756 791 757 792 /** 758 793 * Send an SMTP TURN command. 759 794 * This is an optional command for SMTP that this class does not support. 760 * This method is here to make the RFC821 Definition 761 * complete for this class and __may__ be implemented in future795 * This method is here to make the RFC821 Definition complete for this class 796 * and _may_ be implemented in future 762 797 * Implements from rfc 821: TURN <CRLF> 763 798 * @access public 764 * @return bool 799 * @return boolean 765 800 */ 766 801 public function turn() 767 802 { … … 768 803 $this->error = array( 769 804 'error' => 'The SMTP TURN command is not implemented' 770 805 ); 771 if ($this->do_debug >= 1) { 772 $this->edebug('SMTP -> NOTICE: ' . $this->error['error']); 773 } 806 $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT); 774 807 return false; 775 808 } 776 809 … … 778 811 * Send raw data to the server. 779 812 * @param string $data The data to send 780 813 * @access public 781 * @return int |bool The number of bytes sent to the server or FALSEon error814 * @return integer|boolean The number of bytes sent to the server or false on error 782 815 */ 783 816 public function client_send($data) 784 817 { 785 if ($this->do_debug >= 1) { 786 $this->edebug("CLIENT -> SMTP: $data"); 787 } 818 $this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT); 788 819 return fwrite($this->smtp_conn, $data); 789 820 } 790 821 … … 819 850 */ 820 851 protected function get_lines() 821 852 { 853 // If the connection is bad, give up straight away 854 if (!is_resource($this->smtp_conn)) { 855 return ''; 856 } 822 857 $data = ''; 823 858 $endtime = 0; 824 // If the connection is bad, give up now825 if (!is_resource($this->smtp_conn)) {826 return $data;827 }828 859 stream_set_timeout($this->smtp_conn, $this->Timeout); 829 860 if ($this->Timelimit > 0) { 830 861 $endtime = time() + $this->Timelimit; … … 831 862 } 832 863 while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { 833 864 $str = @fgets($this->smtp_conn, 515); 834 if ($this->do_debug >= 4) { 835 $this->edebug("SMTP -> get_lines(): \$data was \"$data\""); 836 $this->edebug("SMTP -> get_lines(): \$str is \"$str\""); 837 } 865 $this->edebug("SMTP -> get_lines(): \$data was \"$data\"", self::DEBUG_LOWLEVEL); 866 $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL); 838 867 $data .= $str; 839 if ($this->do_debug >= 4) { 840 $this->edebug("SMTP -> get_lines(): \$data is \"$data\""); 841 } 842 // if 4th character is a space, we are done reading, break the loop 843 if (substr($str, 3, 1) == ' ') { 868 $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL); 869 // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen 870 if ((isset($str[3]) and $str[3] == ' ')) { 844 871 break; 845 872 } 846 873 // Timed-out? Log and break 847 874 $info = stream_get_meta_data($this->smtp_conn); 848 875 if ($info['timed_out']) { 849 if ($this->do_debug >= 4) { 850 $this->edebug( 851 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)' 852 ); 853 } 876 $this->edebug( 877 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)', 878 self::DEBUG_LOWLEVEL 879 ); 854 880 break; 855 881 } 856 882 // Now check if reads took too long 857 if ($endtime) { 858 if (time() > $endtime) { 859 if ($this->do_debug >= 4) { 860 $this->edebug( 861 'SMTP -> get_lines(): timelimit reached (' 862 . $this->Timelimit . ' sec)' 863 ); 864 } 865 break; 866 } 883 if ($endtime and time() > $endtime) { 884 $this->edebug( 885 'SMTP -> get_lines(): timelimit reached ('. 886 $this->Timelimit . ' sec)', 887 self::DEBUG_LOWLEVEL 888 ); 889 break; 867 890 } 868 891 } 869 892 return $data; … … 871 894 872 895 /** 873 896 * Enable or disable VERP address generation. 874 * @param bool $enabled897 * @param boolean $enabled 875 898 */ 876 899 public function setVerp($enabled = false) 877 900 { … … 880 903 881 904 /** 882 905 * Get VERP address generation mode. 883 * @return bool 906 * @return boolean 884 907 */ 885 908 public function getVerp() 886 909 { … … 907 930 908 931 /** 909 932 * Set debug output level. 910 * @param int $level933 * @param integer $level 911 934 */ 912 935 public function setDebugLevel($level = 0) 913 936 { … … 916 939 917 940 /** 918 941 * Get debug output level. 919 * @return int 942 * @return integer 920 943 */ 921 944 public function getDebugLevel() 922 945 { … … 925 948 926 949 /** 927 950 * Set SMTP timeout. 928 * @param int $timeout951 * @param integer $timeout 929 952 */ 930 953 public function setTimeout($timeout = 0) 931 954 { … … 934 957 935 958 /** 936 959 * Get SMTP timeout. 937 * @return int 960 * @return integer 938 961 */ 939 962 public function getTimeout() 940 963 { -
wp-includes/class-phpmailer.php
1 1 <?php 2 2 /** 3 3 * PHPMailer - PHP email creation and transport class. 4 * PHP Version 5.0.0 5 * Version 5.2.7 4 * PHP Version 5 6 5 * @package PHPMailer 7 * @link https://github.com/PHPMailer/PHPMailer/ 8 * @author Marcus Bointon ( coolbru) <phpmailer@synchromedia.co.uk>6 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project 7 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 9 8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 10 9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 11 10 * @author Brent R. Matzelle (original founder) 12 * @copyright 201 3Marcus Bointon11 * @copyright 2012 - 2014 Marcus Bointon 13 12 * @copyright 2010 - 2012 Jim Jagielski 14 13 * @copyright 2004 - 2009 Andy Prevost 15 14 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License … … 18 17 * FITNESS FOR A PARTICULAR PURPOSE. 19 18 */ 20 19 21 if (version_compare(PHP_VERSION, '5.0.0', '<')) {22 exit("Sorry, PHPMailer will only run on PHP version 5 or greater!\n");23 }24 25 20 /** 26 21 * PHPMailer - PHP email creation and transport class. 27 * PHP Version 5.0.028 22 * @package PHPMailer 29 * @author Marcus Bointon ( coolbru) <phpmailer@synchromedia.co.uk>23 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 30 24 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 31 25 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 32 26 * @author Brent R. Matzelle (original founder) 33 * @copyright 2013 Marcus Bointon34 * @copyright 2010 - 2012 Jim Jagielski35 * @copyright 2004 - 2009 Andy Prevost36 27 */ 37 28 class PHPMailer 38 29 { … … 40 31 * The PHPMailer Version number. 41 32 * @type string 42 33 */ 43 public $Version = '5.2. 7';34 public $Version = '5.2.9'; 44 35 45 36 /** 46 37 * Email priority. 47 38 * Options: 1 = High, 3 = Normal, 5 = low. 48 * @type int 39 * @type integer 49 40 */ 50 41 public $Priority = 3; 51 42 … … 97 88 * The Return-Path of the message. 98 89 * If empty, it will be set to either From or Sender. 99 90 * @type string 91 * @deprecated Email senders should never set a return-path header; 92 * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything. 93 * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference 100 94 */ 101 95 public $ReturnPath = ''; 102 96 … … 155 149 156 150 /** 157 151 * Word-wrap the message body to this number of chars. 158 * @type int 152 * @type integer 159 153 */ 160 154 public $WordWrap = 0; 161 155 … … 175 169 /** 176 170 * Whether mail() uses a fully sendmail-compatible MTA. 177 171 * One which supports sendmail's "-oi -f" options. 178 * @type bool 172 * @type boolean 179 173 */ 180 174 public $UseSendmailOptions = true; 181 175 … … 222 216 * You can also specify a different port 223 217 * for each host by using this format: [hostname:port] 224 218 * (e.g. "smtp1.example.com:25;smtp2.example.com"). 219 * You can also specify encryption type, for example: 220 * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). 225 221 * Hosts will be tried in order. 226 222 * @type string 227 223 */ … … 229 225 230 226 /** 231 227 * The default SMTP server port. 232 * @type int 233 * @T odoWhy is this needed when the SMTP class takes care of it?228 * @type integer 229 * @TODO Why is this needed when the SMTP class takes care of it? 234 230 */ 235 231 public $Port = 25; 236 232 … … 252 248 /** 253 249 * Whether to use SMTP authentication. 254 250 * Uses the Username and Password properties. 255 * @type bool 251 * @type boolean 256 252 * @see PHPMailer::$Username 257 253 * @see PHPMailer::$Password 258 254 */ … … 293 289 294 290 /** 295 291 * The SMTP server timeout in seconds. 296 * @type int 292 * @type integer 297 293 */ 298 294 public $Timeout = 10; 299 295 300 296 /** 301 297 * SMTP class debug output mode. 302 * Options: 0 = off, 1 = commands, 2 = commands and data 303 * @type int 298 * Debug output level. 299 * Options: 300 * * `0` No output 301 * * `1` Commands 302 * * `2` Data and commands 303 * * `3` As 2 plus connection status 304 * * `4` Low-level data output 305 * @type integer 304 306 * @see SMTP::$do_debug 305 307 */ 306 308 public $SMTPDebug = 0; 307 309 308 310 /** 309 * The function/method to use for debugging output. 310 * Options: "echo" or "error_log" 311 * @type string 311 * How to handle debug output. 312 * Options: 313 * * `echo` Output plain-text as-is, appropriate for CLI 314 * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output 315 * * `error_log` Output to error log as configured in php.ini 316 * 317 * Alternatively, you can provide a callable expecting two params: a message string and the debug level: 318 * <code> 319 * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; 320 * </code> 321 * @type string|callable 312 322 * @see SMTP::$Debugoutput 313 323 */ 314 public $Debugoutput = "echo";324 public $Debugoutput = 'echo'; 315 325 316 326 /** 317 327 * Whether to keep SMTP connection open after each message. 318 328 * If this is set to true then to close the connection 319 329 * requires an explicit call to smtpClose(). 320 * @type bool 330 * @type boolean 321 331 */ 322 332 public $SMTPKeepAlive = false; 323 333 … … 324 334 /** 325 335 * Whether to split multiple to addresses into multiple messages 326 336 * or send them all in one message. 327 * @type bool 337 * @type boolean 328 338 */ 329 339 public $SingleTo = false; 330 340 … … 331 341 /** 332 342 * Storage for addresses when SingleTo is enabled. 333 343 * @type array 334 * @ todoThis should really not be public344 * @TODO This should really not be public 335 345 */ 336 346 public $SingleToArray = array(); 337 347 … … 339 349 * Whether to generate VERP addresses on send. 340 350 * Only applicable when sending via SMTP. 341 351 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path 342 * @type bool 352 * @link http://www.postfix.org/VERP_README.html Postfix VERP info 353 * @type boolean 343 354 */ 344 355 public $do_verp = false; 345 356 346 357 /** 347 358 * Whether to allow sending messages with an empty body. 348 * @type bool 359 * @type boolean 349 360 */ 350 361 public $AllowEmpty = false; 351 362 … … 396 407 * The function that handles the result of the send email action. 397 408 * It is called out by send() for each email sent. 398 409 * 399 * Value can be: 400 * - 'function_name' for function names 401 * - 'Class::Method' for static method calls 402 * - array($object, 'Method') for calling methods on $object 403 * See http://php.net/is_callable manual page for more details. 410 * Value can be any php callable: http://www.php.net/is_callable 404 411 * 405 412 * Parameters: 406 * bool 413 * boolean $result result of the send action 407 414 * string $to email address of the recipient 408 415 * string $cc cc email addresses 409 416 * string $bcc bcc email addresses … … 410 417 * string $subject the subject 411 418 * string $body the email body 412 419 * string $from email address of sender 413 *414 420 * @type string 415 421 */ 416 422 public $action_function = ''; … … 538 544 539 545 /** 540 546 * Whether to throw exceptions for errors. 541 * @type bool 547 * @type boolean 542 548 * @access protected 543 549 */ 544 550 protected $exceptions = false; 545 551 546 552 /** 547 * Error severity: message only, continue processing 553 * Error severity: message only, continue processing. 548 554 */ 549 555 const STOP_MESSAGE = 0; 550 556 551 557 /** 552 * Error severity: message, likely ok to continue processing 558 * Error severity: message, likely ok to continue processing. 553 559 */ 554 560 const STOP_CONTINUE = 1; 555 561 556 562 /** 557 * Error severity: message, plus full stop, critical error reached 563 * Error severity: message, plus full stop, critical error reached. 558 564 */ 559 565 const STOP_CRITICAL = 2; 560 566 561 567 /** 562 * SMTP RFC standard line ending 568 * SMTP RFC standard line ending. 563 569 */ 564 570 const CRLF = "\r\n"; 565 571 566 572 /** 567 * Constructor 568 * @param bool $exceptions Should we throw external exceptions?573 * Constructor. 574 * @param boolean $exceptions Should we throw external exceptions? 569 575 */ 570 576 public function __construct($exceptions = false) 571 577 { … … 593 599 * @param string $header Additional Header(s) 594 600 * @param string $params Params 595 601 * @access private 596 * @return bool 602 * @return boolean 597 603 */ 598 604 private function mailPassthru($to, $subject, $body, $header, $params) 599 605 { 606 //Check overloading of mail function to avoid double-encoding 607 if (ini_get('mbstring.func_overload') & 1) { 608 $subject = $this->secureHeader($subject); 609 } else { 610 $subject = $this->encodeHeader($this->secureHeader($subject)); 611 } 600 612 if (ini_get('safe_mode') || !($this->UseSendmailOptions)) { 601 $r t = @mail($to, $this->encodeHeader($this->secureHeader($subject)), $body, $header);613 $result = @mail($to, $subject, $body, $header); 602 614 } else { 603 $r t = @mail($to, $this->encodeHeader($this->secureHeader($subject)), $body, $header, $params);615 $result = @mail($to, $subject, $body, $header, $params); 604 616 } 605 return $r t;617 return $result; 606 618 } 607 619 608 620 /** 609 621 * Output debugging info via user-defined method. 610 * Only if debug output is enabled.622 * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug). 611 623 * @see PHPMailer::$Debugoutput 612 624 * @see PHPMailer::$SMTPDebug 613 625 * @param string $str … … 614 626 */ 615 627 protected function edebug($str) 616 628 { 617 if ( !$this->SMTPDebug) {629 if ($this->SMTPDebug <= 0) { 618 630 return; 619 631 } 632 if (is_callable($this->Debugoutput)) { 633 call_user_func($this->Debugoutput, $str, $this->SMTPDebug); 634 return; 635 } 620 636 switch ($this->Debugoutput) { 621 637 case 'error_log': 638 //Don't output, just log 622 639 error_log($str); 623 640 break; 624 641 case 'html': 625 //Cleans up output a bit for a better looking display that's HTML-safe 626 echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, $this->CharSet) . "<br>\n"; 642 //Cleans up output a bit for a better looking, HTML-safe output 643 echo htmlentities( 644 preg_replace('/[\r\n]+/', '', $str), 645 ENT_QUOTES, 646 'UTF-8' 647 ) 648 . "<br>\n"; 627 649 break; 628 650 case 'echo': 629 651 default: 630 //Just echoes exactly what was received 631 echo $str; 652 //Normalize line breaks 653 $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); 654 echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( 655 "\n", 656 "\n \t ", 657 trim($str) 658 ) . "\n"; 632 659 } 633 660 } 634 661 635 662 /** 636 663 * Sets message type to HTML or plain. 637 * @param bool $ishtml True for HTML mode.664 * @param boolean $isHtml True for HTML mode. 638 665 * @return void 639 666 */ 640 public function isHTML($is html = true)667 public function isHTML($isHtml = true) 641 668 { 642 if ($is html) {669 if ($isHtml) { 643 670 $this->ContentType = 'text/html'; 644 671 } else { 645 672 $this->ContentType = 'text/plain'; … … 670 697 */ 671 698 public function isSendmail() 672 699 { 673 if (!stristr(ini_get('sendmail_path'), 'sendmail')) { 674 $this->Sendmail = '/var/qmail/bin/sendmail'; 700 $ini_sendmail_path = ini_get('sendmail_path'); 701 702 if (!stristr($ini_sendmail_path, 'sendmail')) { 703 $this->Sendmail = '/usr/sbin/sendmail'; 704 } else { 705 $this->Sendmail = $ini_sendmail_path; 675 706 } 676 707 $this->Mailer = 'sendmail'; 677 708 } … … 682 713 */ 683 714 public function isQmail() 684 715 { 685 if (stristr(ini_get('sendmail_path'), 'qmail')) { 686 $this->Sendmail = '/var/qmail/bin/sendmail'; 716 $ini_sendmail_path = ini_get('sendmail_path'); 717 718 if (!stristr($ini_sendmail_path, 'qmail')) { 719 $this->Sendmail = '/var/qmail/bin/qmail-inject'; 720 } else { 721 $this->Sendmail = $ini_sendmail_path; 687 722 } 688 $this->Mailer = ' sendmail';723 $this->Mailer = 'qmail'; 689 724 } 690 725 691 726 /** … … 692 727 * Add a "To" address. 693 728 * @param string $address 694 729 * @param string $name 695 * @return bool true on success, false if address already used730 * @return boolean true on success, false if address already used 696 731 */ 697 732 public function addAddress($address, $name = '') 698 733 { … … 704 739 * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. 705 740 * @param string $address 706 741 * @param string $name 707 * @return bool true on success, false if address already used742 * @return boolean true on success, false if address already used 708 743 */ 709 744 public function addCC($address, $name = '') 710 745 { … … 716 751 * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. 717 752 * @param string $address 718 753 * @param string $name 719 * @return bool true on success, false if address already used754 * @return boolean true on success, false if address already used 720 755 */ 721 756 public function addBCC($address, $name = '') 722 757 { … … 727 762 * Add a "Reply-to" address. 728 763 * @param string $address 729 764 * @param string $name 730 * @return bool 765 * @return boolean 731 766 */ 732 767 public function addReplyTo($address, $name = '') 733 768 { … … 741 776 * @param string $address The email address to send to 742 777 * @param string $name 743 778 * @throws phpmailerException 744 * @return bool true on success, false if address already used or invalid in some way779 * @return boolean true on success, false if address already used or invalid in some way 745 780 * @access protected 746 781 */ 747 782 protected function addAnAddress($kind, $address, $name = '') … … 748 783 { 749 784 if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) { 750 785 $this->setError($this->lang('Invalid recipient array') . ': ' . $kind); 786 $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind); 751 787 if ($this->exceptions) { 752 788 throw new phpmailerException('Invalid recipient array: ' . $kind); 753 789 } 754 $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind);755 790 return false; 756 791 } 757 792 $address = trim($address); … … 758 793 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 759 794 if (!$this->validateAddress($address)) { 760 795 $this->setError($this->lang('invalid_address') . ': ' . $address); 796 $this->edebug($this->lang('invalid_address') . ': ' . $address); 761 797 if ($this->exceptions) { 762 798 throw new phpmailerException($this->lang('invalid_address') . ': ' . $address); 763 799 } 764 $this->edebug($this->lang('invalid_address') . ': ' . $address);765 800 return false; 766 801 } 767 802 if ($kind != 'Reply-To') { … … 783 818 * Set the From and FromName properties. 784 819 * @param string $address 785 820 * @param string $name 786 * @param bool $auto Whether to also set the Sender address, defaults to true821 * @param boolean $auto Whether to also set the Sender address, defaults to true 787 822 * @throws phpmailerException 788 * @return bool 823 * @return boolean 789 824 */ 790 825 public function setFrom($address, $name = '', $auto = true) 791 826 { … … 793 828 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 794 829 if (!$this->validateAddress($address)) { 795 830 $this->setError($this->lang('invalid_address') . ': ' . $address); 831 $this->edebug($this->lang('invalid_address') . ': ' . $address); 796 832 if ($this->exceptions) { 797 833 throw new phpmailerException($this->lang('invalid_address') . ': ' . $address); 798 834 } 799 $this->edebug($this->lang('invalid_address') . ': ' . $address);800 835 return false; 801 836 } 802 837 $this->From = $address; … … 825 860 * Check that a string looks like an email address. 826 861 * @param string $address The email address to check 827 862 * @param string $patternselect A selector for the validation pattern to use : 828 * 'auto' - pick best one automatically; 829 * 'pcre8' - use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; 830 * 'pcre' - use old PCRE implementation; 831 * 'php' - use PHP built-in FILTER_VALIDATE_EMAIL; faster, less thorough; 832 * 'noregex' - super fast, really dumb. 833 * @return bool 863 * * `auto` Pick strictest one automatically; 864 * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; 865 * * `pcre` Use old PCRE implementation; 866 * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains; 867 * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. 868 * * `noregex` Don't use a regex: super fast, really dumb. 869 * @return boolean 834 870 * @static 835 871 * @access public 836 872 */ 837 873 public static function validateAddress($address, $patternselect = 'auto') 838 874 { 839 if ( $patternselect == 'auto') {840 if (defined(841 'PCRE_VERSION'842 )843 ) { //Check this instead of extension_loaded so it works when that function is disabled844 if (version_compare(PCRE_VERSION, '8.0 ') >= 0) {875 if (!$patternselect or $patternselect == 'auto') { 876 //Check this constant first so it works when extension_loaded() is disabled by safe mode 877 //Constant was added in PHP 5.2.4 878 if (defined('PCRE_VERSION')) { 879 //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2 880 if (version_compare(PCRE_VERSION, '8.0.3') >= 0) { 845 881 $patternselect = 'pcre8'; 846 882 } else { 847 883 $patternselect = 'pcre'; 848 884 } 885 } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) { 886 //Fall back to older PCRE 887 $patternselect = 'pcre'; 849 888 } else { 850 889 //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension 851 890 if (version_compare(PHP_VERSION, '5.2.0') >= 0) { … … 858 897 switch ($patternselect) { 859 898 case 'pcre8': 860 899 /** 861 * Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is 862 * based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to 863 * not allow a@b type valid addresses :( 900 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains. 864 901 * @link http://squiloople.com/2009/12/20/email-address-validation/ 865 902 * @copyright 2009-2010 Michael Rushton 866 903 * Feel free to use and redistribute this code. But please keep this copyright notice. 867 904 */ 868 return (bool )preg_match(905 return (boolean)preg_match( 869 906 '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' . 870 907 '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' . 871 908 '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' . … … 877 914 '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', 878 915 $address 879 916 ); 880 break;881 917 case 'pcre': 882 918 //An older regex that doesn't need a recent PCRE 883 return (bool )preg_match(919 return (boolean)preg_match( 884 920 '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' . 885 921 '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' . 886 922 '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' . … … 893 929 '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', 894 930 $address 895 931 ); 896 break; 897 case 'php': 898 default: 899 return (bool)filter_var($address, FILTER_VALIDATE_EMAIL); 900 break; 932 case 'html5': 933 /** 934 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. 935 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) 936 */ 937 return (boolean)preg_match( 938 '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . 939 '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', 940 $address 941 ); 901 942 case 'noregex': 902 943 //No PCRE! Do something _very_ approximate! 903 944 //Check the address is 3 chars or longer and contains an @ that's not the first or last char … … 904 945 return (strlen($address) >= 3 905 946 and strpos($address, '@') >= 1 906 947 and strpos($address, '@') != strlen($address) - 1); 907 break; 948 case 'php': 949 default: 950 return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL); 908 951 } 909 952 } 910 953 … … 911 954 /** 912 955 * Create a message and send it. 913 956 * Uses the sending method specified by $Mailer. 914 * Returns false on error - Use the ErrorInfo variable to view description of the error.915 957 * @throws phpmailerException 916 * @return bool 958 * @return boolean false on error - See the ErrorInfo property for details of the error. 917 959 */ 918 960 public function send() 919 961 { … … 922 964 return false; 923 965 } 924 966 return $this->postSend(); 925 } catch (phpmailerException $e ) {967 } catch (phpmailerException $exc) { 926 968 $this->mailHeader = ''; 927 $this->setError($e ->getMessage());969 $this->setError($exc->getMessage()); 928 970 if ($this->exceptions) { 929 throw $e ;971 throw $exc; 930 972 } 931 973 return false; 932 974 } … … 935 977 /** 936 978 * Prepare a message for sending. 937 979 * @throws phpmailerException 938 * @return bool 980 * @return boolean 939 981 */ 940 982 public function preSend() 941 983 { 942 984 try { 943 $this->mailHeader = "";985 $this->mailHeader = ''; 944 986 if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { 945 987 throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL); 946 988 } … … 964 1006 // an extra header list which createHeader() doesn't fold in 965 1007 if ($this->Mailer == 'mail') { 966 1008 if (count($this->to) > 0) { 967 $this->mailHeader .= $this->addrAppend( "To", $this->to);1009 $this->mailHeader .= $this->addrAppend('To', $this->to); 968 1010 } else { 969 $this->mailHeader .= $this->headerLine( "To", "undisclosed-recipients:;");1011 $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;'); 970 1012 } 971 1013 $this->mailHeader .= $this->headerLine( 972 1014 'Subject', … … 990 1032 } 991 1033 return true; 992 1034 993 } catch (phpmailerException $e ) {994 $this->setError($e ->getMessage());1035 } catch (phpmailerException $exc) { 1036 $this->setError($exc->getMessage()); 995 1037 if ($this->exceptions) { 996 throw $e ;1038 throw $exc; 997 1039 } 998 1040 return false; 999 1041 } … … 1003 1045 * Actually send a message. 1004 1046 * Send the email via the selected mechanism 1005 1047 * @throws phpmailerException 1006 * @return bool 1048 * @return boolean 1007 1049 */ 1008 1050 public function postSend() 1009 1051 { … … 1011 1053 // Choose the mailer and send through it 1012 1054 switch ($this->Mailer) { 1013 1055 case 'sendmail': 1056 case 'qmail': 1014 1057 return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody); 1015 1058 case 'smtp': 1016 1059 return $this->smtpSend($this->MIMEHeader, $this->MIMEBody); … … 1017 1060 case 'mail': 1018 1061 return $this->mailSend($this->MIMEHeader, $this->MIMEBody); 1019 1062 default: 1063 $sendMethod = $this->Mailer.'Send'; 1064 if (method_exists($this, $sendMethod)) { 1065 return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); 1066 } 1067 1020 1068 return $this->mailSend($this->MIMEHeader, $this->MIMEBody); 1021 1069 } 1022 } catch (phpmailerException $e) { 1023 $this->setError($e->getMessage()); 1070 } catch (phpmailerException $exc) { 1071 $this->setError($exc->getMessage()); 1072 $this->edebug($exc->getMessage()); 1024 1073 if ($this->exceptions) { 1025 throw $e ;1074 throw $exc; 1026 1075 } 1027 $this->edebug($e->getMessage() . "\n");1028 1076 } 1029 1077 return false; 1030 1078 } … … 1036 1084 * @see PHPMailer::$Sendmail 1037 1085 * @throws phpmailerException 1038 1086 * @access protected 1039 * @return bool 1087 * @return boolean 1040 1088 */ 1041 1089 protected function sendmailSend($header, $body) 1042 1090 { 1043 1091 if ($this->Sender != '') { 1044 $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 1092 if ($this->Mailer == 'qmail') { 1093 $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 1094 } else { 1095 $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 1096 } 1045 1097 } else { 1046 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); 1098 if ($this->Mailer == 'qmail') { 1099 $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail)); 1100 } else { 1101 $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); 1102 } 1047 1103 } 1048 1104 if ($this->SingleTo === true) { 1049 foreach ($this->SingleToArray as $ val) {1105 foreach ($this->SingleToArray as $toAddr) { 1050 1106 if (!@$mail = popen($sendmail, 'w')) { 1051 1107 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 1052 1108 } 1053 fputs($mail, "To: " . $val. "\n");1109 fputs($mail, 'To: ' . $toAddr . "\n"); 1054 1110 fputs($mail, $header); 1055 1111 fputs($mail, $body); 1056 1112 $result = pclose($mail); 1057 // implement call back function if it exists 1058 $isSent = ($result == 0) ? 1 : 0; 1059 $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1113 $this->doCallback( 1114 ($result == 0), 1115 array($toAddr), 1116 $this->cc, 1117 $this->bcc, 1118 $this->Subject, 1119 $body, 1120 $this->From 1121 ); 1060 1122 if ($result != 0) { 1061 1123 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 1062 1124 } … … 1068 1130 fputs($mail, $header); 1069 1131 fputs($mail, $body); 1070 1132 $result = pclose($mail); 1071 // implement call back function if it exists 1072 $isSent = ($result == 0) ? 1 : 0; 1073 $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1133 $this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1074 1134 if ($result != 0) { 1075 1135 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 1076 1136 } … … 1085 1145 * @link http://www.php.net/manual/en/book.mail.php 1086 1146 * @throws phpmailerException 1087 1147 * @access protected 1088 * @return bool 1148 * @return boolean 1089 1149 */ 1090 1150 protected function mailSend($header, $body) 1091 1151 { 1092 1152 $toArr = array(); 1093 foreach ($this->to as $t ) {1094 $toArr[] = $this->addrFormat($t );1153 foreach ($this->to as $toaddr) { 1154 $toArr[] = $this->addrFormat($toaddr); 1095 1155 } 1096 1156 $to = implode(', ', $toArr); 1097 1157 1098 1158 if (empty($this->Sender)) { 1099 $params = " ";1159 $params = ' '; 1100 1160 } else { 1101 $params = sprintf( "-f%s", $this->Sender);1161 $params = sprintf('-f%s', $this->Sender); 1102 1162 } 1103 1163 if ($this->Sender != '' and !ini_get('safe_mode')) { 1104 1164 $old_from = ini_get('sendmail_from'); 1105 1165 ini_set('sendmail_from', $this->Sender); 1106 1166 } 1107 $r t = false;1167 $result = false; 1108 1168 if ($this->SingleTo === true && count($toArr) > 1) { 1109 foreach ($toArr as $val) { 1110 $rt = $this->mailPassthru($val, $this->Subject, $body, $header, $params); 1111 // implement call back function if it exists 1112 $isSent = ($rt == 1) ? 1 : 0; 1113 $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1169 foreach ($toArr as $toAddr) { 1170 $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); 1171 $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1114 1172 } 1115 1173 } else { 1116 $rt = $this->mailPassthru($to, $this->Subject, $body, $header, $params); 1117 // implement call back function if it exists 1118 $isSent = ($rt == 1) ? 1 : 0; 1119 $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1174 $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); 1175 $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1120 1176 } 1121 1177 if (isset($old_from)) { 1122 1178 ini_set('sendmail_from', $old_from); 1123 1179 } 1124 if (!$r t) {1180 if (!$result) { 1125 1181 throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); 1126 1182 } 1127 1183 return true; … … 1135 1191 public function getSMTPInstance() 1136 1192 { 1137 1193 if (!is_object($this->smtp)) { 1138 require_once 'class-smtp.php';1139 1194 $this->smtp = new SMTP; 1140 1195 } 1141 1196 return $this->smtp; … … 1151 1206 * @throws phpmailerException 1152 1207 * @uses SMTP 1153 1208 * @access protected 1154 * @return bool 1209 * @return boolean 1155 1210 */ 1156 1211 protected function smtpSend($header, $body) 1157 1212 { … … 1166 1221 throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); 1167 1222 } 1168 1223 1169 // Attempt to send attachall recipients1224 // Attempt to send to all recipients 1170 1225 foreach ($this->to as $to) { 1171 1226 if (!$this->smtp->recipient($to[0])) { 1172 1227 $bad_rcpt[] = $to[0]; 1173 $isSent = 0;1228 $isSent = false; 1174 1229 } else { 1175 $isSent = 1;1230 $isSent = true; 1176 1231 } 1177 $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body, $this->From);1232 $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From); 1178 1233 } 1179 1234 foreach ($this->cc as $cc) { 1180 1235 if (!$this->smtp->recipient($cc[0])) { 1181 1236 $bad_rcpt[] = $cc[0]; 1182 $isSent = 0;1237 $isSent = false; 1183 1238 } else { 1184 $isSent = 1;1239 $isSent = true; 1185 1240 } 1186 $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body, $this->From);1241 $this->doCallback($isSent, array(), array($cc[0]), array(), $this->Subject, $body, $this->From); 1187 1242 } 1188 1243 foreach ($this->bcc as $bcc) { 1189 1244 if (!$this->smtp->recipient($bcc[0])) { 1190 1245 $bad_rcpt[] = $bcc[0]; 1191 $isSent = 0;1246 $isSent = false; 1192 1247 } else { 1193 $isSent = 1;1248 $isSent = true; 1194 1249 } 1195 $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body, $this->From);1250 $this->doCallback($isSent, array(), array(), array($bcc[0]), $this->Subject, $body, $this->From); 1196 1251 } 1197 1252 1198 if (count($bad_rcpt) > 0) { //Create error message for any bad addresses 1199 throw new phpmailerException($this->lang('recipients_failed') . implode(', ', $bad_rcpt)); 1200 } 1201 if (!$this->smtp->data($header . $body)) { 1253 // Only send the DATA command if we have viable recipients 1254 if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) { 1202 1255 throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL); 1203 1256 } 1204 1257 if ($this->SMTPKeepAlive == true) { … … 1207 1260 $this->smtp->quit(); 1208 1261 $this->smtp->close(); 1209 1262 } 1263 if (count($bad_rcpt) > 0) { // Create error message for any bad addresses 1264 throw new phpmailerException( 1265 $this->lang('recipients_failed') . implode(', ', $bad_rcpt), 1266 self::STOP_CONTINUE 1267 ); 1268 } 1210 1269 return true; 1211 1270 } 1212 1271 … … 1217 1276 * @uses SMTP 1218 1277 * @access public 1219 1278 * @throws phpmailerException 1220 * @return bool 1279 * @return boolean 1221 1280 */ 1222 1281 public function smtpConnect($options = array()) 1223 1282 { … … 1225 1284 $this->smtp = $this->getSMTPInstance(); 1226 1285 } 1227 1286 1228 // Already connected?1287 // Already connected? 1229 1288 if ($this->smtp->connected()) { 1230 1289 return true; 1231 1290 } … … 1234 1293 $this->smtp->setDebugLevel($this->SMTPDebug); 1235 1294 $this->smtp->setDebugOutput($this->Debugoutput); 1236 1295 $this->smtp->setVerp($this->do_verp); 1237 $tls = ($this->SMTPSecure == 'tls');1238 $ssl = ($this->SMTPSecure == 'ssl');1239 1296 $hosts = explode(';', $this->Host); 1240 1297 $lastexception = null; 1241 1298 1242 1299 foreach ($hosts as $hostentry) { 1243 1300 $hostinfo = array(); 1244 $host = $hostentry; 1301 if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) { 1302 // Not a valid host entry 1303 continue; 1304 } 1305 // $hostinfo[2]: optional ssl or tls prefix 1306 // $hostinfo[3]: the hostname 1307 // $hostinfo[4]: optional port number 1308 // The host string prefix can temporarily override the current setting for SMTPSecure 1309 // If it's not specified, the default value is used 1310 $prefix = ''; 1311 $tls = ($this->SMTPSecure == 'tls'); 1312 if ($hostinfo[2] == 'ssl' or ($hostinfo[2] == '' and $this->SMTPSecure == 'ssl')) { 1313 $prefix = 'ssl://'; 1314 $tls = false; // Can't have SSL and TLS at once 1315 } elseif ($hostinfo[2] == 'tls') { 1316 $tls = true; 1317 // tls doesn't use a prefix 1318 } 1319 $host = $hostinfo[3]; 1245 1320 $port = $this->Port; 1246 if (preg_match( 1247 '/^(.+):([0-9]+)$/', 1248 $hostentry, 1249 $hostinfo 1250 ) 1251 ) { //If $hostentry contains 'address:port', override default 1252 $host = $hostinfo[1]; 1253 $port = $hostinfo[2]; 1321 $tport = (integer)$hostinfo[4]; 1322 if ($tport > 0 and $tport < 65536) { 1323 $port = $tport; 1254 1324 } 1255 if ($this->smtp->connect( ($ssl ? 'ssl://' : ''). $host, $port, $this->Timeout, $options)) {1325 if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) { 1256 1326 try { 1257 1327 if ($this->Helo) { 1258 1328 $hello = $this->Helo; … … 1265 1335 if (!$this->smtp->startTLS()) { 1266 1336 throw new phpmailerException($this->lang('connect_host')); 1267 1337 } 1268 // We must resend HELO after tls negotiation1338 // We must resend HELO after tls negotiation 1269 1339 $this->smtp->hello($hello); 1270 1340 } 1271 1341 if ($this->SMTPAuth) { … … 1281 1351 } 1282 1352 } 1283 1353 return true; 1284 } catch (phpmailerException $e ) {1285 $lastexception = $e ;1286 // We must have connected, but then failed TLS or Auth, so close connection nicely1354 } catch (phpmailerException $exc) { 1355 $lastexception = $exc; 1356 // We must have connected, but then failed TLS or Auth, so close connection nicely 1287 1357 $this->smtp->quit(); 1288 1358 } 1289 1359 } 1290 1360 } 1291 // If we get here, all connection attempts have failed, so close connection hard1361 // If we get here, all connection attempts have failed, so close connection hard 1292 1362 $this->smtp->close(); 1293 // As we've caught all exceptions, just report whatever the last one was1363 // As we've caught all exceptions, just report whatever the last one was 1294 1364 if ($this->exceptions and !is_null($lastexception)) { 1295 1365 throw $lastexception; 1296 1366 } … … 1317 1387 * The default language is English. 1318 1388 * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") 1319 1389 * @param string $lang_path Path to the language file directory, with trailing separator (slash) 1320 * @return bool 1390 * @return boolean 1321 1391 * @access public 1322 1392 */ 1323 public function setLanguage($langcode = 'en', $lang_path = ' language/')1393 public function setLanguage($langcode = 'en', $lang_path = '') 1324 1394 { 1325 // Define full set of translatable strings1395 // Define full set of translatable strings in English 1326 1396 $PHPMAILER_LANG = array( 1327 1397 'authenticate' => 'SMTP Error: Could not authenticate.', 1328 1398 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', … … 1343 1413 'smtp_error' => 'SMTP server error: ', 1344 1414 'variable_set' => 'Cannot set or reset variable: ' 1345 1415 ); 1346 //Overwrite language-specific strings. 1347 //This way we'll never have missing translations - no more "language string failed to load"! 1348 $l = true; 1349 if ($langcode != 'en') { //There is no English translation file 1350 $l = @include $lang_path . 'phpmailer.lang-' . $langcode . '.php'; 1416 if (empty($lang_path)) { 1417 // Calculate an absolute path so it can work if CWD is not here 1418 $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR; 1351 1419 } 1420 $foundlang = true; 1421 $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php'; 1422 if ($langcode != 'en') { // There is no English translation file 1423 // Make sure language file path is readable 1424 if (!is_readable($lang_file)) { 1425 $foundlang = false; 1426 } else { 1427 // Overwrite language-specific strings. 1428 // This way we'll never have missing translations. 1429 $foundlang = include $lang_file; 1430 } 1431 } 1352 1432 $this->language = $PHPMAILER_LANG; 1353 return ($ l == true); //Returns false if language not found1433 return ($foundlang == true); // Returns false if language not found 1354 1434 } 1355 1435 1356 1436 /** … … 1375 1455 public function addrAppend($type, $addr) 1376 1456 { 1377 1457 $addresses = array(); 1378 foreach ($addr as $a ) {1379 $addresses[] = $this->addrFormat($a );1458 foreach ($addr as $address) { 1459 $addresses[] = $this->addrFormat($address); 1380 1460 } 1381 1461 return $type . ': ' . implode(', ', $addresses) . $this->LE; 1382 1462 } … … 1393 1473 if (empty($addr[1])) { // No name provided 1394 1474 return $this->secureHeader($addr[0]); 1395 1475 } else { 1396 return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . " <". $this->secureHeader(1476 return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( 1397 1477 $addr[0] 1398 ) . ">";1478 ) . '>'; 1399 1479 } 1400 1480 } 1401 1481 … … 1406 1486 * Original written by philippe. 1407 1487 * @param string $message The message to wrap 1408 1488 * @param integer $length The line length to wrap to 1409 * @param bool $qp_mode Whether to run in Quoted-Printable mode1489 * @param boolean $qp_mode Whether to run in Quoted-Printable mode 1410 1490 * @access public 1411 1491 * @return string 1412 1492 */ 1413 1493 public function wrapText($message, $length, $qp_mode = false) 1414 1494 { 1415 $soft_break = ($qp_mode) ? sprintf( " =%s", $this->LE) : $this->LE;1495 $soft_break = ($qp_mode) ? sprintf(' =%s', $this->LE) : $this->LE; 1416 1496 // If utf-8 encoding is used, we will need to make sure we don't 1417 1497 // split multibyte characters when we wrap 1418 $is_utf8 = (strtolower($this->CharSet) == "utf-8");1498 $is_utf8 = (strtolower($this->CharSet) == 'utf-8'); 1419 1499 $lelen = strlen($this->LE); 1420 1500 $crlflen = strlen(self::CRLF); 1421 1501 … … 1438 1518 $len = $space_left; 1439 1519 if ($is_utf8) { 1440 1520 $len = $this->utf8CharBoundary($word, $len); 1441 } elseif (substr($word, $len - 1, 1) == "=") {1521 } elseif (substr($word, $len - 1, 1) == '=') { 1442 1522 $len--; 1443 } elseif (substr($word, $len - 2, 1) == "=") {1523 } elseif (substr($word, $len - 2, 1) == '=') { 1444 1524 $len -= 2; 1445 1525 } 1446 1526 $part = substr($word, 0, $len); 1447 1527 $word = substr($word, $len); 1448 1528 $buf .= ' ' . $part; 1449 $message .= $buf . sprintf( "=%s", self::CRLF);1529 $message .= $buf . sprintf('=%s', self::CRLF); 1450 1530 } else { 1451 1531 $message .= $buf . $soft_break; 1452 1532 } … … 1459 1539 $len = $length; 1460 1540 if ($is_utf8) { 1461 1541 $len = $this->utf8CharBoundary($word, $len); 1462 } elseif (substr($word, $len - 1, 1) == "=") {1542 } elseif (substr($word, $len - 1, 1) == '=') { 1463 1543 $len--; 1464 } elseif (substr($word, $len - 2, 1) == "=") {1544 } elseif (substr($word, $len - 2, 1) == '=') { 1465 1545 $len -= 2; 1466 1546 } 1467 1547 $part = substr($word, 0, $len); … … 1468 1548 $word = substr($word, $len); 1469 1549 1470 1550 if (strlen($word) > 0) { 1471 $message .= $part . sprintf( "=%s", self::CRLF);1551 $message .= $part . sprintf('=%s', self::CRLF); 1472 1552 } else { 1473 1553 $buf = $part; 1474 1554 } … … 1495 1575 * Original written by Colin Brown. 1496 1576 * @access public 1497 1577 * @param string $encodedText utf-8 QP text 1498 * @param int $maxLength find last character boundary prior to this length1499 * @return int 1578 * @param integer $maxLength find last character boundary prior to this length 1579 * @return integer 1500 1580 */ 1501 1581 public function utf8CharBoundary($encodedText, $maxLength) 1502 1582 { … … 1504 1584 $lookBack = 3; 1505 1585 while (!$foundSplitPos) { 1506 1586 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); 1507 $encodedCharPos = strpos($lastChunk, "=");1587 $encodedCharPos = strpos($lastChunk, '='); 1508 1588 if ($encodedCharPos !== false) { 1509 1589 // Found start of encoded character byte within $lookBack block. 1510 1590 // Check the encoded byte value (the 2 chars after the '=') … … 1531 1611 return $maxLength; 1532 1612 } 1533 1613 1534 1535 1614 /** 1536 1615 * Set the body wrapping. 1537 1616 * @access public … … 1572 1651 $this->boundary[3] = 'b3_' . $uniq_id; 1573 1652 1574 1653 if ($this->MessageDate == '') { 1575 $result .= $this->headerLine('Date', self::rfcDate()); 1576 } else { 1577 $result .= $this->headerLine('Date', $this->MessageDate); 1654 $this->MessageDate = self::rfcDate(); 1578 1655 } 1656 $result .= $this->headerLine('Date', $this->MessageDate); 1579 1657 1580 if ($this->ReturnPath) {1581 $result .= $this->headerLine('Return-Path', '<' . trim($this->ReturnPath) . '>');1582 } elseif ($this->Sender == '') {1583 $result .= $this->headerLine('Return-Path', '<' . trim($this->From) . '>');1584 } else {1585 $result .= $this->headerLine('Return-Path', '<' . trim($this->Sender) . '>');1586 }1587 1658 1588 1659 // To be created automatically by mail() 1589 if ($this-> Mailer != 'mail') {1590 if ($this-> SingleTo === true) {1591 foreach ($this->to as $t ) {1592 $this->SingleToArray[] = $this->addrFormat($t );1660 if ($this->SingleTo === true) { 1661 if ($this->Mailer != 'mail') { 1662 foreach ($this->to as $toaddr) { 1663 $this->SingleToArray[] = $this->addrFormat($toaddr); 1593 1664 } 1594 } else { 1595 if (count($this->to) > 0) { 1665 } 1666 } else { 1667 if (count($this->to) > 0) { 1668 if ($this->Mailer != 'mail') { 1596 1669 $result .= $this->addrAppend('To', $this->to); 1597 } elseif (count($this->cc) == 0) {1598 $result .= $this->headerLine('To', 'undisclosed-recipients:;');1599 1670 } 1671 } elseif (count($this->cc) == 0) { 1672 $result .= $this->headerLine('To', 'undisclosed-recipients:;'); 1600 1673 } 1601 1674 } 1602 1675 … … 1608 1681 } 1609 1682 1610 1683 // sendmail and mail() extract Bcc from the header before sending 1611 if ((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { 1684 if (( 1685 $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail' 1686 ) 1687 and count($this->bcc) > 0 1688 ) { 1612 1689 $result .= $this->addrAppend('Bcc', $this->bcc); 1613 1690 } 1614 1691 … … 1624 1701 if ($this->MessageID != '') { 1625 1702 $this->lastMessageID = $this->MessageID; 1626 1703 } else { 1627 $this->lastMessageID = sprintf( "<%s@%s>", $uniq_id, $this->ServerHostname());1704 $this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname()); 1628 1705 } 1629 1706 $result .= $this->HeaderLine('Message-ID', $this->lastMessageID); 1630 1707 $result .= $this->headerLine('X-Priority', $this->Priority); … … 1667 1744 public function getMailMIME() 1668 1745 { 1669 1746 $result = ''; 1747 $ismultipart = true; 1670 1748 switch ($this->message_type) { 1671 1749 case 'inline': 1672 1750 $result .= $this->headerLine('Content-Type', 'multipart/related;'); … … 1687 1765 default: 1688 1766 // Catches case 'plain': and case '': 1689 1767 $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet); 1768 $ismultipart = false; 1690 1769 break; 1691 1770 } 1692 // RFC1341 part 5 says 7bit is assumed if not specified1771 // RFC1341 part 5 says 7bit is assumed if not specified 1693 1772 if ($this->Encoding != '7bit') { 1694 $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); 1773 // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE 1774 if ($ismultipart) { 1775 if ($this->Encoding == '8bit') { 1776 $result .= $this->headerLine('Content-Transfer-Encoding', '8bit'); 1777 } 1778 // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible 1779 } else { 1780 $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); 1781 } 1695 1782 } 1696 1783 1697 1784 if ($this->Mailer != 'mail') { … … 1704 1791 /** 1705 1792 * Returns the whole MIME message. 1706 1793 * Includes complete headers and body. 1707 * Only valid post PreSend().1708 * @see PHPMailer:: PreSend()1794 * Only valid post preSend(). 1795 * @see PHPMailer::preSend() 1709 1796 * @access public 1710 1797 * @return string 1711 1798 */ … … 1732 1819 1733 1820 $this->setWordWrap(); 1734 1821 1822 $bodyEncoding = $this->Encoding; 1823 $bodyCharSet = $this->CharSet; 1824 if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { 1825 $bodyEncoding = '7bit'; 1826 $bodyCharSet = 'us-ascii'; 1827 } 1828 $altBodyEncoding = $this->Encoding; 1829 $altBodyCharSet = $this->CharSet; 1830 if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { 1831 $altBodyEncoding = '7bit'; 1832 $altBodyCharSet = 'us-ascii'; 1833 } 1735 1834 switch ($this->message_type) { 1736 1835 case 'inline': 1737 $body .= $this->getBoundary($this->boundary[1], '', '', '');1738 $body .= $this->encodeString($this->Body, $ this->Encoding);1836 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); 1837 $body .= $this->encodeString($this->Body, $bodyEncoding); 1739 1838 $body .= $this->LE . $this->LE; 1740 1839 $body .= $this->attachAll('inline', $this->boundary[1]); 1741 1840 break; 1742 1841 case 'attach': 1743 $body .= $this->getBoundary($this->boundary[1], '', '', '');1744 $body .= $this->encodeString($this->Body, $ this->Encoding);1842 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); 1843 $body .= $this->encodeString($this->Body, $bodyEncoding); 1745 1844 $body .= $this->LE . $this->LE; 1746 1845 $body .= $this->attachAll('attachment', $this->boundary[1]); 1747 1846 break; … … 1750 1849 $body .= $this->headerLine('Content-Type', 'multipart/related;'); 1751 1850 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1752 1851 $body .= $this->LE; 1753 $body .= $this->getBoundary($this->boundary[2], '', '', '');1754 $body .= $this->encodeString($this->Body, $ this->Encoding);1852 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding); 1853 $body .= $this->encodeString($this->Body, $bodyEncoding); 1755 1854 $body .= $this->LE . $this->LE; 1756 1855 $body .= $this->attachAll('inline', $this->boundary[2]); 1757 1856 $body .= $this->LE; … … 1758 1857 $body .= $this->attachAll('attachment', $this->boundary[1]); 1759 1858 break; 1760 1859 case 'alt': 1761 $body .= $this->getBoundary($this->boundary[1], '', 'text/plain', '');1762 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1860 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1861 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1763 1862 $body .= $this->LE . $this->LE; 1764 $body .= $this->getBoundary($this->boundary[1], '', 'text/html', '');1765 $body .= $this->encodeString($this->Body, $ this->Encoding);1863 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding); 1864 $body .= $this->encodeString($this->Body, $bodyEncoding); 1766 1865 $body .= $this->LE . $this->LE; 1767 1866 if (!empty($this->Ical)) { 1768 1867 $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', ''); … … 1772 1871 $body .= $this->endBoundary($this->boundary[1]); 1773 1872 break; 1774 1873 case 'alt_inline': 1775 $body .= $this->getBoundary($this->boundary[1], '', 'text/plain', '');1776 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1874 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1875 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1777 1876 $body .= $this->LE . $this->LE; 1778 1877 $body .= $this->textLine('--' . $this->boundary[1]); 1779 1878 $body .= $this->headerLine('Content-Type', 'multipart/related;'); 1780 1879 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1781 1880 $body .= $this->LE; 1782 $body .= $this->getBoundary($this->boundary[2], '', 'text/html', '');1783 $body .= $this->encodeString($this->Body, $ this->Encoding);1881 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); 1882 $body .= $this->encodeString($this->Body, $bodyEncoding); 1784 1883 $body .= $this->LE . $this->LE; 1785 1884 $body .= $this->attachAll('inline', $this->boundary[2]); 1786 1885 $body .= $this->LE; … … 1791 1890 $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); 1792 1891 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1793 1892 $body .= $this->LE; 1794 $body .= $this->getBoundary($this->boundary[2], '', 'text/plain', '');1795 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1893 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1894 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1796 1895 $body .= $this->LE . $this->LE; 1797 $body .= $this->getBoundary($this->boundary[2], '', 'text/html', '');1798 $body .= $this->encodeString($this->Body, $ this->Encoding);1896 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); 1897 $body .= $this->encodeString($this->Body, $bodyEncoding); 1799 1898 $body .= $this->LE . $this->LE; 1800 1899 $body .= $this->endBoundary($this->boundary[2]); 1801 1900 $body .= $this->LE; … … 1806 1905 $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); 1807 1906 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1808 1907 $body .= $this->LE; 1809 $body .= $this->getBoundary($this->boundary[2], '', 'text/plain', '');1810 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1908 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1909 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1811 1910 $body .= $this->LE . $this->LE; 1812 1911 $body .= $this->textLine('--' . $this->boundary[2]); 1813 1912 $body .= $this->headerLine('Content-Type', 'multipart/related;'); 1814 1913 $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"'); 1815 1914 $body .= $this->LE; 1816 $body .= $this->getBoundary($this->boundary[3], '', 'text/html', '');1817 $body .= $this->encodeString($this->Body, $ this->Encoding);1915 $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding); 1916 $body .= $this->encodeString($this->Body, $bodyEncoding); 1818 1917 $body .= $this->LE . $this->LE; 1819 1918 $body .= $this->attachAll('inline', $this->boundary[3]); 1820 1919 $body .= $this->LE; … … 1824 1923 break; 1825 1924 default: 1826 1925 // catch case 'plain' and case '' 1827 $body .= $this->encodeString($this->Body, $ this->Encoding);1926 $body .= $this->encodeString($this->Body, $bodyEncoding); 1828 1927 break; 1829 1928 } 1830 1929 … … 1835 1934 if (!defined('PKCS7_TEXT')) { 1836 1935 throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.'); 1837 1936 } 1937 // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1 1838 1938 $file = tempnam(sys_get_temp_dir(), 'mail'); 1839 file_put_contents($file, $body); // TODO check this worked1939 file_put_contents($file, $body); // @TODO check this worked 1840 1940 $signed = tempnam(sys_get_temp_dir(), 'signed'); 1841 1941 if (@openssl_pkcs7_sign( 1842 1942 $file, … … 1854 1954 @unlink($signed); 1855 1955 throw new phpmailerException($this->lang('signing') . openssl_error_string()); 1856 1956 } 1857 } catch (phpmailerException $e ) {1957 } catch (phpmailerException $exc) { 1858 1958 $body = ''; 1859 1959 if ($this->exceptions) { 1860 throw $e ;1960 throw $exc; 1861 1961 } 1862 1962 } 1863 1963 } … … 1886 1986 $encoding = $this->Encoding; 1887 1987 } 1888 1988 $result .= $this->textLine('--' . $boundary); 1889 $result .= sprintf( "Content-Type: %s; charset=%s", $contentType, $charSet);1989 $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet); 1890 1990 $result .= $this->LE; 1891 $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); 1991 // RFC1341 part 5 says 7bit is assumed if not specified 1992 if ($encoding != '7bit') { 1993 $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); 1994 } 1892 1995 $result .= $this->LE; 1893 1996 1894 1997 return $result; … … 1914 2017 */ 1915 2018 protected function setMessageType() 1916 2019 { 1917 $t his->message_type = array();2020 $type = array(); 1918 2021 if ($this->alternativeExists()) { 1919 $t his->message_type[] = "alt";2022 $type[] = 'alt'; 1920 2023 } 1921 2024 if ($this->inlineImageExists()) { 1922 $t his->message_type[] = "inline";2025 $type[] = 'inline'; 1923 2026 } 1924 2027 if ($this->attachmentExists()) { 1925 $t his->message_type[] = "attach";2028 $type[] = 'attach'; 1926 2029 } 1927 $this->message_type = implode( "_", $this->message_type);1928 if ($this->message_type == "") {1929 $this->message_type = "plain";2030 $this->message_type = implode('_', $type); 2031 if ($this->message_type == '') { 2032 $this->message_type = 'plain'; 1930 2033 } 1931 2034 } 1932 2035 … … 1962 2065 * @param string $type File extension (MIME) type. 1963 2066 * @param string $disposition Disposition to use 1964 2067 * @throws phpmailerException 1965 * @return bool 2068 * @return boolean 1966 2069 */ 1967 2070 public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') 1968 2071 { … … 1971 2074 throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE); 1972 2075 } 1973 2076 1974 // If a MIME type is not specified, try to work it out from the file name2077 // If a MIME type is not specified, try to work it out from the file name 1975 2078 if ($type == '') { 1976 2079 $type = self::filenameToType($path); 1977 2080 } … … 1992 2095 7 => 0 1993 2096 ); 1994 2097 1995 } catch (phpmailerException $e) { 1996 $this->setError($e->getMessage()); 2098 } catch (phpmailerException $exc) { 2099 $this->setError($exc->getMessage()); 2100 $this->edebug($exc->getMessage()); 1997 2101 if ($this->exceptions) { 1998 throw $e ;2102 throw $exc; 1999 2103 } 2000 $this->edebug($e->getMessage() . "\n");2001 2104 return false; 2002 2105 } 2003 2106 return true; … … 2056 2159 } 2057 2160 $cidUniq[$cid] = true; 2058 2161 2059 $mime[] = sprintf( "--%s%s", $boundary, $this->LE);2162 $mime[] = sprintf('--%s%s', $boundary, $this->LE); 2060 2163 $mime[] = sprintf( 2061 "Content-Type: %s; name=\"%s\"%s",2164 'Content-Type: %s; name="%s"%s', 2062 2165 $type, 2063 2166 $this->encodeHeader($this->secureHeader($name)), 2064 2167 $this->LE 2065 2168 ); 2066 $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); 2169 // RFC1341 part 5 says 7bit is assumed if not specified 2170 if ($encoding != '7bit') { 2171 $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE); 2172 } 2067 2173 2068 2174 if ($disposition == 'inline') { 2069 $mime[] = sprintf( "Content-ID: <%s>%s", $cid, $this->LE);2175 $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE); 2070 2176 } 2071 2177 2072 2178 // If a filename contains any of these chars, it should be quoted, … … 2074 2180 // Fixes a warning in IETF's msglint MIME checker 2075 2181 // Allow for bypassing the Content-Disposition header totally 2076 2182 if (!(empty($disposition))) { 2077 if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) { 2183 $encoded_name = $this->encodeHeader($this->secureHeader($name)); 2184 if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) { 2078 2185 $mime[] = sprintf( 2079 "Content-Disposition: %s; filename=\"%s\"%s",2186 'Content-Disposition: %s; filename="%s"%s', 2080 2187 $disposition, 2081 $ this->encodeHeader($this->secureHeader($name)),2188 $encoded_name, 2082 2189 $this->LE . $this->LE 2083 2190 ); 2084 2191 } else { 2085 2192 $mime[] = sprintf( 2086 "Content-Disposition: %s; filename=%s%s",2193 'Content-Disposition: %s; filename=%s%s', 2087 2194 $disposition, 2088 $ this->encodeHeader($this->secureHeader($name)),2195 $encoded_name, 2089 2196 $this->LE . $this->LE 2090 2197 ); 2091 2198 } … … 2110 2217 } 2111 2218 } 2112 2219 2113 $mime[] = sprintf( "--%s--%s", $boundary, $this->LE);2220 $mime[] = sprintf('--%s--%s', $boundary, $this->LE); 2114 2221 2115 return implode( "", $mime);2222 return implode('', $mime); 2116 2223 } 2117 2224 2118 2225 /** … … 2134 2241 $magic_quotes = get_magic_quotes_runtime(); 2135 2242 if ($magic_quotes) { 2136 2243 if (version_compare(PHP_VERSION, '5.3.0', '<')) { 2137 set_magic_quotes_runtime( 0);2244 set_magic_quotes_runtime(false); 2138 2245 } else { 2246 //Doesn't exist in PHP 5.4, but we don't need to check because 2247 //get_magic_quotes_runtime always returns false in 5.4+ 2248 //so it will never get here 2139 2249 ini_set('magic_quotes_runtime', 0); 2140 2250 } 2141 2251 } … … 2145 2255 if (version_compare(PHP_VERSION, '5.3.0', '<')) { 2146 2256 set_magic_quotes_runtime($magic_quotes); 2147 2257 } else { 2148 ini_set('magic_quotes_runtime', $magic_quotes);2258 ini_set('magic_quotes_runtime', ($magic_quotes?'1':'0')); 2149 2259 } 2150 2260 } 2151 2261 return $file_buffer; 2152 } catch (Exception $e ) {2153 $this->setError($e ->getMessage());2262 } catch (Exception $exc) { 2263 $this->setError($exc->getMessage()); 2154 2264 return ''; 2155 2265 } 2156 2266 } … … 2173 2283 case '7bit': 2174 2284 case '8bit': 2175 2285 $encoded = $this->fixEOL($str); 2176 // Make sure it ends with a line break2286 // Make sure it ends with a line break 2177 2287 if (substr($encoded, -(strlen($this->LE))) != $this->LE) { 2178 2288 $encoded .= $this->LE; 2179 2289 } … … 2201 2311 */ 2202 2312 public function encodeHeader($str, $position = 'text') 2203 2313 { 2204 $ x= 0;2314 $matchcount = 0; 2205 2315 switch (strtolower($position)) { 2206 2316 case 'phrase': 2207 2317 if (!preg_match('/[\200-\377]/', $str)) { 2208 // Can't use addslashes as we don't know what value hasmagic_quotes_sybase2318 // Can't use addslashes as we don't know the value of magic_quotes_sybase 2209 2319 $encoded = addcslashes($str, "\0..\37\177\\\""); 2210 2320 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { 2211 2321 return ($encoded); … … 2213 2323 return ("\"$encoded\""); 2214 2324 } 2215 2325 } 2216 $ x= preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);2326 $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); 2217 2327 break; 2218 2328 /** @noinspection PhpMissingBreakStatementInspection */ 2219 2329 case 'comment': 2220 $ x= preg_match_all('/[()"]/', $str, $matches);2330 $matchcount = preg_match_all('/[()"]/', $str, $matches); 2221 2331 // Intentional fall-through 2222 2332 case 'text': 2223 2333 default: 2224 $ x+= preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);2334 $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); 2225 2335 break; 2226 2336 } 2227 2337 2228 if ($ x == 0) { //There are no chars that need encoding2338 if ($matchcount == 0) { // There are no chars that need encoding 2229 2339 return ($str); 2230 2340 } 2231 2341 2232 2342 $maxlen = 75 - 7 - strlen($this->CharSet); 2233 2343 // Try to select the encoding which should produce the shortest output 2234 if ($ x> strlen($str) / 3) {2235 // More than a third of the content will need encoding, so B encoding will be most efficient2344 if ($matchcount > strlen($str) / 3) { 2345 // More than a third of the content will need encoding, so B encoding will be most efficient 2236 2346 $encoding = 'B'; 2237 2347 if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) { 2238 2348 // Use a custom function which correctly encodes and wraps long … … 2250 2360 $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded)); 2251 2361 } 2252 2362 2253 $encoded = preg_replace('/^(.*)$/m', " =?". $this->CharSet . "?$encoding?\\1?=", $encoded);2363 $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded); 2254 2364 $encoded = trim(str_replace("\n", $this->LE, $encoded)); 2255 2365 2256 2366 return $encoded; … … 2260 2370 * Check if a string contains multi-byte characters. 2261 2371 * @access public 2262 2372 * @param string $str multi-byte text to wrap encode 2263 * @return bool 2373 * @return boolean 2264 2374 */ 2265 2375 public function hasMultiBytes($str) 2266 2376 { … … 2272 2382 } 2273 2383 2274 2384 /** 2385 * Does a string contain any 8-bit chars (in any charset)? 2386 * @param string $text 2387 * @return boolean 2388 */ 2389 public function has8bitChars($text) 2390 { 2391 return (boolean)preg_match('/[\x80-\xFF]/', $text); 2392 } 2393 2394 /** 2275 2395 * Encode and wrap long multibyte strings for mail headers 2276 2396 * without breaking lines within a character. 2277 * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php 2397 * Adapted from a function by paravoid 2398 * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 2278 2399 * @access public 2279 2400 * @param string $str multi-byte text to wrap encode 2280 * @param string $l fstring to use as linefeed/end-of-line2401 * @param string $linebreak string to use as linefeed/end-of-line 2281 2402 * @return string 2282 2403 */ 2283 public function base64EncodeWrapMB($str, $l f= null)2404 public function base64EncodeWrapMB($str, $linebreak = null) 2284 2405 { 2285 $start = "=?" . $this->CharSet . "?B?";2286 $end = "?=";2287 $encoded = "";2288 if ($l f=== null) {2289 $l f= $this->LE;2406 $start = '=?' . $this->CharSet . '?B?'; 2407 $end = '?='; 2408 $encoded = ''; 2409 if ($linebreak === null) { 2410 $linebreak = $this->LE; 2290 2411 } 2291 2412 2292 2413 $mb_length = mb_strlen($str, $this->CharSet); … … 2305 2426 $chunk = base64_encode($chunk); 2306 2427 $lookBack++; 2307 2428 } while (strlen($chunk) > $length); 2308 $encoded .= $chunk . $l f;2429 $encoded .= $chunk . $linebreak; 2309 2430 } 2310 2431 2311 2432 // Chomp the last linefeed 2312 $encoded = substr($encoded, 0, -strlen($l f));2433 $encoded = substr($encoded, 0, -strlen($linebreak)); 2313 2434 return $encoded; 2314 2435 } 2315 2436 … … 2320 2441 * @param string $string The text to encode 2321 2442 * @param integer $line_max Number of chars allowed on a line before wrapping 2322 2443 * @return string 2323 * @link PHP version adapted from http://www.php.net/manual/en/function.quoted-printable-decode.php#894172444 * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment 2324 2445 */ 2325 2446 public function encodeQP($string, $line_max = 76) 2326 2447 { 2327 if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3)2328 return quoted_printable_encode($string);2448 if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3) 2449 return $this->fixEOL(quoted_printable_encode($string)); 2329 2450 } 2330 // Fall back to a pure PHP implementation2451 // Fall back to a pure PHP implementation 2331 2452 $string = str_replace( 2332 2453 array('%20', '%0D%0A.', '%0D%0A', '%'), 2333 2454 array(' ', "\r\n=2E", "\r\n", '='), … … 2334 2455 rawurlencode($string) 2335 2456 ); 2336 2457 $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); 2337 return $ string;2458 return $this->fixEOL($string); 2338 2459 } 2339 2460 2340 2461 /** … … 2343 2464 * @access public 2344 2465 * @param string $string 2345 2466 * @param integer $line_max 2346 * @param bool $space_conv2467 * @param boolean $space_conv 2347 2468 * @return string 2348 2469 * @deprecated Use encodeQP instead. 2349 2470 */ … … 2365 2486 */ 2366 2487 public function encodeQ($str, $position = 'text') 2367 2488 { 2368 // There should not be any EOL in the string2489 // There should not be any EOL in the string 2369 2490 $pattern = ''; 2370 2491 $encoded = str_replace(array("\r", "\n"), '', $str); 2371 2492 switch (strtolower($position)) { 2372 2493 case 'phrase': 2373 // RFC 2047 section 5.32494 // RFC 2047 section 5.3 2374 2495 $pattern = '^A-Za-z0-9!*+\/ -'; 2375 2496 break; 2376 2497 /** @noinspection PhpMissingBreakStatementInspection */ 2377 2498 case 'comment': 2378 // RFC 2047 section 5.22499 // RFC 2047 section 5.2 2379 2500 $pattern = '\(\)"'; 2380 // intentional fall-through2381 // for this reason we build the $pattern without including delimiters and []2501 // intentional fall-through 2502 // for this reason we build the $pattern without including delimiters and [] 2382 2503 case 'text': 2383 2504 default: 2384 // RFC 2047 section 5.12385 // Replace every high ascii, control, =, ? and _ characters2505 // RFC 2047 section 5.1 2506 // Replace every high ascii, control, =, ? and _ characters 2386 2507 $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern; 2387 2508 break; 2388 2509 } 2389 2510 $matches = array(); 2390 2511 if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { 2391 // If the string contains an '=', make sure it's the first thing we replace2392 // so as to avoid double-encoding2393 $ s= array_search('=', $matches[0]);2394 if ($ s!== false) {2395 unset($matches[0][$ s]);2512 // If the string contains an '=', make sure it's the first thing we replace 2513 // so as to avoid double-encoding 2514 $eqkey = array_search('=', $matches[0]); 2515 if ($eqkey !== false) { 2516 unset($matches[0][$eqkey]); 2396 2517 array_unshift($matches[0], '='); 2397 2518 } 2398 2519 foreach (array_unique($matches[0]) as $char) { … … 2399 2520 $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); 2400 2521 } 2401 2522 } 2402 // Replace every spaces to _ (more readable than =20)2523 // Replace every spaces to _ (more readable than =20) 2403 2524 return str_replace(' ', '_', $encoded); 2404 2525 } 2405 2526 … … 2422 2543 $type = '', 2423 2544 $disposition = 'attachment' 2424 2545 ) { 2425 // If a MIME type is not specified, try to work it out from the file name2546 // If a MIME type is not specified, try to work it out from the file name 2426 2547 if ($type == '') { 2427 2548 $type = self::filenameToType($filename); 2428 2549 } … … 2453 2574 * @param string $encoding File encoding (see $Encoding). 2454 2575 * @param string $type File MIME type. 2455 2576 * @param string $disposition Disposition to use 2456 * @return bool True on successfully adding an attachment2577 * @return boolean True on successfully adding an attachment 2457 2578 */ 2458 2579 public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') 2459 2580 { … … 2462 2583 return false; 2463 2584 } 2464 2585 2465 // If a MIME type is not specified, try to work it out from the file name2586 // If a MIME type is not specified, try to work it out from the file name 2466 2587 if ($type == '') { 2467 2588 $type = self::filenameToType($path); 2468 2589 } … … 2498 2619 * @param string $encoding File encoding (see $Encoding). 2499 2620 * @param string $type MIME type. 2500 2621 * @param string $disposition Disposition to use 2501 * @return bool True on successfully adding an attachment2622 * @return boolean True on successfully adding an attachment 2502 2623 */ 2503 2624 public function addStringEmbeddedImage( 2504 2625 $string, … … 2508 2629 $type = '', 2509 2630 $disposition = 'inline' 2510 2631 ) { 2511 // If a MIME type is not specified, try to work it out from the name2632 // If a MIME type is not specified, try to work it out from the name 2512 2633 if ($type == '') { 2513 2634 $type = self::filenameToType($name); 2514 2635 } … … 2530 2651 /** 2531 2652 * Check if an inline attachment is present. 2532 2653 * @access public 2533 * @return bool 2654 * @return boolean 2534 2655 */ 2535 2656 public function inlineImageExists() 2536 2657 { … … 2544 2665 2545 2666 /** 2546 2667 * Check if an attachment (non-inline) is present. 2547 * @return bool 2668 * @return boolean 2548 2669 */ 2549 2670 public function attachmentExists() 2550 2671 { … … 2558 2679 2559 2680 /** 2560 2681 * Check if this message has an alternative body set. 2561 * @return bool 2682 * @return boolean 2562 2683 */ 2563 2684 public function alternativeExists() 2564 2685 { … … 2666 2787 */ 2667 2788 public static function rfcDate() 2668 2789 { 2669 // Set the time zone to whatever the default is to avoid 500 errors2670 // Will default to UTC if it's not set properly in php.ini2790 // Set the time zone to whatever the default is to avoid 500 errors 2791 // Will default to UTC if it's not set properly in php.ini 2671 2792 date_default_timezone_set(@date_default_timezone_get()); 2672 2793 return date('D, j M Y H:i:s O'); 2673 2794 } … … 2680 2801 */ 2681 2802 protected function serverHostname() 2682 2803 { 2804 $result = 'localhost.localdomain'; 2683 2805 if (!empty($this->Hostname)) { 2684 2806 $result = $this->Hostname; 2685 } elseif (isset($_SERVER ['SERVER_NAME'])) {2807 } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { 2686 2808 $result = $_SERVER['SERVER_NAME']; 2687 } else { 2688 $result = 'localhost.localdomain'; 2809 } elseif (function_exists('gethostname') && gethostname() !== false) { 2810 $result = gethostname(); 2811 } elseif (php_uname('n') !== false) { 2812 $result = php_uname('n'); 2689 2813 } 2690 2691 2814 return $result; 2692 2815 } 2693 2816 … … 2713 2836 /** 2714 2837 * Check if an error occurred. 2715 2838 * @access public 2716 * @return bool True if an error did occur.2839 * @return boolean True if an error did occur. 2717 2840 */ 2718 2841 public function isError() 2719 2842 { … … 2765 2888 * @access public 2766 2889 * @param string $message HTML message string 2767 2890 * @param string $basedir baseline directory for path 2768 * @param bool $advanced Whether to use the advanced HTML to text converter2891 * @param boolean $advanced Whether to use the advanced HTML to text converter 2769 2892 * @return string $message 2770 2893 */ 2771 2894 public function msgHTML($message, $basedir = '', $advanced = false) 2772 2895 { 2773 preg_match_all( "/(src|background)=[\"'](.*)[\"']/Ui", $message, $images);2896 preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); 2774 2897 if (isset($images[2])) { 2775 foreach ($images[2] as $i => $url) { 2776 // do not change urls for absolute images (thanks to corvuscorax) 2777 if (!preg_match('#^[A-z]+://#', $url)) { 2898 foreach ($images[2] as $imgindex => $url) { 2899 // Convert data URIs into embedded images 2900 if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { 2901 $data = substr($url, strpos($url, ',')); 2902 if ($match[2]) { 2903 $data = base64_decode($data); 2904 } else { 2905 $data = rawurldecode($data); 2906 } 2907 $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 2908 if ($this->addStringEmbeddedImage($data, $cid, '', 'base64', $match[1])) { 2909 $message = preg_replace( 2910 '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', 2911 $images[1][$imgindex] . '="cid:' . $cid . '"', 2912 $message 2913 ); 2914 } 2915 } elseif (!preg_match('#^[A-z]+://#', $url)) { 2916 // Do not change urls for absolute images (thanks to corvuscorax) 2778 2917 $filename = basename($url); 2779 2918 $directory = dirname($url); 2780 2919 if ($directory == '.') { 2781 2920 $directory = ''; 2782 2921 } 2783 $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 22922 $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 2784 2923 if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { 2785 2924 $basedir .= '/'; 2786 2925 } … … 2796 2935 ) 2797 2936 ) { 2798 2937 $message = preg_replace( 2799 "/" . $images[1][$i] . "=[\"']" . preg_quote($url, '/') . "[\"']/Ui",2800 $images[1][$i ] . "=\"cid:" . $cid . "\"",2938 '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', 2939 $images[1][$imgindex] . '="cid:' . $cid . '"', 2801 2940 $message 2802 2941 ); 2803 2942 } … … 2805 2944 } 2806 2945 } 2807 2946 $this->isHTML(true); 2947 // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better 2948 $this->Body = $this->normalizeBreaks($message); 2949 $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); 2808 2950 if (empty($this->AltBody)) { 2809 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; 2951 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . 2952 self::CRLF . self::CRLF; 2810 2953 } 2811 //Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better2812 $this->Body = $this->normalizeBreaks($message);2813 $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));2814 2954 return $this->Body; 2815 2955 } 2816 2956 … … 2817 2957 /** 2818 2958 * Convert an HTML string into plain text. 2819 2959 * @param string $html The HTML text to convert 2820 * @param bool $advanced Should this use the more complex html2text converter or just a simple one?2960 * @param boolean $advanced Should this use the more complex html2text converter or just a simple one? 2821 2961 * @return string 2822 2962 */ 2823 2963 public function html2text($html, $advanced = false) … … 2824 2964 { 2825 2965 if ($advanced) { 2826 2966 require_once 'extras/class.html2text.php'; 2827 $h = new html2text($html);2828 return $h ->get_text();2967 $htmlconverter = new html2text($html); 2968 return $htmlconverter->get_text(); 2829 2969 } 2830 2970 return html_entity_decode( 2831 2971 trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), … … 2920 3060 'txt' => 'text/plain', 2921 3061 'rtx' => 'text/richtext', 2922 3062 'rtf' => 'text/rtf', 3063 'vcf' => 'text/vcard', 3064 'vcard' => 'text/vcard', 2923 3065 'xml' => 'text/xml', 2924 3066 'xsl' => 'text/xml', 2925 3067 'mpeg' => 'video/mpeg', … … 2943 3085 */ 2944 3086 public static function filenameToType($filename) 2945 3087 { 2946 // In case the path is a URL, strip any query string before getting extension3088 // In case the path is a URL, strip any query string before getting extension 2947 3089 $qpos = strpos($filename, '?'); 2948 3090 if ($qpos !== false) { 2949 3091 $filename = substr($filename, 0, $qpos); … … 2966 3108 public static function mb_pathinfo($path, $options = null) 2967 3109 { 2968 3110 $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); 2969 $m = array(); 2970 preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m); 2971 if (array_key_exists(1, $m)) { 2972 $ret['dirname'] = $m[1]; 3111 $pathinfo = array(); 3112 if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) { 3113 if (array_key_exists(1, $pathinfo)) { 3114 $ret['dirname'] = $pathinfo[1]; 3115 } 3116 if (array_key_exists(2, $pathinfo)) { 3117 $ret['basename'] = $pathinfo[2]; 3118 } 3119 if (array_key_exists(5, $pathinfo)) { 3120 $ret['extension'] = $pathinfo[5]; 3121 } 3122 if (array_key_exists(3, $pathinfo)) { 3123 $ret['filename'] = $pathinfo[3]; 3124 } 2973 3125 } 2974 if (array_key_exists(2, $m)) {2975 $ret['basename'] = $m[2];2976 }2977 if (array_key_exists(5, $m)) {2978 $ret['extension'] = $m[5];2979 }2980 if (array_key_exists(3, $m)) {2981 $ret['filename'] = $m[3];2982 }2983 3126 switch ($options) { 2984 3127 case PATHINFO_DIRNAME: 2985 3128 case 'dirname': 2986 3129 return $ret['dirname']; 2987 break;2988 3130 case PATHINFO_BASENAME: 2989 3131 case 'basename': 2990 3132 return $ret['basename']; 2991 break;2992 3133 case PATHINFO_EXTENSION: 2993 3134 case 'extension': 2994 3135 return $ret['extension']; 2995 break;2996 3136 case PATHINFO_FILENAME: 2997 3137 case 'filename': 2998 3138 return $ret['filename']; 2999 break;3000 3139 default: 3001 3140 return $ret; 3002 3141 } … … 3013 3152 * @param mixed $value 3014 3153 * NOTE: will not work with arrays, there are no arrays to set/reset 3015 3154 * @throws phpmailerException 3016 * @return bool 3017 * @ todoShould this not be using __set() magic function?3155 * @return boolean 3156 * @TODO Should this not be using __set() magic function? 3018 3157 */ 3019 3158 public function set($name, $value = '') 3020 3159 { … … 3024 3163 } else { 3025 3164 throw new phpmailerException($this->lang('variable_set') . $name, self::STOP_CRITICAL); 3026 3165 } 3027 } catch (Exception $e ) {3028 $this->setError($e ->getMessage());3029 if ($e ->getCode() == self::STOP_CRITICAL) {3166 } catch (Exception $exc) { 3167 $this->setError($exc->getMessage()); 3168 if ($exc->getCode() == self::STOP_CRITICAL) { 3030 3169 return false; 3031 3170 } 3032 3171 } … … 3061 3200 3062 3201 3063 3202 /** 3064 * Set the p rivate key fileand password for S/MIME signing.3203 * Set the public and private key files and password for S/MIME signing. 3065 3204 * @access public 3066 3205 * @param string $cert_filename 3067 3206 * @param string $key_filename … … 3088 3227 if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { 3089 3228 $line .= $txt[$i]; 3090 3229 } else { 3091 $line .= "=" . sprintf("%02X", $ord);3230 $line .= '=' . sprintf('%02X', $ord); 3092 3231 } 3093 3232 } 3094 3233 return $line; … … 3097 3236 /** 3098 3237 * Generate a DKIM signature. 3099 3238 * @access public 3100 * @param string $s 3239 * @param string $signHeader 3101 3240 * @throws phpmailerException 3102 3241 * @return string 3103 3242 */ 3104 public function DKIM_Sign($s )3243 public function DKIM_Sign($signHeader) 3105 3244 { 3106 3245 if (!defined('PKCS7_TEXT')) { 3107 3246 if ($this->exceptions) { 3108 throw new phpmailerException($this->lang( "signing") . ' OpenSSL extension missing.');3247 throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.'); 3109 3248 } 3110 3249 return ''; 3111 3250 } … … 3115 3254 } else { 3116 3255 $privKey = $privKeyStr; 3117 3256 } 3118 if (openssl_sign($s , $signature, $privKey)) {3257 if (openssl_sign($signHeader, $signature, $privKey)) { 3119 3258 return base64_encode($signature); 3120 3259 } 3121 3260 return ''; … … 3124 3263 /** 3125 3264 * Generate a DKIM canonicalization header. 3126 3265 * @access public 3127 * @param string $s Header3266 * @param string $signHeader Header 3128 3267 * @return string 3129 3268 */ 3130 public function DKIM_HeaderC($s )3269 public function DKIM_HeaderC($signHeader) 3131 3270 { 3132 $s = preg_replace("/\r\n\s+/", " ", $s);3133 $lines = explode("\r\n", $s );3271 $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader); 3272 $lines = explode("\r\n", $signHeader); 3134 3273 foreach ($lines as $key => $line) { 3135 list($heading, $value) = explode( ":", $line, 2);3274 list($heading, $value) = explode(':', $line, 2); 3136 3275 $heading = strtolower($heading); 3137 $value = preg_replace( "/\s+/", " ", $value); // Compress useless spaces3138 $lines[$key] = $heading . ":". trim($value); // Don't forget to remove WSP around the value3276 $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces 3277 $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value 3139 3278 } 3140 $s = implode("\r\n", $lines);3141 return $s ;3279 $signHeader = implode("\r\n", $lines); 3280 return $signHeader; 3142 3281 } 3143 3282 3144 3283 /** … … 3205 3344 ); // Copied header fields (dkim-quoted-printable) 3206 3345 $body = $this->DKIM_BodyC($body); 3207 3346 $DKIMlen = strlen($body); // Length of body 3208 $DKIMb64 = base64_encode(pack( "H*", sha1($body))); // Base64 of packed binary SHA-1 hash of body3209 $ident = ($this->DKIM_identity == '') ? '' : " i=" . $this->DKIM_identity . ";";3210 $dkimhdrs = "DKIM-Signature: v=1; a=".3211 $DKIMsignatureType . "; q=".3212 $DKIMquery . "; l=".3213 $DKIMlen . "; s=".3347 $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body 3348 $ident = ($this->DKIM_identity == '') ? '' : ' i=' . $this->DKIM_identity . ';'; 3349 $dkimhdrs = 'DKIM-Signature: v=1; a=' . 3350 $DKIMsignatureType . '; q=' . 3351 $DKIMquery . '; l=' . 3352 $DKIMlen . '; s=' . 3214 3353 $this->DKIM_selector . 3215 3354 ";\r\n" . 3216 "\tt=" . $DKIMtime . "; c=". $DKIMcanonicalization . ";\r\n" .3355 "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . 3217 3356 "\th=From:To:Subject;\r\n" . 3218 "\td=" . $this->DKIM_domain . ";". $ident . "\r\n" .3357 "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . 3219 3358 "\tz=$from\r\n" . 3220 3359 "\t|$to\r\n" . 3221 3360 "\t|$subject;\r\n" . … … 3229 3368 } 3230 3369 3231 3370 /** 3371 * Allows for public read access to 'to' property. 3372 * @access public 3373 * @return array 3374 */ 3375 public function getToAddresses() 3376 { 3377 return $this->to; 3378 } 3379 3380 /** 3381 * Allows for public read access to 'cc' property. 3382 * @access public 3383 * @return array 3384 */ 3385 public function getCcAddresses() 3386 { 3387 return $this->cc; 3388 } 3389 3390 /** 3391 * Allows for public read access to 'bcc' property. 3392 * @access public 3393 * @return array 3394 */ 3395 public function getBccAddresses() 3396 { 3397 return $this->bcc; 3398 } 3399 3400 /** 3401 * Allows for public read access to 'ReplyTo' property. 3402 * @access public 3403 * @return array 3404 */ 3405 public function getReplyToAddresses() 3406 { 3407 return $this->ReplyTo; 3408 } 3409 3410 /** 3411 * Allows for public read access to 'all_recipients' property. 3412 * @access public 3413 * @return array 3414 */ 3415 public function getAllRecipientAddresses() 3416 { 3417 return $this->all_recipients; 3418 } 3419 3420 /** 3232 3421 * Perform a callback. 3233 * @param bool $isSent3234 * @param string$to3235 * @param string$cc3236 * @param string$bcc3422 * @param boolean $isSent 3423 * @param array $to 3424 * @param array $cc 3425 * @param array $bcc 3237 3426 * @param string $subject 3238 3427 * @param string $body 3239 3428 * @param string $from 3240 3429 */ 3241 protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null)3430 protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) 3242 3431 { 3243 3432 if (!empty($this->action_function) && is_callable($this->action_function)) { 3244 3433 $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);