Skip to content

Commit

Permalink
Add ability to inject custom validator and set custom default validat…
Browse files Browse the repository at this point in the history
…or, fixes PHPMailer#573
  • Loading branch information
Synchro committed May 9, 2016
1 parent d30b95b commit 77c0bc8
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 4 deletions.
24 changes: 22 additions & 2 deletions class.phpmailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,15 @@ class PHPMailer
*/
public $XMailer = '';

/**
* Which validator to use by default when validating email addresses.
* May be a callable to inject your own validator, but there are several built-in validators.
* @see PHPMailer::validateAddress()
* @var string|callable
* @static
*/
public static $validator = 'auto';

/**
* An instance of the SMTP sender class.
* @var SMTP
Expand Down Expand Up @@ -1028,19 +1037,30 @@ public function getLastMessageID()
/**
* Check that a string looks like an email address.
* @param string $address The email address to check
* @param string $patternselect A selector for the validation pattern to use :
* @param string|callable $patternselect A selector for the validation pattern to use :
* * `auto` Pick best pattern automatically;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
* * `pcre` Use old PCRE implementation;
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
* * `noregex` Don't use a regex: super fast, really dumb.
* Alternatively you may pass in a callable to inject your own validator, for example:
* PHPMailer::validateAddress('user@example.com', function($address) {
* return (strpos($address, '@') !== false);
* });
* You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
* @return boolean
* @static
* @access public
*/
public static function validateAddress($address, $patternselect = 'auto')
public static function validateAddress($address, $patternselect = null)
{
if (is_null($patternselect)) {
$patternselect = self::$validator;
}
if (is_callable($patternselect)) {
return call_user_func($patternselect, $address);
}
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
return false;
Expand Down
53 changes: 51 additions & 2 deletions test/phpmailerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ public function testValidate()
'"Doug "Ace" L."@iana.org',
'Doug\ \"Ace\"\ L\.@iana.org',
'hello world@iana.org',
//'helloworld@iana .org',
'helloworld@iana .org',
'gatsby@f.sc.ot.t.f.i.tzg.era.l.d.',
'test.iana.org',
'test.@iana.org',
Expand Down Expand Up @@ -606,7 +606,9 @@ public function testValidate()
'first.last@[IPv6:a1:a2:a3:a4:b1:b2:b3:]',
'first.last@[IPv6::a2:a3:a4:b1:b2:b3:b4]',
'first.last@[IPv6:a1:a2:a3:a4::b1:b2:b3:b4]',
"(\r\n RCPT TO:user@example.com\r\n DATA \\\nSubject: spam10\\\n\r\n Hello,\r\n this is a spam mail.\\\n.\r\n QUIT\r\n ) a@example.net" //This is valid RCC5322, but we don't want to allow it
//This is a valid RCC5322 address, but we don't want to allow it for obvious reasons!
"(\r\n RCPT TO:user@example.com\r\n DATA \\\nSubject: spam10\\\n\r\n Hello,\r\n".
" this is a spam mail.\\\n.\r\n QUIT\r\n ) a@example.net"
);
// IDNs in Unicode and ASCII forms.
$unicodeaddresses = array(
Expand Down Expand Up @@ -657,6 +659,53 @@ public function testValidate()
$this->assertFalse(PHPMailer::validateAddress('bad', 'noregex'));
}

/**
* Test injecting a custom validator.
*/
public function testCustomValidator()
{
//Inject a one-off custom validator
$this->assertTrue(
PHPMailer::validateAddress(
'user@example.com',
function ($address) {
return (strpos($address, '@') !== false);
}
),
'Custom validator false negative'
);
$this->assertFalse(
PHPMailer::validateAddress(
'userexample.com',
function ($address) {
return (strpos($address, '@') !== false);
}
),
'Custom validator false positive'
);
//Set the default validator to an injected function
PHPMailer::$validator = function ($address) {
return ('user@example.com' === $address);
};
$this->assertTrue(
$this->Mail->addAddress('user@example.com'),
'Custom default validator false negative'
);
$this->assertFalse(
//Need to pick a failing value which would pass all other validators
//to be sure we're using our custom one
$this->Mail->addAddress('bananas@example.com'),
'Custom default validator false positive'
);
//Set default validator to PHP built-in
PHPMailer::$validator = 'php';
$this->assertFalse(
//This is a valid address that FILTER_VALIDATE_EMAIL thinks is invalid
$this->Mail->addAddress('first.last@example.123'),
'PHP validator not behaving as expected'
);
}

/**
* Word-wrap an ASCII message.
*/
Expand Down

0 comments on commit 77c0bc8

Please sign in to comment.