Skip to content

Commit

Permalink
Merge pull request PHPMailer#2449 from jrfnl/feature/parseaddresses-b…
Browse files Browse the repository at this point in the history
…ug-fix-2-mbstring-needs-charset

PHPMailer::parseAddresses(): bug fix [2] - Mbstring encoding
  • Loading branch information
Synchro committed Jul 13, 2021
2 parents 7cc67dd + 228338f commit 5c64f7e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 9 additions & 3 deletions src/PHPMailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,7 @@ protected function addAnAddress($kind, $address, $name = '')
*
* @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')) {
Expand All @@ -1209,7 +1209,10 @@ public static function parseAddresses($addrstr, $useimap = true)
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[] = [
Expand Down Expand Up @@ -1240,7 +1243,10 @@ public static function parseAddresses($addrstr, $useimap = true)
//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
Expand Down Expand Up @@ -1723,7 +1729,7 @@ protected function sendmailSend($header, $body)
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']]],
Expand Down Expand Up @@ -1883,7 +1889,7 @@ protected function mailSend($header, $body)
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']]],
Expand Down
47 changes: 39 additions & 8 deletions test/PHPMailer/ParseAddressesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
/**
* 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
Expand All @@ -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'];
Expand All @@ -59,10 +70,16 @@ public function testAddressSplittingNative($addrstr, $expected)
*
* @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'];
Expand All @@ -81,14 +98,20 @@ public function testAddressSplittingImap($addrstr, $expected)
*
* @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'];
Expand All @@ -109,14 +132,20 @@ public function testAddressSplittingNativeNoMbstring($addrstr, $expected)
*
* @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'];
Expand Down Expand Up @@ -157,6 +186,7 @@ protected function verifyExpectations($actual, $expected)
* - `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()
{
Expand Down Expand Up @@ -282,6 +312,7 @@ public function dataAddressSplitting()
],
],
],
'charset' => PHPMailer::CHARSET_UTF8,
],

// Test cases with invalid addresses.
Expand Down

0 comments on commit 5c64f7e

Please sign in to comment.