From b3d1f75cc0c29ae8e0d5d84ba48ea463806eff0c Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Sun, 15 Oct 2023 06:53:17 +0200 Subject: [PATCH] Introduce validation for emails starting with slash --- .../tests/unit/validators/EmailValidatorTest.php | 14 +++++++++++++- common/validators/EmailValidator.php | 16 ++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/common/tests/unit/validators/EmailValidatorTest.php b/common/tests/unit/validators/EmailValidatorTest.php index b0c0ac9..ea5874b 100644 --- a/common/tests/unit/validators/EmailValidatorTest.php +++ b/common/tests/unit/validators/EmailValidatorTest.php @@ -9,7 +9,10 @@ use common\validators\EmailValidator; use yii\base\Model; use yii\validators\EmailValidator as YiiEmailValidator; -class EmailValidatorTest extends TestCase { +/** + * @covers \common\validators\EmailValidator + */ +final class EmailValidatorTest extends TestCase { private EmailValidator $validator; @@ -86,6 +89,15 @@ class EmailValidatorTest extends TestCase { $this->assertNotSame(['error.email_invalid'], $model->getErrors('field')); } + public function testValidateAttributeStartingWithSlash(): void { + $this->getFunctionMock(YiiEmailValidator::class, 'checkdnsrr')->expects($this->any())->willReturn(true); + $this->getFunctionMock(YiiEmailValidator::class, 'dns_get_record')->expects($this->any())->willReturn(['mx.google.com']); + + $model = $this->createModel('\slash@gmail.com'); + $this->validator->validateAttribute($model, 'field'); + $this->assertSame(['error.email_invalid'], $model->getErrors('field')); + } + public function testValidateAttributeTempmail() { $this->getFunctionMock(YiiEmailValidator::class, 'checkdnsrr')->expects($this->any())->willReturn(true); $this->getFunctionMock(YiiEmailValidator::class, 'dns_get_record')->expects($this->any())->willReturn(['127.0.0.1']); diff --git a/common/validators/EmailValidator.php b/common/validators/EmailValidator.php index 3c23f45..0ad4224 100644 --- a/common/validators/EmailValidator.php +++ b/common/validators/EmailValidator.php @@ -12,7 +12,7 @@ use yii\db\QueryInterface; use yii\validators; use yii\validators\Validator; -class EmailValidator extends Validator { +final class EmailValidator extends Validator { /** * @var callable(): int the function must return the account id for which the current validation is being performed. @@ -37,6 +37,17 @@ class EmailValidator extends Validator { $email->enableIDN = true; $email->message = E::EMAIL_INVALID; + $additionalEmail = new class extends Validator { + protected function validateValue($value): ?array { + // Disallow emails starting with slash since Postfix (or someone before?) can't correctly handle it + if (str_starts_with($value, '/')) { + return [E::EMAIL_INVALID, []]; + } + + return null; + } + }; + $tempmail = new TempmailValidator(); $tempmail->message = E::EMAIL_IS_TEMPMAIL; @@ -57,7 +68,7 @@ class EmailValidator extends Validator { $idnaDomain = new validators\FilterValidator(['filter' => function(string $value): string { [$name, $domain] = explode('@', $value); - return idn_to_ascii($name, 0, INTL_IDNA_VARIANT_UTS46) . '@' . idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46); + return idn_to_ascii($name) . '@' . idn_to_ascii($domain); }]); $unique = new validators\UniqueValidator(); @@ -74,6 +85,7 @@ class EmailValidator extends Validator { $this->executeValidation($required, $model, $attribute) && $this->executeValidation($length, $model, $attribute) && $this->executeValidation($email, $model, $attribute) && + $this->executeValidation($additionalEmail, $model, $attribute) && $this->executeValidation($tempmail, $model, $attribute) && $this->executeValidation($blacklist, $model, $attribute) && $this->executeValidation($idnaDomain, $model, $attribute) &&