Skip to content

Commit

Permalink
Relax email validation rules even more.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
markstory committed Jun 30, 2014
1 parent a966f08 commit dc34d80
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 15 deletions.
21 changes: 11 additions & 10 deletions lib/Cake/Network/Email/CakeEmail.php
Expand Up @@ -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.
Expand Down Expand Up @@ -547,8 +549,8 @@ public function headerCharset($charset = null) {
* @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;
Expand Down Expand Up @@ -593,13 +595,12 @@ protected function _setEmail($varName, $email, $name) {
* @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));
}

/**
Expand Down
12 changes: 7 additions & 5 deletions lib/Cake/Test/Case/Network/Email/CakeEmailTest.php
Expand Up @@ -249,12 +249,16 @@ public function testTo() {
$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'
Expand All @@ -265,6 +269,8 @@ public function testTo() {
$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',
Expand All @@ -275,11 +281,9 @@ public function testTo() {
);
$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
*
Expand All @@ -291,8 +295,6 @@ public static function invalidEmails() {
array(''),
array('string'),
array('<tag>'),
array('some@one-whereis'),
array('wrong@key' => 'Name'),
array(array('ok@cakephp.org', 1.0, '', 'string'))
);
}
Expand Down

0 comments on commit dc34d80

Please sign in to comment.