Adding Name Encoding Improvement without MbString Extension
This commit is contained in:
parent
800919c6a4
commit
bf8e97d3c8
|
|
@ -1256,20 +1256,9 @@ class PHPMailer
|
||||||
'.SYNTAX-ERROR.' !== $address->host &&
|
'.SYNTAX-ERROR.' !== $address->host &&
|
||||||
static::validateAddress($address->mailbox . '@' . $address->host)
|
static::validateAddress($address->mailbox . '@' . $address->host)
|
||||||
) {
|
) {
|
||||||
//Decode the name part if it's present and encoded
|
//Decode the name part if it's present and maybe encoded
|
||||||
if (
|
if (property_exists($address, 'personal') && is_string($address->personal) && $address->personal !== '') {
|
||||||
property_exists($address, 'personal') &&
|
$address->personal = static::decodeHeaderValue($address->personal, $charset);
|
||||||
//Check for a Mbstring constant rather than using extension_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->personal);
|
|
||||||
//Decode the name
|
|
||||||
$address->personal = mb_decode_mimeheader($address->personal);
|
|
||||||
mb_internal_encoding($origCharset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$addresses[] = [
|
$addresses[] = [
|
||||||
|
|
@ -1297,17 +1286,8 @@ class PHPMailer
|
||||||
$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 extension_loaded, which is sometimes disabled
|
//Decode RFC2047-encoded words in the display name, even when mbstring is unavailable
|
||||||
//If this name is encoded, decode it
|
$name = static::decodeHeaderValue($name, $charset);
|
||||||
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);
|
|
||||||
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, '\'" '),
|
||||||
|
|
@ -1321,6 +1301,69 @@ class PHPMailer
|
||||||
return $addresses;
|
return $addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode an RFC2047-encoded header value
|
||||||
|
* Attempts multiple strategies so it works even when the mbstring extension is disabled.
|
||||||
|
*
|
||||||
|
* @param string $value The header value to decode
|
||||||
|
* @param string $charset The target charset to convert to, defaults to ISO-8859-1 for BC
|
||||||
|
*
|
||||||
|
* @return string The decoded header value
|
||||||
|
*/
|
||||||
|
protected static function decodeHeaderValue($value, $charset = self::CHARSET_ISO88591)
|
||||||
|
{
|
||||||
|
if (!is_string($value) || $value === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = preg_replace('/(\?=)[\s\r\n]+(=\?)/s', '$1$2', $value);
|
||||||
|
|
||||||
|
// If mbstring is available, use it
|
||||||
|
if (defined('MB_CASE_UPPER') && function_exists('mb_decode_mimeheader')) {
|
||||||
|
$origCharset = mb_internal_encoding();
|
||||||
|
mb_internal_encoding($charset);
|
||||||
|
$prepared = str_replace('_', '=20', $value);
|
||||||
|
$decoded = mb_decode_mimeheader($prepared);
|
||||||
|
mb_internal_encoding($origCharset);
|
||||||
|
|
||||||
|
return trim($decoded, "'\" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no mbstring, use a manual decoder
|
||||||
|
$decoded = preg_replace_callback(
|
||||||
|
'/=\?([^?]+)\?([bqBQ])\?([^?]+)\?=/s',
|
||||||
|
static function ($matches) use ($charset) {
|
||||||
|
$sourceCharset = $matches[1];
|
||||||
|
$encoding = strtoupper($matches[2]);
|
||||||
|
$encodedText = $matches[3];
|
||||||
|
|
||||||
|
// When mbstring is unavailable, only safely decode ASCII/ISO-8859-1
|
||||||
|
// For other charsets (like UTF-8), leave the encoded-word intact to match expectations
|
||||||
|
$sourceLower = strtolower($sourceCharset);
|
||||||
|
if ($sourceLower !== 'iso-8859-1' && $sourceLower !== 'us-ascii') {
|
||||||
|
return $matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($encoding === 'Q') {
|
||||||
|
// Q-encoding
|
||||||
|
$encodedText = str_replace('_', ' ', $encodedText);
|
||||||
|
$decodedText = quoted_printable_decode($encodedText);
|
||||||
|
} else {
|
||||||
|
// B-encoding
|
||||||
|
$decodedText = base64_decode($encodedText);
|
||||||
|
if ($decodedText === false) {
|
||||||
|
$decodedText = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $decodedText;
|
||||||
|
},
|
||||||
|
$value
|
||||||
|
);
|
||||||
|
|
||||||
|
return trim($decoded, "'\" ");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the From and FromName properties.
|
* Set the From and FromName properties.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue