"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "mrbs-1.9.4/web/lib/PHPMailer/src/PHPMailer.php" between
mrbs-1.9.4.tar.gz and mrbs-1.10.0.tar.gz

About: MRBS is a web application for booking meeting rooms or other resources (using PHP and MySQL/pgsql).

PHPMailer.php  (mrbs-1.9.4):PHPMailer.php  (mrbs-1.10.0)
skipping to change at line 106 skipping to change at line 106
* *
* @var string * @var string
*/ */
public $ErrorInfo = ''; public $ErrorInfo = '';
/** /**
* The From email address for the message. * The From email address for the message.
* *
* @var string * @var string
*/ */
public $From = 'root@localhost'; public $From = '';
/** /**
* The From name of the message. * The From name of the message.
* *
* @var string * @var string
*/ */
public $FromName = 'Root User'; public $FromName = '';
/** /**
* The envelope sender of the message. * The envelope sender of the message.
* This will usually be turned into a Return-Path header by the receiver, * This will usually be turned into a Return-Path header by the receiver,
* and is the address that bounces will be sent to. * and is the address that bounces will be sent to.
* If not empty, will be passed via `-f` to sendmail or as the 'MAIL FROM' v alue over SMTP. * If not empty, will be passed via `-f` to sendmail or as the 'MAIL FROM' v alue over SMTP.
* *
* @var string * @var string
*/ */
public $Sender = ''; public $Sender = '';
skipping to change at line 431 skipping to change at line 431
* $mail->Debugoutput = new myPsr3Logger; * $mail->Debugoutput = new myPsr3Logger;
* ``` * ```
* *
* @see SMTP::$Debugoutput * @see SMTP::$Debugoutput
* *
* @var string|callable|\Psr\Log\LoggerInterface * @var string|callable|\Psr\Log\LoggerInterface
*/ */
public $Debugoutput = 'echo'; public $Debugoutput = 'echo';
/** /**
* Whether to keep SMTP connection open after each message. * Whether to keep the SMTP connection open after each message.
* If this is set to true then to close the connection * If this is set to true then the connection will remain open after a send,
* requires an explicit call to smtpClose(). * and closing the connection will require an explicit call to smtpClose().
* It's a good idea to use this if you are sending multiple messages as it r
educes overhead.
* See the mailing list example for how to use it.
* *
* @var bool * @var bool
*/ */
public $SMTPKeepAlive = false; public $SMTPKeepAlive = false;
/** /**
* Whether to split multiple to addresses into multiple messages * Whether to split multiple to addresses into multiple messages
* or send them all in one message. * or send them all in one message.
* Only supported in `mail` and `sendmail` transports, not in SMTP. * Only supported in `mail` and `sendmail` transports, not in SMTP.
* *
skipping to change at line 690 skipping to change at line 692
protected $message_type = ''; protected $message_type = '';
/** /**
* The array of MIME boundary strings. * The array of MIME boundary strings.
* *
* @var array * @var array
*/ */
protected $boundary = []; protected $boundary = [];
/** /**
* The array of available languages. * The array of available text strings for the current language.
* *
* @var array * @var array
*/ */
protected $language = []; protected $language = [];
/** /**
* The number of errors encountered. * The number of errors encountered.
* *
* @var int * @var int
*/ */
skipping to change at line 751 skipping to change at line 753
* *
* @var string * @var string
*/ */
protected $uniqueid = ''; protected $uniqueid = '';
/** /**
* The PHPMailer Version number. * The PHPMailer Version number.
* *
* @var string * @var string
*/ */
const VERSION = '6.4.1'; const VERSION = '6.5.3';
/** /**
* Error severity: message only, continue processing. * Error severity: message only, continue processing.
* *
* @var int * @var int
*/ */
const STOP_MESSAGE = 0; const STOP_MESSAGE = 0;
/** /**
* Error severity: message, likely ok to continue processing. * Error severity: message, likely ok to continue processing.
skipping to change at line 1189 skipping to change at line 1191
* Uses the imap_rfc822_parse_adrlist function if the IMAP extension is avai lable. * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is avai lable.
* Note that quotes in the name part are removed. * Note that quotes in the name part are removed.
* *
* @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822. php A more careful implementation * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822. php A more careful implementation
* *
* @param string $addrstr The address list string * @param string $addrstr The address list string
* @param bool $useimap Whether to use the IMAP extension to parse the lis t * @param bool $useimap Whether to use the IMAP extension to parse the lis t
* *
* @return array * @return array
*/ */
public static function parseAddresses($addrstr, $useimap = true) public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
{ {
$addresses = []; $addresses = [];
if ($useimap && function_exists('imap_rfc822_parse_adrlist')) { if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
//Use this built-in parser if it's available //Use this built-in parser if it's available
$list = imap_rfc822_parse_adrlist($addrstr, ''); $list = imap_rfc822_parse_adrlist($addrstr, '');
// Clear any potential IMAP errors to get rid of notices being throw
n at end of script.
imap_errors();
foreach ($list as $address) { foreach ($list as $address) {
if ( if (
('.SYNTAX-ERROR.' !== $address->host) && static::validateAdd '.SYNTAX-ERROR.' !== $address->host &&
ress( static::validateAddress($address->mailbox . '@' . $address->
$address->mailbox . '@' . $address->host host)
)
) { ) {
//Decode the name part if it's present and encoded //Decode the name part if it's present and encoded
if ( if (
property_exists($address, 'personal') && property_exists($address, 'personal') &&
extension_loaded('mbstring') && //Check for a Mbstring constant rather than using extens
preg_match('/^=\?.*\?=$/', $address->personal) ion_loaded, which is sometimes disabled
defined('MB_CASE_UPPER') &&
preg_match('/^=\?.*\?=$/s', $address->personal)
) { ) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
//Undo any RFC2047-encoded spaces-as-underscores
$address->personal = str_replace('_', '=20', $address->p
ersonal);
//Decode the name
$address->personal = mb_decode_mimeheader($address->pers onal); $address->personal = mb_decode_mimeheader($address->pers onal);
mb_internal_encoding($origCharset);
} }
$addresses[] = [ $addresses[] = [
'name' => (property_exists($address, 'personal') ? $addr ess->personal : ''), 'name' => (property_exists($address, 'personal') ? $addr ess->personal : ''),
'address' => $address->mailbox . '@' . $address->host, 'address' => $address->mailbox . '@' . $address->host,
]; ];
} }
} }
} else { } else {
//Use this simpler parser //Use this simpler parser
skipping to change at line 1235 skipping to change at line 1245
$addresses[] = [ $addresses[] = [
'name' => '', 'name' => '',
'address' => $address, 'address' => $address,
]; ];
} }
} else { } else {
list($name, $email) = explode('<', $address); list($name, $email) = explode('<', $address);
$email = trim(str_replace('>', '', $email)); $email = trim(str_replace('>', '', $email));
$name = trim($name); $name = trim($name);
if (static::validateAddress($email)) { if (static::validateAddress($email)) {
//Check for a Mbstring constant rather than using extens ion_loaded, which is sometimes disabled
//If this name is encoded, decode it //If this name is encoded, decode it
if (preg_match('/^=\?.*\?=$/', $name)) { if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/
s', $name)) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
//Undo any RFC2047-encoded spaces-as-underscores
$name = str_replace('_', '=20', $name);
//Decode the name
$name = mb_decode_mimeheader($name); $name = mb_decode_mimeheader($name);
mb_internal_encoding($origCharset);
} }
$addresses[] = [ $addresses[] = [
//Remove any surrounding quotes and spaces from the name //Remove any surrounding quotes and spaces from the name
'name' => trim($name, '\'" '), 'name' => trim($name, '\'" '),
'address' => $email, 'address' => $email,
]; ];
} }
} }
} }
} }
skipping to change at line 1338 skipping to change at line 1355
* @param string $address The email address to check * @param string $address The email address to check
* @param string|callable $patternselect Which pattern to use * @param string|callable $patternselect Which pattern to use
* *
* @return bool * @return bool
*/ */
public static function validateAddress($address, $patternselect = null) public static function validateAddress($address, $patternselect = null)
{ {
if (null === $patternselect) { if (null === $patternselect) {
$patternselect = static::$validator; $patternselect = static::$validator;
} }
if (is_callable($patternselect)) { //Don't allow strings as callables, see SECURITY.md and CVE-2021-3603
if (is_callable($patternselect) && !is_string($patternselect)) {
return call_user_func($patternselect, $address); return call_user_func($patternselect, $address);
} }
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
if (strpos($address, "\n") !== false || strpos($address, "\r") !== false ) { if (strpos($address, "\n") !== false || strpos($address, "\r") !== false ) {
return false; return false;
} }
switch ($patternselect) { switch ($patternselect) {
case 'pcre': //Kept for BC case 'pcre': //Kept for BC
case 'pcre8': case 'pcre8':
/* /*
skipping to change at line 1436 skipping to change at line 1454
) { ) {
$domain = substr($address, ++$pos); $domain = substr($address, ++$pos);
//Verify CharSet string is a valid one, and domain properly encoded in this CharSet. //Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $thi s->CharSet)) { if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $thi s->CharSet)) {
//Convert the domain from whatever charset it's in to UTF-8 //Convert the domain from whatever charset it's in to UTF-8
$domain = mb_convert_encoding($domain, self::CHARSET_UTF8, $this ->CharSet); $domain = mb_convert_encoding($domain, self::CHARSET_UTF8, $this ->CharSet);
//Ignore IDE complaints about this line - method signature chang ed in PHP 5.4 //Ignore IDE complaints about this line - method signature chang ed in PHP 5.4
$errorcode = 0; $errorcode = 0;
if (defined('INTL_IDNA_VARIANT_UTS46')) { if (defined('INTL_IDNA_VARIANT_UTS46')) {
//Use the current punycode standard (appeared in PHP 7.2) //Use the current punycode standard (appeared in PHP 7.2)
$punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VAR $punycode = idn_to_ascii(
IANT_UTS46); $domain,
\IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI
|
\IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCI
I,
\INTL_IDNA_VARIANT_UTS46
);
} elseif (defined('INTL_IDNA_VARIANT_2003')) { } elseif (defined('INTL_IDNA_VARIANT_2003')) {
//Fall back to this old, deprecated/removed encoding //Fall back to this old, deprecated/removed encoding
$punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VAR IANT_2003); $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VAR IANT_2003);
} else { } else {
//Fall back to a default we don't know about //Fall back to a default we don't know about
$punycode = idn_to_ascii($domain, $errorcode); $punycode = idn_to_ascii($domain, $errorcode);
} }
if (false !== $punycode) { if (false !== $punycode) {
return substr($address, 0, $pos) . $punycode; return substr($address, 0, $pos) . $punycode;
} }
skipping to change at line 1508 skipping to change at line 1531
static::setLE(PHP_EOL); static::setLE(PHP_EOL);
} }
//Check for buggy PHP versions that add a header with an incorrect line break //Check for buggy PHP versions that add a header with an incorrect line break
if ( if (
'mail' === $this->Mailer 'mail' === $this->Mailer
&& ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017) && ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017)
|| (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103)) || (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103))
&& ini_get('mail.add_x_header') === '1' && ini_get('mail.add_x_header') === '1'
&& stripos(PHP_OS, 'WIN') === 0 && stripos(PHP_OS, 'WIN') === 0
) { ) {
trigger_error( trigger_error($this->lang('buggy_php'), E_USER_WARNING);
'Your version of PHP is affected by a bug that may result in cor
rupted messages.' .
' To fix it, switch to sending using SMTP, disable the mail.add_
x_header option in' .
' your php.ini, switch to MacOS or Linux, or upgrade your PHP to
version 7.0.17+ or 7.1.3+.',
E_USER_WARNING
);
} }
try { try {
$this->error_count = 0; //Reset errors $this->error_count = 0; //Reset errors
$this->mailHeader = ''; $this->mailHeader = '';
//Dequeue recipient and Reply-To addresses with IDN //Dequeue recipient and Reply-To addresses with IDN
foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) { foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
$params[1] = $this->punyencodeAddress($params[1]); $params[1] = $this->punyencodeAddress($params[1]);
call_user_func_array([$this, 'addAnAddress'], $params); call_user_func_array([$this, 'addAnAddress'], $params);
skipping to change at line 1687 skipping to change at line 1705
$this->edebug('Sending with sendmail'); $this->edebug('Sending with sendmail');
} }
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE; $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
//This sets the SMTP envelope sender which gets turned into a return-pat h header by the receiver //This sets the SMTP envelope sender which gets turned into a return-pat h header by the receiver
//A space after `-f` is optional, but there is a long history of its pre sence //A space after `-f` is optional, but there is a long history of its pre sence
//causing problems, so we don't use one //causing problems, so we don't use one
//Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch -the_exim_command_line.html //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch -the_exim_command_line.html
//Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
//Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
//Example problem: https://www.drupal.org/node/1057954 //Example problem: https://www.drupal.org/node/1057954
if (empty($this->Sender) && !empty(ini_get('sendmail_from'))) {
//PHP 5.6 workaround
$sendmail_from_value = ini_get('sendmail_from');
if (empty($this->Sender) && !empty($sendmail_from_value)) {
//PHP config has a sender address we can use //PHP config has a sender address we can use
$this->Sender = ini_get('sendmail_from'); $this->Sender = ini_get('sendmail_from');
} }
//CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be es caped. //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be es caped.
if (!empty($this->Sender) && static::validateAddress($this->Sender) && s elf::isShellSafe($this->Sender)) { if (!empty($this->Sender) && static::validateAddress($this->Sender) && s elf::isShellSafe($this->Sender)) {
if ($this->Mailer === 'qmail') { if ($this->Mailer === 'qmail') {
$sendmailFmt = '%s -f%s'; $sendmailFmt = '%s -f%s';
} else { } else {
$sendmailFmt = '%s -oi -f%s -t'; $sendmailFmt = '%s -oi -f%s -t';
} }
skipping to change at line 1724 skipping to change at line 1745
foreach ($this->SingleToArray as $toAddr) { foreach ($this->SingleToArray as $toAddr) {
$mail = @popen($sendmail, 'w'); $mail = @popen($sendmail, 'w');
if (!$mail) { if (!$mail) {
throw new Exception($this->lang('execute') . $this->Sendmail , self::STOP_CRITICAL); throw new Exception($this->lang('execute') . $this->Sendmail , self::STOP_CRITICAL);
} }
$this->edebug("To: {$toAddr}"); $this->edebug("To: {$toAddr}");
fwrite($mail, 'To: ' . $toAddr . "\n"); fwrite($mail, 'To: ' . $toAddr . "\n");
fwrite($mail, $header); fwrite($mail, $header);
fwrite($mail, $body); fwrite($mail, $body);
$result = pclose($mail); $result = pclose($mail);
$addrinfo = static::parseAddresses($toAddr); $addrinfo = static::parseAddresses($toAddr, true, $this->charSet );
$this->doCallback( $this->doCallback(
($result === 0), ($result === 0),
[[$addrinfo['address'], $addrinfo['name']]], [[$addrinfo['address'], $addrinfo['name']]],
$this->cc, $this->cc,
$this->bcc, $this->bcc,
$this->Subject, $this->Subject,
$body, $body,
$this->From, $this->From,
[] []
); );
skipping to change at line 1869 skipping to change at line 1890
$params = null; $params = null;
//This sets the SMTP envelope sender which gets turned into a return-pat h header by the receiver //This sets the SMTP envelope sender which gets turned into a return-pat h header by the receiver
//A space after `-f` is optional, but there is a long history of its pre sence //A space after `-f` is optional, but there is a long history of its pre sence
//causing problems, so we don't use one //causing problems, so we don't use one
//Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch -the_exim_command_line.html //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch -the_exim_command_line.html
//Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
//Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
//Example problem: https://www.drupal.org/node/1057954 //Example problem: https://www.drupal.org/node/1057954
//CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be es caped. //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be es caped.
if (empty($this->Sender) && !empty(ini_get('sendmail_from'))) {
//PHP 5.6 workaround
$sendmail_from_value = ini_get('sendmail_from');
if (empty($this->Sender) && !empty($sendmail_from_value)) {
//PHP config has a sender address we can use //PHP config has a sender address we can use
$this->Sender = ini_get('sendmail_from'); $this->Sender = ini_get('sendmail_from');
} }
if (!empty($this->Sender) && static::validateAddress($this->Sender)) { if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
if (self::isShellSafe($this->Sender)) { if (self::isShellSafe($this->Sender)) {
$params = sprintf('-f%s', $this->Sender); $params = sprintf('-f%s', $this->Sender);
} }
$old_from = ini_get('sendmail_from'); $old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $this->Sender); ini_set('sendmail_from', $this->Sender);
} }
$result = false; $result = false;
if ($this->SingleTo && count($toArr) > 1) { if ($this->SingleTo && count($toArr) > 1) {
foreach ($toArr as $toAddr) { foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $h eader, $params); $result = $this->mailPassthru($toAddr, $this->Subject, $body, $h eader, $params);
$addrinfo = static::parseAddresses($toAddr); $addrinfo = static::parseAddresses($toAddr, true, $this->charSet );
$this->doCallback( $this->doCallback(
$result, $result,
[[$addrinfo['address'], $addrinfo['name']]], [[$addrinfo['address'], $addrinfo['name']]],
$this->cc, $this->cc,
$this->bcc, $this->bcc,
$this->Subject, $this->Subject,
$body, $body,
$this->From, $this->From,
[] []
); );
skipping to change at line 2181 skipping to change at line 2205
public function smtpClose() public function smtpClose()
{ {
if ((null !== $this->smtp) && $this->smtp->connected()) { if ((null !== $this->smtp) && $this->smtp->connected()) {
$this->smtp->quit(); $this->smtp->quit();
$this->smtp->close(); $this->smtp->close();
} }
} }
/** /**
* Set the language for error messages. * Set the language for error messages.
* Returns false if it cannot load the language file.
* The default language is English. * The default language is English.
* *
* @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
* Optionally, the language code can be enhanced wi
th a 4-character
* script annotation and/or a 2-character country a
nnotation.
* @param string $lang_path Path to the language file directory, with traili ng separator (slash) * @param string $lang_path Path to the language file directory, with traili ng separator (slash)
* Do not set this from user input!
* *
* @return bool * @return bool Returns true if the requested language was loaded, false oth erwise.
*/ */
public function setLanguage($langcode = 'en', $lang_path = '') public function setLanguage($langcode = 'en', $lang_path = '')
{ {
//Backwards compatibility for renamed language codes //Backwards compatibility for renamed language codes
$renamed_langcodes = [ $renamed_langcodes = [
'br' => 'pt_br', 'br' => 'pt_br',
'cz' => 'cs', 'cz' => 'cs',
'dk' => 'da', 'dk' => 'da',
'no' => 'nb', 'no' => 'nb',
'se' => 'sv', 'se' => 'sv',
skipping to change at line 2210 skipping to change at line 2236
'am' => 'hy', 'am' => 'hy',
]; ];
if (array_key_exists($langcode, $renamed_langcodes)) { if (array_key_exists($langcode, $renamed_langcodes)) {
$langcode = $renamed_langcodes[$langcode]; $langcode = $renamed_langcodes[$langcode];
} }
//Define full set of translatable strings in English //Define full set of translatable strings in English
$PHPMAILER_LANG = [ $PHPMAILER_LANG = [
'authenticate' => 'SMTP Error: Could not authenticate.', 'authenticate' => 'SMTP Error: Could not authenticate.',
'buggy_php' => 'Your version of PHP is affected by a bug that may re
sult in corrupted messages.' .
' To fix it, switch to sending using SMTP, disable the mail.add_
x_header option in' .
' your php.ini, switch to MacOS or Linux, or upgrade your PHP to
version 7.0.17+ or 7.1.3+.',
'connect_host' => 'SMTP Error: Could not connect to SMTP host.', 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
'data_not_accepted' => 'SMTP Error: data not accepted.', 'data_not_accepted' => 'SMTP Error: data not accepted.',
'empty_message' => 'Message body empty', 'empty_message' => 'Message body empty',
'encoding' => 'Unknown encoding: ', 'encoding' => 'Unknown encoding: ',
'execute' => 'Could not execute: ', 'execute' => 'Could not execute: ',
'extension_missing' => 'Extension missing: ',
'file_access' => 'Could not access file: ', 'file_access' => 'Could not access file: ',
'file_open' => 'File Error: Could not open file: ', 'file_open' => 'File Error: Could not open file: ',
'from_failed' => 'The following From address failed: ', 'from_failed' => 'The following From address failed: ',
'instantiate' => 'Could not instantiate mail function.', 'instantiate' => 'Could not instantiate mail function.',
'invalid_address' => 'Invalid address: ', 'invalid_address' => 'Invalid address: ',
'invalid_header' => 'Invalid header name or value',
'invalid_hostentry' => 'Invalid hostentry: ', 'invalid_hostentry' => 'Invalid hostentry: ',
'invalid_host' => 'Invalid host: ', 'invalid_host' => 'Invalid host: ',
'mailer_not_supported' => ' mailer is not supported.', 'mailer_not_supported' => ' mailer is not supported.',
'provide_address' => 'You must provide at least one recipient email address.', 'provide_address' => 'You must provide at least one recipient email address.',
'recipients_failed' => 'SMTP Error: The following recipients failed: ', 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
'signing' => 'Signing Error: ', 'signing' => 'Signing Error: ',
'smtp_code' => 'SMTP code: ',
'smtp_code_ex' => 'Additional SMTP info: ',
'smtp_connect_failed' => 'SMTP connect() failed.', 'smtp_connect_failed' => 'SMTP connect() failed.',
'smtp_detail' => 'Detail: ',
'smtp_error' => 'SMTP server error: ', 'smtp_error' => 'SMTP server error: ',
'variable_set' => 'Cannot set or reset variable: ', 'variable_set' => 'Cannot set or reset variable: ',
'extension_missing' => 'Extension missing: ',
]; ];
if (empty($lang_path)) { if (empty($lang_path)) {
//Calculate an absolute path so it can work if CWD is not here //Calculate an absolute path so it can work if CWD is not here
$lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . D IRECTORY_SEPARATOR; $lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . D IRECTORY_SEPARATOR;
} }
//Validate $langcode //Validate $langcode
if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) { $foundlang = true;
$langcode = strtolower($langcode);
if (
!preg_match('/^(?P<lang>[a-z]{2})(?P<script>_[a-z]{4})?(?P<country>_
[a-z]{2})?$/', $langcode, $matches)
&& $langcode !== 'en'
) {
$foundlang = false;
$langcode = 'en'; $langcode = 'en';
} }
$foundlang = true;
$lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
//There is no English translation file //There is no English translation file
if ('en' !== $langcode) { if ('en' !== $langcode) {
//Make sure language file path is readable $langcodes = [];
if (!static::fileIsAccessible($lang_file)) { if (!empty($matches['script']) && !empty($matches['country'])) {
$langcodes[] = $matches['lang'] . $matches['script'] . $matches[
'country'];
}
if (!empty($matches['country'])) {
$langcodes[] = $matches['lang'] . $matches['country'];
}
if (!empty($matches['script'])) {
$langcodes[] = $matches['lang'] . $matches['script'];
}
$langcodes[] = $matches['lang'];
//Try and find a readable language file for the requested language.
$foundFile = false;
foreach ($langcodes as $code) {
$lang_file = $lang_path . 'phpmailer.lang-' . $code . '.php';
if (static::fileIsAccessible($lang_file)) {
$foundFile = true;
break;
}
}
if ($foundFile === false) {
$foundlang = false; $foundlang = false;
} else { } else {
//Overwrite language-specific strings. $lines = file($lang_file);
//This way we'll never have missing translation keys. foreach ($lines as $line) {
$foundlang = include $lang_file; //Translation file lines look like this:
//$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifi
zierung fehlgeschlagen.';
//These files are parsed as text and not PHP so as to avoid
the possibility of code injection
//See https://blog.stevenlevithan.com/archives/match-quoted-
string
$matches = [];
if (
preg_match(
'/^\$PHPMAILER_LANG\[\'([a-z\d_]+)\'\]\s*=\s*(["\'])
(.+)*?\2;/',
$line,
$matches
) &&
//Ignore unknown translation keys
array_key_exists($matches[1], $PHPMAILER_LANG)
) {
//Overwrite language-specific strings so we'll never hav
e missing translation keys.
$PHPMAILER_LANG[$matches[1]] = (string)$matches[3];
}
}
} }
} }
$this->language = $PHPMAILER_LANG; $this->language = $PHPMAILER_LANG;
return (bool) $foundlang; //Returns false if language not found return $foundlang; //Returns false if language not found
} }
/** /**
* Get the array of strings for the current language. * Get the array of strings for the current language.
* *
* @return array * @return array
*/ */
public function getTranslations() public function getTranslations()
{ {
if (empty($this->language)) {
$this->setLanguage(); // Set the default language.
}
return $this->language; return $this->language;
} }
/** /**
* Create recipient headers. * Create recipient headers.
* *
* @param string $type * @param string $type
* @param array $addr An array of recipients, * @param array $addr An array of recipients,
* where each recipient is a 2-element indexed array wit h element 0 containing an address * where each recipient is a 2-element indexed array wit h element 0 containing an address
* and element 1 containing a name, like: * and element 1 containing a name, like:
skipping to change at line 2532 skipping to change at line 2613
$result .= $this->addrAppend('Reply-To', $this->ReplyTo); $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
} }
//mail() sets the subject itself //mail() sets the subject itself
if ('mail' !== $this->Mailer) { if ('mail' !== $this->Mailer) {
$result .= $this->headerLine('Subject', $this->encodeHeader($this->s ecureHeader($this->Subject))); $result .= $this->headerLine('Subject', $this->encodeHeader($this->s ecureHeader($this->Subject)));
} }
//Only allow a custom message ID if it conforms to RFC 5322 section 3.6. 4 //Only allow a custom message ID if it conforms to RFC 5322 section 3.6. 4
//https://tools.ietf.org/html/rfc5322#section-3.6.4 //https://tools.ietf.org/html/rfc5322#section-3.6.4
if ('' !== $this->MessageID && preg_match('/^<.*@.*>$/', $this->MessageI if (
D)) { '' !== $this->MessageID &&
preg_match(
'/^<((([a-z\d!#$%&\'*+\/=?^_`{|}~-]+(\.[a-z\d!#$%&\'*+\/=?^_`{|}
~-]+)*)' .
'|("(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])
' .
'|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(([a-z\d!#$%&\'*+\/=?^_`
{|}~-]+' .
'(\.[a-z\d!#$%&\'*+\/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E
-\x1F\x7F]' .
'|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))>
$/Di',
$this->MessageID
)
) {
$this->lastMessageID = $this->MessageID; $this->lastMessageID = $this->MessageID;
} else { } else {
$this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->se rverHostname()); $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->se rverHostname());
} }
$result .= $this->headerLine('Message-ID', $this->lastMessageID); $result .= $this->headerLine('Message-ID', $this->lastMessageID);
if (null !== $this->Priority) { if (null !== $this->Priority) {
$result .= $this->headerLine('X-Priority', $this->Priority); $result .= $this->headerLine('X-Priority', $this->Priority);
} }
if ('' === $this->XMailer) { if ('' === $this->XMailer) {
$result .= $this->headerLine( $result .= $this->headerLine(
skipping to change at line 3916 skipping to change at line 4007
* @param string $msg * @param string $msg
*/ */
protected function setError($msg) protected function setError($msg)
{ {
++$this->error_count; ++$this->error_count;
if ('smtp' === $this->Mailer && null !== $this->smtp) { if ('smtp' === $this->Mailer && null !== $this->smtp) {
$lasterror = $this->smtp->getError(); $lasterror = $this->smtp->getError();
if (!empty($lasterror['error'])) { if (!empty($lasterror['error'])) {
$msg .= $this->lang('smtp_error') . $lasterror['error']; $msg .= $this->lang('smtp_error') . $lasterror['error'];
if (!empty($lasterror['detail'])) { if (!empty($lasterror['detail'])) {
$msg .= ' Detail: ' . $lasterror['detail']; $msg .= ' ' . $this->lang('smtp_detail') . $lasterror['detai l'];
} }
if (!empty($lasterror['smtp_code'])) { if (!empty($lasterror['smtp_code'])) {
$msg .= ' SMTP code: ' . $lasterror['smtp_code']; $msg .= ' ' . $this->lang('smtp_code') . $lasterror['smtp_co de'];
} }
if (!empty($lasterror['smtp_code_ex'])) { if (!empty($lasterror['smtp_code_ex'])) {
$msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex ']; $msg .= ' ' . $this->lang('smtp_code_ex') . $lasterror['smtp _code_ex'];
} }
} }
} }
$this->ErrorInfo = $msg; $this->ErrorInfo = $msg;
} }
/** /**
* Return an RFC 822 formatted date. * Return an RFC 822 formatted date.
* *
* @return string * @return string
skipping to change at line 3983 skipping to change at line 4074
* *
* @return bool * @return bool
*/ */
public static function isValidHost($host) public static function isValidHost($host)
{ {
//Simple syntax limits //Simple syntax limits
if ( if (
empty($host) empty($host)
|| !is_string($host) || !is_string($host)
|| strlen($host) > 256 || strlen($host) > 256
|| !preg_match('/^([a-zA-Z\d.-]*|\[[a-fA-F\d:]+])$/', $host) || !preg_match('/^([a-zA-Z\d.-]*|\[[a-fA-F\d:]+\])$/', $host)
) { ) {
return false; return false;
} }
//Looks like a bracketed IPv6 address //Looks like a bracketed IPv6 address
if (strlen($host) > 2 && substr($host, 0, 1) === '[' && substr($host, -1 , 1) === ']') { if (strlen($host) > 2 && substr($host, 0, 1) === '[' && substr($host, -1 , 1) === ']') {
return filter_var(substr($host, 1, -1), FILTER_VALIDATE_IP, FILTER_F LAG_IPV6) !== false; return filter_var(substr($host, 1, -1), FILTER_VALIDATE_IP, FILTER_F LAG_IPV6) !== false;
} }
//If removing all the dots results in a numeric string, it must be an IP v4 address. //If removing all the dots results in a numeric string, it must be an IP v4 address.
//Need to check this first because otherwise things like `999.0.0.0` are considered valid host names //Need to check this first because otherwise things like `999.0.0.0` are considered valid host names
if (is_numeric(str_replace('.', '', $host))) { if (is_numeric(str_replace('.', '', $host))) {
skipping to change at line 4060 skipping to change at line 4151
* *
* @throws Exception * @throws Exception
*/ */
public function addCustomHeader($name, $value = null) public function addCustomHeader($name, $value = null)
{ {
if (null === $value && strpos($name, ':') !== false) { if (null === $value && strpos($name, ':') !== false) {
//Value passed in as name:value //Value passed in as name:value
list($name, $value) = explode(':', $name, 2); list($name, $value) = explode(':', $name, 2);
} }
$name = trim($name); $name = trim($name);
$value = trim($value); $value = (null === $value) ? '' : trim($value);
//Ensure name is not empty, and that neither name nor value contain line breaks //Ensure name is not empty, and that neither name nor value contain line breaks
if (empty($name) || strpbrk($name . $value, "\r\n") !== false) { if (empty($name) || strpbrk($name . $value, "\r\n") !== false) {
if ($this->exceptions) { if ($this->exceptions) {
throw new Exception('Invalid header name or value'); throw new Exception($this->lang('invalid_header'));
} }
return false; return false;
} }
$this->CustomHeader[] = [$name, $value]; $this->CustomHeader[] = [$name, $value];
return true; return true;
} }
/** /**
skipping to change at line 4218 skipping to change at line 4309
* $plain = $mail->html2text($html); * $plain = $mail->html2text($html);
* //Use your own custom converter * //Use your own custom converter
* $plain = $mail->html2text($html, function($html) { * $plain = $mail->html2text($html, function($html) {
* $converter = new MyHtml2text($html); * $converter = new MyHtml2text($html);
* return $converter->get_text(); * return $converter->get_text();
* }); * });
* ``` * ```
* *
* @param string $html The HTML text to convert * @param string $html The HTML text to convert
* @param bool|callable $advanced Any boolean value to use the internal conv erter, * @param bool|callable $advanced Any boolean value to use the internal conv erter,
* or provide your own callable for custom co * or provide your own callable for custom co
nversion nversion.
* *Never* pass user-supplied data into this
parameter
* *
* @return string * @return string
*/ */
public function html2text($html, $advanced = false) public function html2text($html, $advanced = false)
{ {
if (is_callable($advanced)) { if (is_callable($advanced)) {
return call_user_func($advanced, $html); return call_user_func($advanced, $html);
} }
return html_entity_decode( return html_entity_decode(
 End of changes. 46 change blocks. 
53 lines changed or deleted 165 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)