diff --git a/UPGRADE-2.5.md b/UPGRADE-2.5.md index f9fe7dda18..f5704103fe 100644 --- a/UPGRADE-2.5.md +++ b/UPGRADE-2.5.md @@ -44,3 +44,31 @@ Form public function getErrors($deep = false, $flatten = true) { ``` + +Validator +--------- + + * EmailValidator has changed to allow `non-strict` and `strict` email validation + + Before: + + Email validation was done with php's `filter_var()` + + After: + + Default email validation is now done via a simple regex which may cause invalid emails (not RFC compilant) to be + valid. This is the default behaviour. + + Strict email validation has to be explicitly activated in the configuration file by adding + ``` + framework_bundle: + //... + validation: + strict_email: true + //... + + ``` + Also you have to add to your composer.json: + ``` + "egulias/email-validator": "1.1.*" + ``` diff --git a/composer.json b/composer.json index 3b67c4b3e8..7efd53bdff 100644 --- a/composer.json +++ b/composer.json @@ -73,7 +73,8 @@ "monolog/monolog": "~1.3", "propel/propel1": "1.6.*", "ircmaxell/password-compat": "1.0.*", - "ocramius/proxy-manager": ">=0.3.1,<0.6-dev" + "ocramius/proxy-manager": ">=0.3.1,<0.6-dev", + "egulias/email-validator": "1.1.0" }, "autoload": { "psr-0": { "Symfony\\": "src/" }, diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index e78edaf356..a317d3cc8e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -445,6 +445,7 @@ class Configuration implements ConfigurationInterface ->scalarNode('cache')->end() ->booleanNode('enable_annotations')->defaultFalse()->end() ->scalarNode('translation_domain')->defaultValue('validators')->end() + ->booleanNode('strict_email')->defaultFalse()->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3221e74d92..5ee6982bc8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -678,6 +678,9 @@ class FrameworkExtension extends Extension $container->setParameter('validator.mapping.loader.xml_files_loader.mapping_files', $this->getValidatorXmlMappingFiles($container)); $container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $this->getValidatorYamlMappingFiles($container)); + $definition = $container->findDefinition('validator.email'); + $definition->replaceArgument(0, $config['strict_email']); + if (array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { $loaderChain = $container->getDefinition('validator.mapping.loader.loader_chain'); $arguments = $loaderChain->getArguments(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml index 4c1ac47d1f..9a30a2065d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml @@ -18,6 +18,7 @@ Symfony\Component\Validator\Constraints\ExpressionValidator + Symfony\Component\Validator\Constraints\EmailValidator @@ -69,5 +70,10 @@ + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index b62ad8395d..f2675d7d30 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -127,6 +127,7 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase 'enabled' => false, 'enable_annotations' => false, 'translation_domain' => 'validators', + 'strict_email' => false, ), 'annotations' => array( 'cache' => 'file', diff --git a/src/Symfony/Component/Validator/Constraints/Email.php b/src/Symfony/Component/Validator/Constraints/Email.php index 581dfb985f..e59d28d9a9 100644 --- a/src/Symfony/Component/Validator/Constraints/Email.php +++ b/src/Symfony/Component/Validator/Constraints/Email.php @@ -25,4 +25,13 @@ class Email extends Constraint public $message = 'This value is not a valid email address.'; public $checkMX = false; public $checkHost = false; + public $strict = null; + + /** + * {@inheritDoc} + */ + public function validatedBy() + { + return 'validator.email'; + } } diff --git a/src/Symfony/Component/Validator/Constraints/EmailValidator.php b/src/Symfony/Component/Validator/Constraints/EmailValidator.php index 1e9b94552b..fc1585d4c0 100644 --- a/src/Symfony/Component/Validator/Constraints/EmailValidator.php +++ b/src/Symfony/Component/Validator/Constraints/EmailValidator.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; +use Egulias\EmailValidator\EmailValidator as StrictEmailValidator; /** * @author Bernhard Schussek @@ -22,6 +23,18 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException; */ class EmailValidator extends ConstraintValidator { + /** + * isStrict + * + * @var Boolean + */ + private $isStrict; + + public function __construct($strict = false) + { + $this->isStrict = $strict; + } + /** * {@inheritDoc} */ @@ -40,12 +53,23 @@ class EmailValidator extends ConstraintValidator } $value = (string) $value; - $valid = filter_var($value, FILTER_VALIDATE_EMAIL); + if (null === $constraint->strict) { + $constraint->strict = $this->isStrict; + } + + if ($constraint->strict && class_exists('\Egulias\EmailValidator\EmailValidator')) { + $strictValidator = new StrictEmailValidator(); + $valid = $strictValidator->isValid($value, false); + } elseif ($constraint->strict === true) { + throw new \RuntimeException('Strict email validation requires egulias/email-validator'); + } else { + $valid = preg_match('/.+\@.+\..+/', $value); + } if ($valid) { $host = substr($value, strpos($value, '@') + 1); - // Check for host DNS resource records + if ($valid && $constraint->checkMX) { $valid = $this->checkMX($host); } elseif ($valid && $constraint->checkHost) { diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php index 701ab1f556..27c142f615 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php @@ -22,7 +22,7 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); - $this->validator = new EmailValidator(); + $this->validator = new EmailValidator(false); $this->validator->initialize($this->context); } @@ -100,7 +100,14 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase array('example'), array('example@'), array('example@localhost'), - array('example@example.com@example.com'), ); } + + public function testStrict() + { + $this->context->expects($this->never()) + ->method('addViolation'); + + $this->validator->validate('example@localhost', new Email(array('strict' => true))); + } } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index af14eabdb6..2e97389ca5 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -26,7 +26,8 @@ "symfony/yaml": "~2.0", "symfony/config": "~2.2", "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.0" + "doctrine/cache": "~1.0", + "egulias/email-validator": "~1.0" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", @@ -34,7 +35,8 @@ "symfony/http-foundation": "", "symfony/intl": "", "symfony/yaml": "", - "symfony/config": "" + "symfony/config": "", + "egulias/email-validator": "Strict (RFC compliant) email validation" }, "autoload": { "psr-0": { "Symfony\\Component\\Validator\\": "" }