mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-13 22:06:51 +08:00
#10142 Fixed EmailValidator to check email length properly
This commit is contained in:
@ -35,6 +35,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #9999: Fixed `yii\web\UrlRule` to allow route parameter names with `-`, `_`, `.`characters (silverfire)
|
||||
- Bug #10029: Fixed MaskedInput not working with PJAX (martrix78, samdark)
|
||||
- Bug #10101: Fixed assignments saving on role removing in `\yii\rbac\PhpManager` (rezident1307)
|
||||
- Bug #10142: Fixed `yii\validators\EmailValidator` to check the length of email properly (silverfire)
|
||||
- Bug: Fixed generation of canonical URLs for `ViewAction` pages (samdark)
|
||||
- Enh #3506: Added `\yii\validators\IpValidator` to perform validation of IP addresses and subnets (SilverFire, samdark)
|
||||
- Enh #5146: Added `\yii\i18n\Formatter::asDuration()` method (nineinchnick, SilverFire)
|
||||
|
@ -192,17 +192,30 @@ yii.validation = (function ($) {
|
||||
|
||||
var valid = true;
|
||||
|
||||
if (options.enableIDN) {
|
||||
var regexp = /^(.*<?)(.*)@(.*)(>?)$/,
|
||||
matches = regexp.exec(value);
|
||||
if (matches === null) {
|
||||
|
||||
var regexp = /^((?:"?([^"]*)"?\s)?)(?:\s+)?(?:(<?)((.+)@([^>]+))(>?))$/,
|
||||
matches = regexp.exec(value);
|
||||
|
||||
if (matches === null) {
|
||||
valid = false
|
||||
} else {
|
||||
if (options.enableIDN) {
|
||||
matches[5] = punycode.toASCII(matches[5]);
|
||||
matches[6] = punycode.toASCII(matches[6]);
|
||||
|
||||
value = matches[1] + matches[3] + matches[5] + '@' + matches[6] + matches[7];
|
||||
}
|
||||
|
||||
if (matches[5].length > 64 || matches[1].length > 64) {
|
||||
valid = false;
|
||||
} else if ((matches[5] + '@' + matches[6]).length > 254) {
|
||||
valid = false;
|
||||
} else {
|
||||
value = matches[1] + punycode.toASCII(matches[2]) + '@' + punycode.toASCII(matches[3]) + matches[4];
|
||||
valid = value.match(options.pattern) || (options.allowName && value.match(options.fullPattern));
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid || !(value.match(options.pattern) || (options.allowName && value.match(options.fullPattern)))) {
|
||||
if (!valid) {
|
||||
pub.addMessage(messages, options.message, value);
|
||||
}
|
||||
},
|
||||
|
@ -70,19 +70,34 @@ class EmailValidator extends Validator
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
// make sure string length is limited to avoid DOS attacks
|
||||
if (!is_string($value) || strlen($value) >= 320) {
|
||||
if (!is_string($value)) {
|
||||
$valid = false;
|
||||
} elseif (!preg_match('/^(.*<?)(.*)@(.*?)(>?)$/', $value, $matches)) {
|
||||
} elseif (!preg_match('/^(?P<name>(?:"?([^"]*)"?\s)?)(?:\s+)?(?:(?P<open><?)((?P<local>.+)@(?P<domain>[^>]+))(?P<close>>?))$/i', $value, $matches)) {
|
||||
$valid = false;
|
||||
} else {
|
||||
$domain = $matches[3];
|
||||
if ($this->enableIDN) {
|
||||
$value = $matches[1] . idn_to_ascii($matches[2]) . '@' . idn_to_ascii($domain) . $matches[4];
|
||||
$matches['local'] = idn_to_ascii($matches['local']);
|
||||
$matches['domain'] = idn_to_ascii($matches['domain']);
|
||||
$value = $matches['name'] . $matches['open'] . $matches['local'] . '@' . $matches['domain'] . $matches['close'];
|
||||
}
|
||||
$valid = preg_match($this->pattern, $value) || $this->allowName && preg_match($this->fullPattern, $value);
|
||||
if ($valid && $this->checkDNS) {
|
||||
$valid = checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A');
|
||||
|
||||
if (strlen($matches['local']) > 64 || mb_strlen($matches['name']) > 64) {
|
||||
// The maximum total length of a user name or other local-part is 64 octets. RFC 5322 section 4.5.3.1.1
|
||||
// http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1
|
||||
$valid = false;
|
||||
} elseif (strlen($matches['local'] . '@' . $matches['domain']) > 254) {
|
||||
// There is a restriction in RFC 2821 on the length of an address in MAIL and RCPT commands
|
||||
// of 254 characters. Since addresses that do not fit in those fields are not normally useful, the
|
||||
// upper limit on address lengths should normally be considered to be 254.
|
||||
//
|
||||
// Dominic Sayers, RFC 3696 erratum 1690
|
||||
// http://www.rfc-editor.org/errata_search.php?eid=1690
|
||||
$valid = false;
|
||||
} else {
|
||||
$valid = preg_match($this->pattern, $value) || $this->allowName && preg_match($this->fullPattern, $value);
|
||||
if ($valid && $this->checkDNS) {
|
||||
$valid = checkdnsrr($matches['domain'], 'MX') || checkdnsrr($matches['domain'], 'A');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +116,7 @@ class EmailValidator extends Validator
|
||||
'message' => Yii::$app->getI18n()->format($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
], Yii::$app->language),
|
||||
'enableIDN' => (bool) $this->enableIDN,
|
||||
'enableIDN' => (bool)$this->enableIDN,
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
|
@ -43,6 +43,9 @@ class EmailValidatorTest extends TestCase
|
||||
$this->assertTrue($validator->validate('test@example.com'));
|
||||
$this->assertTrue($validator->validate('John Smith <john.smith@example.com>'));
|
||||
$this->assertFalse($validator->validate('John Smith <example.com>'));
|
||||
$this->assertFalse($validator->validate('Short Name <localPartMoreThan64Characters-blah-blah-blah-blah-blah-blah-blah-blah@example.com>'));
|
||||
$this->assertFalse($validator->validate('Short Name <domainNameIsMoreThan254Characters@example-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah.com>'));
|
||||
$this->assertFalse($validator->validate('"This name is longer than 64 characters. Blah blah blah blah blah" <shortmail@example.com>'));
|
||||
}
|
||||
|
||||
public function testValidateValueIdn()
|
||||
@ -82,6 +85,9 @@ class EmailValidatorTest extends TestCase
|
||||
$this->assertTrue($validator->validate('test@example.com'));
|
||||
$this->assertTrue($validator->validate('John Smith <john.smith@example.com>'));
|
||||
$this->assertFalse($validator->validate('John Smith <example.com>'));
|
||||
$this->assertFalse($validator->validate('Короткое имя <после-преобразования-в-idn-тут-будет-больше-чем-64-символа@пример.com>'));
|
||||
$this->assertFalse($validator->validate('Короткое имя <тест@это-доменное-имя.после-преобразования-в-idn.будет-содержать-больше-254-символов.бла-бла-бла-бла-бла-бла-бла-бла.бла-бла-бла-бла-бла-бла.бла-бла-бла-бла-бла-бла.бла-бла-бла-бла-бла-бла.com>'));
|
||||
$this->assertFalse($validator->validate('"Такое имя достаточно длинное, чтобы не допустить валидацию имейла" <shortmail@example.com>'));
|
||||
}
|
||||
|
||||
public function testValidateValueMx()
|
||||
|
Reference in New Issue
Block a user