mirror of
https://github.com/egulias/EmailValidator.git
synced 2026-09-01 13:08:58 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 04c6cdf987 | |||
| cc9defe645 | |||
| 50aaa0b18f | |||
| de448a30fa | |||
| a7b385301d | |||
| f6447f8b99 | |||
| d4001715b2 | |||
| 4b7fcf6796 | |||
| 2a1145ffbf |
@@ -9,7 +9,7 @@ With the help of
|
|||||||
Run the command below to install via Composer
|
Run the command below to install via Composer
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
composer require egulias/email-validator
|
composer require egulias/email-validator "~1.2"
|
||||||
```
|
```
|
||||||
|
|
||||||
##Usage##
|
##Usage##
|
||||||
|
|||||||
@@ -67,8 +67,6 @@ class EmailLexer extends AbstractLexer
|
|||||||
"\n" => self::S_LF,
|
"\n" => self::S_LF,
|
||||||
"\r\n" => self::CRLF,
|
"\r\n" => self::CRLF,
|
||||||
'IPv6' => self::S_IPV6TAG,
|
'IPv6' => self::S_IPV6TAG,
|
||||||
'<' => self::S_LOWERTHAN,
|
|
||||||
'>' => self::S_GREATERTHAN,
|
|
||||||
'{' => self::S_OPENQBRACKET,
|
'{' => self::S_OPENQBRACKET,
|
||||||
'}' => self::S_CLOSEQBRACKET,
|
'}' => self::S_CLOSEQBRACKET,
|
||||||
'' => self::S_EMPTY,
|
'' => self::S_EMPTY,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class EmailValidator
|
|||||||
const ERR_FWS_CRLF_END = 149;
|
const ERR_FWS_CRLF_END = 149;
|
||||||
const ERR_CR_NO_LF = 150;
|
const ERR_CR_NO_LF = 150;
|
||||||
const ERR_DEPREC_REACHED = 151;
|
const ERR_DEPREC_REACHED = 151;
|
||||||
|
const ERR_UNOPENEDCOMMENT = 152;
|
||||||
const RFC5321_TLD = 9;
|
const RFC5321_TLD = 9;
|
||||||
const RFC5321_TLDNUMERIC = 10;
|
const RFC5321_TLDNUMERIC = 10;
|
||||||
const RFC5321_QUOTEDSTRING = 11;
|
const RFC5321_QUOTEDSTRING = 11;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
namespace Egulias\EmailValidator\Parser;
|
namespace Egulias\EmailValidator\Parser;
|
||||||
|
|
||||||
use Egulias\EmailValidator\EmailLexer;
|
use Egulias\EmailValidator\EmailLexer;
|
||||||
use Egulias\EmailValidator\Parser\Parser;
|
|
||||||
use Egulias\EmailValidator\EmailValidator;
|
use Egulias\EmailValidator\EmailValidator;
|
||||||
|
|
||||||
class DomainPart extends Parser
|
class DomainPart extends Parser
|
||||||
@@ -103,8 +102,9 @@ class DomainPart extends Parser
|
|||||||
protected function doParseDomainPart()
|
protected function doParseDomainPart()
|
||||||
{
|
{
|
||||||
$domain = '';
|
$domain = '';
|
||||||
|
$openedParenthesis = 0;
|
||||||
|
$openBrackets = false;
|
||||||
do {
|
do {
|
||||||
|
|
||||||
$prev = $this->lexer->getPrevious();
|
$prev = $this->lexer->getPrevious();
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_SLASH) {
|
if ($this->lexer->token['type'] === EmailLexer::S_SLASH) {
|
||||||
@@ -113,13 +113,25 @@ class DomainPart extends Parser
|
|||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||||
$this->parseComments();
|
$this->parseComments();
|
||||||
|
$openedParenthesis += $this->getOpenedParenthesis();
|
||||||
$this->lexer->moveNext();
|
$this->lexer->moveNext();
|
||||||
|
$tmpPrev = $this->lexer->getPrevious();
|
||||||
|
if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
|
||||||
|
$openedParenthesis--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
|
||||||
|
if ($openedParenthesis === 0) {
|
||||||
|
throw new \InvalidArgumentException('ERR_UNOPENEDCOMMENT');
|
||||||
|
} else {
|
||||||
|
$openedParenthesis--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->checkConsecutiveDots();
|
$this->checkConsecutiveDots();
|
||||||
$this->checkDomainPartExceptions($prev);
|
$this->checkDomainPartExceptions($prev);
|
||||||
|
|
||||||
if ($this->hasBrackets()) {
|
if ($openBrackets = $this->hasBrackets($openBrackets)) {
|
||||||
$this->parseDomainLiteral();
|
$this->parseDomainLiteral();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +192,7 @@ class DomainPart extends Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->lexer->isNextToken(EmailLexer::S_CR)) {
|
if ($this->lexer->isNextToken(EmailLexer::S_CR)) {
|
||||||
throw new \InvalidArgumentException("ERR_CR_NO_LF");
|
throw new \InvalidArgumentException('ERR_CR_NO_LF');
|
||||||
}
|
}
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) {
|
if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) {
|
||||||
$this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
|
$this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
|
||||||
@@ -276,8 +288,12 @@ class DomainPart extends Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hasBrackets()
|
protected function hasBrackets($openBrackets)
|
||||||
{
|
{
|
||||||
|
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEBRACKET && !$openBrackets) {
|
||||||
|
throw new \InvalidArgumentException('ERR_EXPECTING_OPENBRACKET');
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) {
|
if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace Egulias\EmailValidator\Parser;
|
|||||||
|
|
||||||
use Egulias\EmailValidator\EmailLexer;
|
use Egulias\EmailValidator\EmailLexer;
|
||||||
use Egulias\EmailValidator\EmailValidator;
|
use Egulias\EmailValidator\EmailValidator;
|
||||||
use \InvalidArgumentException;
|
|
||||||
|
|
||||||
class LocalPart extends Parser
|
class LocalPart extends Parser
|
||||||
{
|
{
|
||||||
@@ -12,9 +11,9 @@ class LocalPart extends Parser
|
|||||||
{
|
{
|
||||||
$parseDQuote = true;
|
$parseDQuote = true;
|
||||||
$closingQuote = false;
|
$closingQuote = false;
|
||||||
|
$openedParenthesis = 0;
|
||||||
|
|
||||||
while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
|
while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
|
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
|
||||||
throw new \InvalidArgumentException('ERR_DOT_START');
|
throw new \InvalidArgumentException('ERR_DOT_START');
|
||||||
}
|
}
|
||||||
@@ -26,12 +25,19 @@ class LocalPart extends Parser
|
|||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||||
$this->parseComments();
|
$this->parseComments();
|
||||||
|
$openedParenthesis += $this->getOpenedParenthesis();
|
||||||
|
}
|
||||||
|
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
|
||||||
|
if ($openedParenthesis === 0) {
|
||||||
|
throw new \InvalidArgumentException('ERR_UNOPENEDCOMMENT');
|
||||||
|
} else {
|
||||||
|
$openedParenthesis--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->checkConsecutiveDots();
|
$this->checkConsecutiveDots();
|
||||||
|
|
||||||
if (
|
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
|
||||||
$this->lexer->token['type'] === EmailLexer::S_DOT &&
|
|
||||||
$this->lexer->isNextToken(EmailLexer::S_AT)
|
$this->lexer->isNextToken(EmailLexer::S_AT)
|
||||||
) {
|
) {
|
||||||
throw new \InvalidArgumentException('ERR_DOT_END');
|
throw new \InvalidArgumentException('ERR_DOT_END');
|
||||||
@@ -82,7 +88,7 @@ class LocalPart extends Parser
|
|||||||
$this->lexer->moveNext();
|
$this->lexer->moveNext();
|
||||||
|
|
||||||
if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) {
|
if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) {
|
||||||
throw new InvalidArgumentException("ERR_EXPECTED_ATEXT");
|
throw new \InvalidArgumentException('ERR_EXPECTED_ATEXT');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +96,12 @@ class LocalPart extends Parser
|
|||||||
|
|
||||||
if ($prev['type'] === EmailLexer::S_BACKSLASH) {
|
if ($prev['type'] === EmailLexer::S_BACKSLASH) {
|
||||||
if (!$this->checkDQUOTE(false)) {
|
if (!$this->checkDQUOTE(false)) {
|
||||||
throw new \InvalidArgumentException("ERR_UNCLOSED_DQUOTE");
|
throw new \InvalidArgumentException('ERR_UNCLOSED_DQUOTE');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) {
|
if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) {
|
||||||
throw new \InvalidArgumentException("ERR_EXPECED_AT");
|
throw new \InvalidArgumentException('ERR_EXPECED_AT');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $parseAgain;
|
return $parseAgain;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ abstract class Parser
|
|||||||
{
|
{
|
||||||
protected $warnings = array();
|
protected $warnings = array();
|
||||||
protected $lexer;
|
protected $lexer;
|
||||||
|
protected $openedParenthesis = 0;
|
||||||
|
|
||||||
public function __construct(EmailLexer $lexer)
|
public function __construct(EmailLexer $lexer)
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,13 @@ abstract class Parser
|
|||||||
return $this->warnings;
|
return $this->warnings;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract function parse($str);
|
abstract public function parse($str);
|
||||||
|
|
||||||
|
/** @return int */
|
||||||
|
public function getOpenedParenthesis()
|
||||||
|
{
|
||||||
|
return $this->openedParenthesis;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* validateQuotedPair
|
* validateQuotedPair
|
||||||
@@ -35,15 +42,15 @@ abstract class Parser
|
|||||||
$this->warnings[] = EmailValidator::DEPREC_QP;
|
$this->warnings[] = EmailValidator::DEPREC_QP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string the the comment
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
protected function parseComments()
|
protected function parseComments()
|
||||||
{
|
{
|
||||||
|
$this->openedParenthesis = 1;
|
||||||
$this->isUnclosedComment();
|
$this->isUnclosedComment();
|
||||||
$this->warnings[] = EmailValidator::CFWS_COMMENT;
|
$this->warnings[] = EmailValidator::CFWS_COMMENT;
|
||||||
while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
|
while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
|
||||||
|
if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
|
||||||
|
$this->openedParenthesis++;
|
||||||
|
}
|
||||||
$this->warnEscaping();
|
$this->warnEscaping();
|
||||||
$this->lexer->moveNext();
|
$this->lexer->moveNext();
|
||||||
}
|
}
|
||||||
@@ -75,11 +82,11 @@ abstract class Parser
|
|||||||
$this->checkCRLFInFWS();
|
$this->checkCRLFInFWS();
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_CR) {
|
if ($this->lexer->token['type'] === EmailLexer::S_CR) {
|
||||||
throw new \InvalidArgumentException("ERR_CR_NO_LF");
|
throw new \InvalidArgumentException('ERR_CR_NO_LF');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) {
|
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) {
|
||||||
throw new \InvalidArgumentException("ERR_ATEXT_AFTER_CFWS");
|
throw new \InvalidArgumentException('ERR_ATEXT_AFTER_CFWS');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) {
|
if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) {
|
||||||
@@ -160,7 +167,7 @@ abstract class Parser
|
|||||||
return $hasClosingQuote;
|
return $hasClosingQuote;
|
||||||
}
|
}
|
||||||
$previous = $this->lexer->getPrevious();
|
$previous = $this->lexer->getPrevious();
|
||||||
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) {
|
if ($previous['type'] === EmailLexer::GENERIC && $this->lexer->isNextToken(EmailLexer::GENERIC)) {
|
||||||
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +188,10 @@ abstract class Parser
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($this->lexer->isNextToken(EmailLexer::CRLF)) {
|
if ($this->lexer->isNextToken(EmailLexer::CRLF)) {
|
||||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_X2");
|
throw new \InvalidArgumentException('ERR_FWS_CRLF_X2');
|
||||||
}
|
}
|
||||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
|
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
|
||||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
|
throw new \InvalidArgumentException('ERR_FWS_CRLF_END');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||||||
array('test@email^'),
|
array('test@email^'),
|
||||||
array('test@email%'),
|
array('test@email%'),
|
||||||
array('test@email$'),
|
array('test@email$'),
|
||||||
|
array('test@email.com.au'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +124,8 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||||||
array('test@email>'),
|
array('test@email>'),
|
||||||
array('test@email<'),
|
array('test@email<'),
|
||||||
array('test@email{'),
|
array('test@email{'),
|
||||||
|
array('test@email.com]'),
|
||||||
|
array('test@ema[il.com'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +155,11 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||||||
array(EmailValidator::ERR_DOT_END, 'example@localhost.'),
|
array(EmailValidator::ERR_DOT_END, 'example@localhost.'),
|
||||||
array(EmailValidator::ERR_DOT_END, 'example.@example.co.uk'),
|
array(EmailValidator::ERR_DOT_END, 'example.@example.co.uk'),
|
||||||
array(EmailValidator::ERR_UNCLOSEDCOMMENT, '(example@localhost'),
|
array(EmailValidator::ERR_UNCLOSEDCOMMENT, '(example@localhost'),
|
||||||
|
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'comment)example@localhost'),
|
||||||
|
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example(comment))@localhost'),
|
||||||
|
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example@comment)localhost'),
|
||||||
|
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example@localhost(comment))'),
|
||||||
|
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example@(comment))example.com'),
|
||||||
array(EmailValidator::ERR_UNCLOSEDQUOTEDSTR, '"example@localhost'),
|
array(EmailValidator::ERR_UNCLOSEDQUOTEDSTR, '"example@localhost'),
|
||||||
array(EmailValidator::ERR_EXPECTING_ATEXT, 'exa"mple@localhost'),
|
array(EmailValidator::ERR_EXPECTING_ATEXT, 'exa"mple@localhost'),
|
||||||
//This was the original. But atext is not allowed after \n
|
//This was the original. But atext is not allowed after \n
|
||||||
|
|||||||
Reference in New Issue
Block a user