Introduce validation for emails starting with slash

This commit is contained in:
ErickSkrauch 2023-10-15 06:53:17 +02:00
parent e738bce717
commit b3d1f75cc0
No known key found for this signature in database
GPG Key ID: 669339FCBB30EE0E
2 changed files with 27 additions and 3 deletions

View File

@ -9,7 +9,10 @@ use common\validators\EmailValidator;
use yii\base\Model; use yii\base\Model;
use yii\validators\EmailValidator as YiiEmailValidator; use yii\validators\EmailValidator as YiiEmailValidator;
class EmailValidatorTest extends TestCase { /**
* @covers \common\validators\EmailValidator
*/
final class EmailValidatorTest extends TestCase {
private EmailValidator $validator; private EmailValidator $validator;
@ -86,6 +89,15 @@ class EmailValidatorTest extends TestCase {
$this->assertNotSame(['error.email_invalid'], $model->getErrors('field')); $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() { public function testValidateAttributeTempmail() {
$this->getFunctionMock(YiiEmailValidator::class, 'checkdnsrr')->expects($this->any())->willReturn(true); $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']); $this->getFunctionMock(YiiEmailValidator::class, 'dns_get_record')->expects($this->any())->willReturn(['127.0.0.1']);

View File

@ -12,7 +12,7 @@ use yii\db\QueryInterface;
use yii\validators; use yii\validators;
use yii\validators\Validator; 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. * @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->enableIDN = true;
$email->message = E::EMAIL_INVALID; $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 = new TempmailValidator();
$tempmail->message = E::EMAIL_IS_TEMPMAIL; $tempmail->message = E::EMAIL_IS_TEMPMAIL;
@ -57,7 +68,7 @@ class EmailValidator extends Validator {
$idnaDomain = new validators\FilterValidator(['filter' => function(string $value): string { $idnaDomain = new validators\FilterValidator(['filter' => function(string $value): string {
[$name, $domain] = explode('@', $value); [$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(); $unique = new validators\UniqueValidator();
@ -74,6 +85,7 @@ class EmailValidator extends Validator {
$this->executeValidation($required, $model, $attribute) && $this->executeValidation($required, $model, $attribute) &&
$this->executeValidation($length, $model, $attribute) && $this->executeValidation($length, $model, $attribute) &&
$this->executeValidation($email, $model, $attribute) && $this->executeValidation($email, $model, $attribute) &&
$this->executeValidation($additionalEmail, $model, $attribute) &&
$this->executeValidation($tempmail, $model, $attribute) && $this->executeValidation($tempmail, $model, $attribute) &&
$this->executeValidation($blacklist, $model, $attribute) && $this->executeValidation($blacklist, $model, $attribute) &&
$this->executeValidation($idnaDomain, $model, $attribute) && $this->executeValidation($idnaDomain, $model, $attribute) &&