Adjust eai regex to disallow emoji and letters/numbers.

Update a few tests to match the recent changes.

Use the eai validator (unless another is being used) for addresses such as
info@müller-schmidt.de, for which PHPMailer may not choose to use SMTPUTF8.
This commit is contained in:
Arnt Gulbrandsen 2025-04-08 16:49:08 +02:00 committed by Marcus Bointon
parent b62de86fd2
commit d31cb27117
No known key found for this signature in database
GPG Key ID: DE31CD6EB646AA24
2 changed files with 24 additions and 20 deletions

View File

@ -1174,10 +1174,10 @@ class PHPMailer
{ {
if ( if (
self::$validator === 'php' && self::$validator === 'php' &&
$this->addressHasUnicodeLocalPart($address) ((bool) preg_match('/[\x80-\xFF]/', $address))
) { ) {
//The caller has not altered the validator, so assume that they want UTF-8 support //The caller has not altered the validator and is sending to an address
//instead of failing //with UTF-8, so assume that they want UTF-8 support instead of failing
$this->CharSet = self::CHARSET_UTF8; $this->CharSet = self::CHARSET_UTF8;
self::$validator = 'eai'; self::$validator = 'eai';
} }
@ -1467,9 +1467,9 @@ class PHPMailer
* @see https://en.wikipedia.org/wiki/International_email * @see https://en.wikipedia.org/wiki/International_email
*/ */
return (bool) preg_match( return (bool) preg_match(
'/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~\x80-\xff-]+@[a-zA-Z0-9\x80-\xff](?:[a-zA-Z0-9\x80-\xff-]{0,61}' . '/^[-\p{L}\p{N}\p{M}.!#$%&\'*+\/=?^_`{|}~]+@[\p{L}\p{N}\p{M}](?:[\p{L}\p{N}\p{M}-]{0,61}' .
'[a-zA-Z0-9\x80-\xff])?(?:\.[a-zA-Z0-9\x80-\xff]' . '[\p{L}\p{N}\p{M}])?(?:\.[\p{L}\p{N}\p{M}]' .
'(?:[a-zA-Z0-9\x80-\xff-]{0,61}[a-zA-Z0-9\x80-\xff])?)*$/sD', '(?:[-\p{L}\p{N}\p{M}]{0,61}[\p{L}\p{N}\p{M}])?)*$/usD',
$address $address
); );
case 'php': case 'php':

View File

@ -1197,24 +1197,30 @@ EOT;
*/ */
public function testUnsupportedSmtpUTF8() public function testUnsupportedSmtpUTF8()
{ {
$this->Mail = new PHPMailer(true); self::assertFalse(PHPMailer::validateAddress('spın̈altap@example.com', 'html5'));
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8; self::assertTrue(PHPMailer::validateAddress('spın̈altap@example.com', 'eai'));
PHPMailer::$validator = 'html5';
self::assertFalse(PHPMailer::validateAddress('spın̈altap@example.com'));
PHPMailer::$validator = 'eai';
self::assertTrue(PHPMailer::validateAddress('spın̈altap@example.com'));
} }
/** /**
* Test that SMTPUTF8 is automatically allowed if charset is UTF8. * The eai regex is complex and warrants a few extra tests.
*/
public function testStrangeUnicodeEmailAddresses()
{
PHPMailer::$validator = 'eai';
self::assertTrue(PHPMailer::validateAddress('spın̈altap@example.com'));
self::assertTrue(PHPMailer::validateAddress('spın̈altap@spın̈altap.com'));
self::assertTrue(PHPMailer::validateAddress('दूकान@मेरी.दूकान.भारत'));
self::assertTrue(PHPMailer::validateAddress('慕田峪长城@慕田峪长城.网址'));
self::assertFalse(PHPMailer::validateAddress('慕田峪长城@慕田峪长城。网址'));
}
/**
* Test that SMTPUTF8 is allowed unless the caller has made a concious choice against.
*/ */
public function testAutomaticEaiValidation() public function testAutomaticEaiValidation()
{ {
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
$this->Mail = new PHPMailer(true); $this->Mail = new PHPMailer(true);
PHPMailer::$validator = 'php'; PHPMailer::$validator = 'php';
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
$this->Mail->Body = 'Test'; $this->Mail->Body = 'Test';
$this->Mail->isSMTP(); $this->Mail->isSMTP();
self::assertTrue($this->Mail->addAddress('spın̈altap@example.com', '')); self::assertTrue($this->Mail->addAddress('spın̈altap@example.com', ''));
@ -1227,7 +1233,7 @@ EOT;
*/ */
public function testSmtpUTF8() public function testSmtpUTF8()
{ {
PHPMailer::$validator = 'eai'; PHPMailer::$validator = 'php';
$this->Mail = new PHPMailer(true); $this->Mail = new PHPMailer(true);
$this->Mail->Body = 'Test'; $this->Mail->Body = 'Test';
$this->Mail->isSMTP(); $this->Mail->isSMTP();
@ -1235,15 +1241,13 @@ EOT;
$this->Mail->preSend(); $this->Mail->preSend();
self::assertFalse($this->Mail->needsSMTPUTF8()); self::assertFalse($this->Mail->needsSMTPUTF8());
//Using a punycoded domain does not need SMTPUTF8 //Using a punycodable domain does not need SMTPUTF8
self::assertFalse($this->Mail->needsSMTPUTF8()); self::assertFalse($this->Mail->needsSMTPUTF8());
PHPMailer::$validator = 'eai';
$this->Mail->addAddress('foo@spın̈altap.example', ''); $this->Mail->addAddress('foo@spın̈altap.example', '');
$this->Mail->preSend(); $this->Mail->preSend();
self::assertFalse($this->Mail->needsSMTPUTF8()); self::assertFalse($this->Mail->needsSMTPUTF8());
//Need to use SMTPUTF8, and can. //Need to use SMTPUTF8, and can.
$this->Mail->CharSet = PHPMailer::CHARSET_UTF8;
self::assertTrue($this->Mail->addAddress('spın̈altap@example.com', '')); self::assertTrue($this->Mail->addAddress('spın̈altap@example.com', ''));
$this->Mail->preSend(); $this->Mail->preSend();
self::assertTrue($this->Mail->needsSMTPUTF8()); self::assertTrue($this->Mail->needsSMTPUTF8());