From dc34d80f6f622e883b8c7db9ef489bd514c8701f Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 30 Jun 2014 10:42:37 -0400 Subject: [PATCH] Relax email validation rules even more. While filter_var() allows a number of email addresses that Validation::email() does not, it misses out of email address that contain IDN host names, and unicode mailboxes. Both of these are generally deliverable, and should be permitted. filter_var() also fails on local mailboxes like `root@localhost` which is useful in the context of cron jobs. Fixes #3742 --- lib/Cake/Network/Email/CakeEmail.php | 21 ++++++++++--------- .../Test/Case/Network/Email/CakeEmailTest.php | 12 ++++++----- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/Cake/Network/Email/CakeEmail.php b/lib/Cake/Network/Email/CakeEmail.php index 39da66c51..2643edf1a 100644 --- a/lib/Cake/Network/Email/CakeEmail.php +++ b/lib/Cake/Network/Email/CakeEmail.php @@ -314,11 +314,13 @@ class CakeEmail { /** * Regex for email validation - * If null, filter_var() will be used. + * + * If null, filter_var() will be used. Use the emailPattern() method + * to set a custom pattern.' * * @var string */ - protected $_emailPattern = null; + protected $_emailPattern = '/^((?:[\p{L}0-9!#$%&\'*+\/=?^_`{|}~-]+)*@[\p{L}0-9-.]+)$/ui'; /** * The class name used for email configuration. @@ -547,8 +549,8 @@ class CakeEmail { * @param string $regex for email address validation * @return string|$this */ - public function emailPattern($regex = null) { - if ($regex === null) { + public function emailPattern($regex = false) { + if ($regex === false) { return $this->_emailPattern; } $this->_emailPattern = $regex; @@ -593,13 +595,12 @@ class CakeEmail { * @throws SocketException If email address does not validate */ protected function _validateEmail($email) { - $valid = (($this->_emailPattern !== null && - preg_match($this->_emailPattern, $email)) || - filter_var($email, FILTER_VALIDATE_EMAIL) - ); - if (!$valid) { - throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $email)); + if ($this->_emailPattern === null && filter_var($email, FILTER_VALIDATE_EMAIL)) { + return; + } elseif (preg_match($this->_emailPattern, $email)) { + return; } + throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $email)); } /** diff --git a/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php b/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php index d2293a40d..83c520839 100644 --- a/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php +++ b/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php @@ -249,12 +249,16 @@ class CakeEmailTest extends CakeTestCase { $this->assertSame($this->CakeEmail->to(), $expected); $list = array( + 'root@localhost' => 'root', + 'bjørn@hammeröath.com' => 'Bjorn', 'cake@cakephp.org' => 'Cake PHP', 'cake-php@googlegroups.com' => 'Cake Groups', 'root@cakephp.org' ); $this->CakeEmail->to($list); $expected = array( + 'root@localhost' => 'root', + 'bjørn@hammeröath.com' => 'Bjorn', 'cake@cakephp.org' => 'Cake PHP', 'cake-php@googlegroups.com' => 'Cake Groups', 'root@cakephp.org' => 'root@cakephp.org' @@ -265,6 +269,8 @@ class CakeEmailTest extends CakeTestCase { $this->CakeEmail->addTo('mark_story@cakephp.org', 'Mark Story'); $result = $this->CakeEmail->addTo(array('phpnut@cakephp.org' => 'PhpNut', 'jose_zap@cakephp.org')); $expected = array( + 'root@localhost' => 'root', + 'bjørn@hammeröath.com' => 'Bjorn', 'cake@cakephp.org' => 'Cake PHP', 'cake-php@googlegroups.com' => 'Cake Groups', 'root@cakephp.org' => 'root@cakephp.org', @@ -275,11 +281,9 @@ class CakeEmailTest extends CakeTestCase { ); $this->assertSame($this->CakeEmail->to(), $expected); $this->assertSame($this->CakeEmail, $result); - - $this->setExpectedException('SocketException'); - $this->CakeEmail->to(array('cake@localhost', 'CakePHP')); } + /** * Data provider function for testBuildInvalidData * @@ -291,8 +295,6 @@ class CakeEmailTest extends CakeTestCase { array(''), array('string'), array(''), - array('some@one-whereis'), - array('wrong@key' => 'Name'), array(array('ok@cakephp.org', 1.0, '', 'string')) ); }