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\\": "" }