Decode encoded names in the address parser, see #2266
This commit is contained in:
parent
c2c5a3b9af
commit
e2eb2304fe
|
|
@ -5,6 +5,7 @@
|
|||
* Switch to Github Actions for CI
|
||||
* Generate debug output for `mail()` and `sendmail` transports – enable using the same mechanism as for SMTP: set `SMTPDebug` > 0
|
||||
* Make the `mail()` transport set the envelope sender the same way as SMTP does, i.e. use whatever `From` is set to, only falling back to the `sendmail_from` php.ini setting if `From` is unset. This avoids errors from the `mail()` function if `Sender` is not set explicitly and php.ini is not configured. This is a minor functionality change, so bumps the minor version number.
|
||||
* Extend `parseAddresses` to decode encoded names, improve tests
|
||||
|
||||
## Version 6.2.0
|
||||
* PHP 8.0 compatibility, many thanks to @jrf_nl!
|
||||
|
|
|
|||
|
|
@ -1196,6 +1196,11 @@ class PHPMailer
|
|||
$address->mailbox . '@' . $address->host
|
||||
)
|
||||
) {
|
||||
//Decode the name part if it's present and encoded
|
||||
if (property_exists($address, 'personal') && preg_match('/^=\?.*\?=$/', $address->personal)) {
|
||||
$address->personal = mb_decode_mimeheader($address->personal);
|
||||
}
|
||||
|
||||
$addresses[] = [
|
||||
'name' => (property_exists($address, 'personal') ? $address->personal : ''),
|
||||
'address' => $address->mailbox . '@' . $address->host,
|
||||
|
|
@ -1219,9 +1224,15 @@ class PHPMailer
|
|||
} else {
|
||||
list($name, $email) = explode('<', $address);
|
||||
$email = trim(str_replace('>', '', $email));
|
||||
$name = trim($name);
|
||||
if (static::validateAddress($email)) {
|
||||
//If this name is encoded, decode it
|
||||
if (preg_match('/^=\?.*\?=$/', $name)) {
|
||||
$name = mb_decode_mimeheader($name);
|
||||
}
|
||||
$addresses[] = [
|
||||
'name' => trim(str_replace(['"', "'"], '', $name)),
|
||||
//Remove any surrounding quotes and spaces from the name
|
||||
'name' => trim($name, '\'" '),
|
||||
'address' => $email,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3029,24 +3029,81 @@ EOT;
|
|||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address list parsing using PHPMailer's parser.
|
||||
* @test
|
||||
*/
|
||||
public function imapParsedAddressList_parseAddress_returnsAddressArray()
|
||||
{
|
||||
$addressLine = 'joe@example.com, <me@example.com>, Joe Doe <doe@example.com>, "John O\'Groats" <johnog@example.net>,' .
|
||||
' =?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?= <encoded@example.org>';
|
||||
|
||||
//Test using PHPMailer's own parser
|
||||
$expected = [
|
||||
[
|
||||
'name' => 'joe',
|
||||
'name' => '',
|
||||
'address' => 'joe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => 'me',
|
||||
'address' => 'me@home.com',
|
||||
'name' => '',
|
||||
'address' => 'me@example.com',
|
||||
],
|
||||
[
|
||||
'name' => 'Joe Doe',
|
||||
'address' => 'doe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => "John O'Groats",
|
||||
'address' => 'johnog@example.net',
|
||||
],
|
||||
[
|
||||
'name' => 'Название теста',
|
||||
'address' => 'encoded@example.org',
|
||||
],
|
||||
];
|
||||
if (file_exists($this->INCLUDE_DIR . '/test/fakefunctions.php')) {
|
||||
include $this->INCLUDE_DIR . '/test/fakefunctions.php';
|
||||
$addresses = PHPMailer::parseAddresses('joe@example.com, me@home.com');
|
||||
$this->assertEquals(asort($expected), asort($addresses));
|
||||
$parsed = PHPMailer::parseAddresses($addressLine, false);
|
||||
$this->assertSameSize($expected, $parsed);
|
||||
for ($i = 0; $i < count($expected); $i++) {
|
||||
$this->assertSame($expected[$i], $parsed[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address list parsing using the IMAP extension's parser.
|
||||
* @test
|
||||
*/
|
||||
public function imapParsedAddressList_parseAddress_returnsAddressArray_usingImap()
|
||||
{
|
||||
if (!extension_loaded('imap')) {
|
||||
$this->markTestSkipped("imap extension missing, can't run this test");
|
||||
}
|
||||
$addressLine = 'joe@example.com, <me@example.com>, Joe Doe <doe@example.com>, "John O\'Groats" <johnog@example.net>,' .
|
||||
' =?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?= <encoded@example.org>';
|
||||
$expected = [
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'joe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'me@example.com',
|
||||
],
|
||||
[
|
||||
'name' => 'Joe Doe',
|
||||
'address' => 'doe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => "John O'Groats",
|
||||
'address' => 'johnog@example.net',
|
||||
],
|
||||
[
|
||||
'name' => 'Название теста',
|
||||
'address' => 'encoded@example.org',
|
||||
],
|
||||
];
|
||||
$parsed = PHPMailer::parseAddresses($addressLine, true);
|
||||
$this->assertSameSize($expected, $parsed);
|
||||
for ($i = 0; $i < count($expected); $i++) {
|
||||
$this->assertSame($expected[$i], $parsed[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,38 +13,3 @@ if (!function_exists('mb_convert_encoding')) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('imap_rfc822_parse_adrlist')) {
|
||||
function imap_rfc822_parse_adrlist($addressList)
|
||||
{
|
||||
$addresses = explode(',', $addressList);
|
||||
$fakedAddresses = [];
|
||||
foreach ($addresses as $address) {
|
||||
$fakedAddresses[] = new FakeAddress($address);
|
||||
}
|
||||
|
||||
return $fakedAddresses;
|
||||
}
|
||||
|
||||
if (!class_exists(FakeAddress::class)) {
|
||||
class FakeAddress
|
||||
{
|
||||
public $host = 'example.com';
|
||||
public $mailbox = 'joe';
|
||||
public $personal = 'joe example';
|
||||
|
||||
/**
|
||||
* FakeAddress constructor.
|
||||
*
|
||||
* @param string $addressString
|
||||
*/
|
||||
public function __construct($addressString)
|
||||
{
|
||||
$addressParts = explode('@', $addressString);
|
||||
$this->mailbox = trim($addressParts[0]);
|
||||
$this->host = trim($addressParts[1]);
|
||||
$this->personal = explode('.', $addressParts[1])[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue