Merge pull request #2449 from jrfnl/feature/parseaddresses-bug-fix-2-mbstring-needs-charset

PHPMailer::parseAddresses(): bug fix [2] - Mbstring encoding
This commit is contained in:
Marcus Bointon 2021-07-13 09:46:07 +02:00 committed by GitHub
commit 5c64f7e2d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 12 deletions

View File

@ -116,7 +116,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
coverage: ${{ steps.set_cov.outputs.COV }}
ini-values: sendmail_path=/usr/sbin/sendmail -t -i, zend.multibyte=1, zend.script_encoding=UTF-8, default_charset=UTF-8, error_reporting=E_ALL, display_errors=On
ini-values: sendmail_path=/usr/sbin/sendmail -t -i, error_reporting=E_ALL, display_errors=On
extensions: imap, mbstring, intl, ctype, filter, hash
# Install dependencies and handle caching in one go.

View File

@ -1188,7 +1188,7 @@ class PHPMailer
*
* @return array
*/
public static function parseAddresses($addrstr, $useimap = true)
public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
{
$addresses = [];
if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
@ -1209,7 +1209,10 @@ class PHPMailer
defined('MB_CASE_UPPER') &&
preg_match('/^=\?.*\?=$/', $address->personal)
) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
$address->personal = mb_decode_mimeheader($address->personal);
mb_internal_encoding($origCharset);
}
$addresses[] = [
@ -1240,7 +1243,10 @@ class PHPMailer
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
//If this name is encoded, decode it
if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/', $name)) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
$name = mb_decode_mimeheader($name);
mb_internal_encoding($origCharset);
}
$addresses[] = [
//Remove any surrounding quotes and spaces from the name
@ -1723,7 +1729,7 @@ class PHPMailer
fwrite($mail, $header);
fwrite($mail, $body);
$result = pclose($mail);
$addrinfo = static::parseAddresses($toAddr);
$addrinfo = static::parseAddresses($toAddr, true, $this->charSet);
$this->doCallback(
($result === 0),
[[$addrinfo['address'], $addrinfo['name']]],
@ -1883,7 +1889,7 @@ class PHPMailer
if ($this->SingleTo && count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
$addrinfo = static::parseAddresses($toAddr);
$addrinfo = static::parseAddresses($toAddr, true, $this->charSet);
$this->doCallback(
$result,
[[$addrinfo['address'], $addrinfo['name']]],

View File

@ -19,6 +19,11 @@ use Yoast\PHPUnitPolyfills\TestCases\TestCase;
/**
* Test RFC822 address splitting.
*
* @todo Additional tests need to be added to verify the correct handling of inputs which
* include a different encoding than UTF8 or even mixed encoding. For more information
* on what these test cases should look like and should test, please see
* {@link https://github.com/PHPMailer/PHPMailer/pull/2449} for context.
*
* @covers \PHPMailer\PHPMailer\PHPMailer::parseAddresses
*/
final class ParseAddressesTest extends TestCase
@ -34,10 +39,16 @@ final class ParseAddressesTest extends TestCase
*
* @param string $addrstr The address list string.
* @param array $expected The expected function output.
* @param string $charset Optional. The charset to use.
*/
public function testAddressSplittingNative($addrstr, $expected)
public function testAddressSplittingNative($addrstr, $expected, $charset = null)
{
$parsed = PHPMailer::parseAddresses($addrstr, false);
if (isset($charset)) {
$parsed = PHPMailer::parseAddresses($addrstr, false, $charset);
} else {
$parsed = PHPMailer::parseAddresses($addrstr, false);
}
$expectedOutput = $expected['default'];
if (empty($expected['native+mbstring']) === false) {
$expectedOutput = $expected['native+mbstring'];
@ -59,10 +70,16 @@ final class ParseAddressesTest extends TestCase
*
* @param string $addrstr The address list string.
* @param array $expected The expected function output.
* @param string $charset Optional. The charset to use.
*/
public function testAddressSplittingImap($addrstr, $expected)
public function testAddressSplittingImap($addrstr, $expected, $charset = null)
{
$parsed = PHPMailer::parseAddresses($addrstr, true);
if (isset($charset)) {
$parsed = PHPMailer::parseAddresses($addrstr, true, $charset);
} else {
$parsed = PHPMailer::parseAddresses($addrstr, true);
}
$expectedOutput = $expected['default'];
if (empty($expected['imap+mbstring']) === false) {
$expectedOutput = $expected['imap+mbstring'];
@ -81,14 +98,20 @@ final class ParseAddressesTest extends TestCase
*
* @param string $addrstr The address list string.
* @param array $expected The expected function output.
* @param string $charset Optional. The charset to use.
*/
public function testAddressSplittingNativeNoMbstring($addrstr, $expected)
public function testAddressSplittingNativeNoMbstring($addrstr, $expected, $charset = null)
{
if (extension_loaded('mbstring')) {
$this->markTestSkipped('Test requires MbString *not* to be available');
}
$parsed = PHPMailer::parseAddresses($addrstr, false);
if (isset($charset)) {
$parsed = PHPMailer::parseAddresses($addrstr, false, $charset);
} else {
$parsed = PHPMailer::parseAddresses($addrstr, false);
}
$expectedOutput = $expected['default'];
if (empty($expected['native--mbstring']) === false) {
$expectedOutput = $expected['native--mbstring'];
@ -109,14 +132,20 @@ final class ParseAddressesTest extends TestCase
*
* @param string $addrstr The address list string.
* @param array $expected The expected function output.
* @param string $charset Optional. The charset to use.
*/
public function testAddressSplittingImapNoMbstring($addrstr, $expected)
public function testAddressSplittingImapNoMbstring($addrstr, $expected, $charset = null)
{
if (extension_loaded('mbstring')) {
$this->markTestSkipped('Test requires MbString *not* to be available');
}
$parsed = PHPMailer::parseAddresses($addrstr, true);
if (isset($charset)) {
$parsed = PHPMailer::parseAddresses($addrstr, true, $charset);
} else {
$parsed = PHPMailer::parseAddresses($addrstr, true);
}
$expectedOutput = $expected['default'];
if (empty($expected['imap--mbstring']) === false) {
$expectedOutput = $expected['imap--mbstring'];
@ -157,6 +186,7 @@ final class ParseAddressesTest extends TestCase
* - `imap` Expected output from the IMAP implementation with or without Mbstring.
* - `imap+mbstring` Expected output from the IMAP implementation with Mbstring.
* - `imap--mbstring` Expected output from the IMAP implementation without Mbstring.
* Also optionally, an additional `charset` key can be passed,
*/
public function dataAddressSplitting()
{
@ -282,6 +312,7 @@ final class ParseAddressesTest extends TestCase
],
],
],
'charset' => PHPMailer::CHARSET_UTF8,
],
// Test cases with invalid addresses.