DNS validation. Closes #63 (#98)

This commit is contained in:
Eduardo Gulias Davis
2016-04-30 14:02:24 +02:00
parent ed861e1696
commit 6484b80486
8 changed files with 154 additions and 58 deletions
+11 -42
View File
@@ -2,24 +2,26 @@
namespace Egulias\EmailValidator;
use Egulias\EmailValidator\Warning\NoDNSMXRecord;
use Egulias\EmailValidator\Warning\NoDNSRecord;
use Egulias\EmailValidator\Warning\DomainLiteral;
use Egulias\EmailValidator\Warning\TLD;
use Egulias\EmailValidator\Exception\InvalidEmail;
use Egulias\EmailValidator\Validation\EmailValidation;
class EmailValidator
{
const ERR_DEPREC_REACHED = 151;
/**
* @var EmailLexer
*/
private $lexer;
/**
* @var array
*/
protected $warnings;
protected $error;
protected $threshold = 255;
/**
* @var InvalidEmail
*/
protected $error;
public function __construct()
{
$this->lexer = new EmailLexer();
@@ -35,14 +37,8 @@ class EmailValidator
$isValid = $emailValidation->isValid($email, $this->lexer);
$this->warnings = $emailValidation->getWarnings();
$this->error = $emailValidation->getError();
return $isValid;
// if ($this->hasWarnings() && ((int) max($this->warnings) > $this->threshold)) {
// $this->error = self::ERR_DEPREC_REACHED;
//
// return false;
// }
}
/**
@@ -68,31 +64,4 @@ class EmailValidator
{
return $this->error;
}
protected function checkDNS()
{
$checked = true;
$MXresult = checkdnsrr(trim($this->parser->getParsedDomainPart()), 'MX');
if (!$MXresult) {
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
$Aresult = checkdnsrr(trim($this->parser->getParsedDomainPart()), 'A');
if (!$Aresult) {
$this->warnings[NoDNSRecord::CODE] = new NoDNSRecord();
$checked = false;
$this->addTLDWarnings();
}
}
return $checked;
}
protected function addTLDWarnings()
{
if (!isset($this->warnings[NoDNSMXRecord::CODE]) &&
!isset($this->warnings[NoDNSRecord::CODE]) &&
isset($this->warnings[DomainLiteral::CODE])
) {
$this->warnings[TLD::CODE] = new TLD();
}
}
}
@@ -0,0 +1,11 @@
<?php
namespace Egulias\EmailValidator\Exception;
use Egulias\EmailValidator\Exception\InvalidEmail;
class NoDNSRecord extends InvalidEmail
{
const CODE = 5;
const REASON = 'No MX or A DSN record was found for this email';
}
@@ -16,7 +16,6 @@ use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\ExpectingDomainLiteralClose;
use Egulias\EmailValidator\Exception\ExpectingDTEXT;
use Egulias\EmailValidator\Exception\NoDomainPart;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Exception\UnopenedComment;
use Egulias\EmailValidator\Warning\AddressLiteral;
use Egulias\EmailValidator\Warning\CFWSWithFWS;
@@ -32,6 +31,7 @@ use Egulias\EmailValidator\Warning\IPV6GroupCount;
use Egulias\EmailValidator\Warning\IPV6MaxGroups;
use Egulias\EmailValidator\Warning\LabelTooLong;
use Egulias\EmailValidator\Warning\ObsoleteDTEXT;
use Egulias\EmailValidator\Warning\TLD;
class DomainPart extends Parser
{
@@ -353,4 +353,11 @@ class DomainPart extends Parser
throw new ExpectingATEXT();
}
}
protected function addTLDWarnings()
{
if ($this->warnings[DomainLiteral::CODE]) {
$this->warnings[TLD::CODE] = new TLD();
}
}
}
@@ -0,0 +1,73 @@
<?php
namespace Egulias\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Warning\NoDNSMXRecord;
use Egulias\EmailValidator\Exception\NoDNSRecord;
class DNSCheckValidation implements EmailValidation
{
/**
* @var EmailParser
*/
private $parser;
/**
* @var array
*/
private $warnings = [];
/**
* @var InvalidEmail
*/
private $error;
public function isValid($email, EmailLexer $emailLexer)
{
// use the input to check DNS if we cannot extract something similar to a domain
$host = $email;
// Arguable pattern to extract the domain. Not aiming to validate the domain nor the email
$pattern = "/^[a-z'0-9]+([._-][a-z'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+)+)+$/";
if (preg_match($pattern, $email, $result)) {
$host = $this->extractHost($result);
}
return $this->checkDNS($host);
}
public function getError()
{
return $this->error;
}
public function getWarnings()
{
return $this->warnings;
}
private function extractHost(array $result)
{
foreach ($result as $match) {
$onlyDomainPattern = "/^([a-z0-9]+([._-][a-z0-9]+))+$/";
if (preg_match($onlyDomainPattern, $match, $domainResult)) {
return $domainResult[0];
}
}
}
protected function checkDNS($host)
{
$Aresult = true;
$MXresult = checkdnsrr($host, 'MX');
if (!$MXresult) {
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
$Aresult = checkdnsrr($host, 'A');
if (!$Aresult) {
$this->error = new NoDNSRecord();
}
}
return $MXresult || $Aresult;
}
}
@@ -9,7 +9,7 @@ interface EmailValidation
public function isValid($email, EmailLexer $emailLexer);
/**
* @return InvalidArgumentException or InvalidEmail
* @return InvalidEmail
*/
public function getError();
@@ -8,8 +8,19 @@ use Egulias\EmailValidator\Exception\InvalidEmail;
class RFCValidation implements EmailValidation
{
/**
* @var EmailParser
*/
private $parser;
/**
* @var array
*/
private $warnings = [];
/**
* @var InvalidEmail
*/
private $error;
public function isValid($email, EmailLexer $emailLexer)
@@ -1,14 +0,0 @@
<?php
namespace Egulias\EmailValidator\Warning;
class NoDNSRecord extends Warning
{
const CODE = 5;
public function __construct()
{
$this->message = 'No MX or A DSN record was found for this email';
$this->rfcNumber = 5321;
}
}
@@ -0,0 +1,39 @@
<?php
namespace Egulias\Tests\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\NoDNSRecord;
use Egulias\EmailValidator\Validation\DNSCheckValidation;
use Egulias\EmailValidator\Warning\NoDNSMXRecord;
class DNSCheckValidationTest extends \PHPUnit_Framework_TestCase
{
public function testValidDNS()
{
$validation = new DNSCheckValidation();
$this->assertTrue($validation->isValid("example@example.com", new EmailLexer()));
}
public function testInvalidDNS()
{
$validation = new DNSCheckValidation();
$this->assertFalse($validation->isValid("example@invalid.example.com", new EmailLexer()));
}
public function testDNSWarnings()
{
$validation = new DNSCheckValidation();
$expectedWarnings = [NoDNSMXRecord::CODE => new NoDNSMXRecord()];
$validation->isValid("example@invalid.example.com", new EmailLexer());
$this->assertEquals($expectedWarnings, $validation->getWarnings());
}
public function testNoDNSError()
{
$validation = new DNSCheckValidation();
$expectedError = new NoDNSRecord();
$validation->isValid("example@invalid.example.com", new EmailLexer());
$this->assertEquals($expectedError, $validation->getError());
}
}