Compare commits

..

15 Commits

Author SHA1 Message Date
Eduardo Gulias Davis 01002fa052 update readme with new validator 2021-03-06 19:02:51 +01:00
Eduardo Gulias Davis 8edbe450f1 Merge branch 'message-id-validator' of github.com:egulias/EmailValidator into message-id-validator 2021-03-06 18:15:56 +01:00
Eduardo Gulias Davis c14d12ee17 improve parser from comments 2021-03-06 18:15:18 +01:00
Eduardo Gulias Davis 9320624d03 Merge branch '3.x' of github.com:egulias/EmailValidator into message-id-validator 2021-03-06 18:02:37 +01:00
Eduardo Gulias Davis ab22322b82 Update src/Parser.php
Co-authored-by: Alexander M. Turek <me@derrabus.de>
2021-03-06 17:53:57 +01:00
Eduardo Gulias Davis 44d20e3440 Update src/Parser.php
Co-authored-by: Alexander M. Turek <me@derrabus.de>
2021-03-06 17:53:37 +01:00
Eduardo Gulias Davis c5d6b8c16a Suppress psalm inheritance over tokens and dependencies 2021-02-28 17:52:27 +01:00
Eduardo Gulias Davis b03e9c935f comments are not allowed in IDLeft for message-id 2021-02-28 17:02:00 +01:00
Eduardo Gulias Davis 8fb7a88965 Better naming 2021-02-28 16:28:48 +01:00
Eduardo Gulias Davis 06579b96ca psaml errors 2021-02-28 16:26:08 +01:00
Eduardo Gulias Davis b79cd8f033 change left for right, which is the right one 2021-02-28 16:05:41 +01:00
Eduardo Gulias Davis 07464f87c8 MessageIDParser passing tests. 2021-02-21 22:41:37 +01:00
Eduardo Gulias Davis b80f568f75 Improved EmailParser to remove leaked logic. User of lexer recorder within parsers. 2021-02-21 22:06:38 +01:00
Eduardo Gulias Davis 03a062e9e4 Improve domain valid tokens 2021-02-20 17:46:52 +01:00
Eduardo Gulias Davis 1cb5b2a402 scafolding for MessageID validation 2021-02-07 16:15:32 +01:00
24 changed files with 972 additions and 1518 deletions
+2 -3
View File
@@ -3,12 +3,11 @@ imports:
build:
environment:
php: '7.3'
php: '7.2.13'
tests:
override:
-
command: 'vendor/bin/phpunit --coverage-clover=clover.xml --exclude-group flaky'
command: 'vendor/bin/phpunit --coverage-clover=clover.xml --exclude-group slow'
coverage:
file: 'clover.xml'
format: 'clover'
- php-scrutinizer-run
+8 -4
View File
@@ -2,20 +2,24 @@ language: php
matrix:
include:
- php: 7.2
env:
- psalm=yes
dist: bionic
- php: 7.3
dist: bionic
env:
- psalm=yes
dist: bionic
- php: 7.4
dist: bionic
env:
- psalm=yes
dist: bionic
- php: 8.0
env:
- psalm=yes
dist: bionic
#ppc64le support code
- php: 7.3
- php: 7.2
arch: ppc64le
env:
- psalm=yes
@@ -34,7 +38,7 @@ before_script:
- mkdir -p build/logs
script:
- vendor/bin/phpunit --coverage-clover build/logs/clover.xml --exclude-group flaky
- vendor/bin/phpunit --coverage-clover build/logs/clover.xml --exclude-group slow
- if [ "$psalm" = "yes" ]; then vendor/bin/psalm; fi
after_script:
+4 -4
View File
@@ -1,6 +1,6 @@
# Contributing
When contributing to this repository make sure to follow the Pull request process below.
When contributing to this repository make sure to follow the Pull request process below.
Reduce to the minimum 3rd party dependencies.
Please note we have a [code of conduct](#Code of Conduct), please follow it in all your interactions with the project.
@@ -14,7 +14,7 @@ When doing a PR to v2 remember that you also have to do the PR port to v3, or te
3. Describe the changes you are proposing
1. If adding an extra validation state the benefits of adding it and the problem is solving
2. Document in the readme, by adding it to the list
4. Provide appropriate tests for the code you are submitting: aim to keep the existing coverage percentage.
4. Provide appropiate tests for the code you are submitting: aim to keep the existing coverage percentage.
5. Add your Twitter handle (if you have) so we can thank you there.
## License
@@ -139,11 +139,11 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
Community Impact Guidelines were inspired by
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
+8 -7
View File
@@ -1,8 +1,9 @@
# EmailValidator
[![Build Status](https://app.travis-ci.com/egulias/EmailValidator.svg?branch=3.x)](https://app.travis-ci.com/github/egulias/EmailValidator)
[![Build Status](https://travis-ci.org/egulias/EmailValidator.svg?branch=3.x)](https://travis-ci.org/egulias/EmailValidator)
[![Code Quality](https://scrutinizer-ci.com/g/egulias/EmailValidator/badges/quality-score.png?b=3.x)](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=3.x)
[![Test Coverage](https://scrutinizer-ci.com/g/egulias/EmailValidator/badges/coverage.png?b=3.x)](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=3.x)
[![SymfonyInsight](https://insight.symfony.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6/mini.svg)](https://insight.symfony.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)
A library for validating emails against several RFC.
@@ -19,7 +20,7 @@ This library aims to support RFCs:
## Supported versions
**Current major version with full support is v3**
**Curent major version with full support is v3**
| Version | Released | EOL | Only critical bug fixes | Full |
| ---- | :----: | :----: | :----: | :----: |
@@ -32,7 +33,7 @@ This library aims to support RFCs:
* PHP 7.2
* [Composer](https://getcomposer.org) is required for installation
* [Spoofchecking](/src/Validation/Extra/SpoofCheckValidation.php) and [DNSCheckValidation](/src/Validation/DNSCheckValidation.php) validation requires that your PHP system has the [PHP Internationalization Libraries](https://php.net/manual/en/book.intl.php) (also known as PHP Intl)
* [Spoofchecking](/src/Validation/SpoofCheckValidation.php) and [DNSCheckValidation](/src/Validation/DNSCheckValidation.php) validation requires that your PHP system has the [PHP Internationalization Libraries](https://php.net/manual/en/book.intl.php) (also known as PHP Intl)
**Note**: `PHP version upgrades will happen to accomodate to the pace of major frameworks. Minor versions bumps will go via minor versions of this library (i.e: PHP7.3 -> v3.x+1). Major versions will go with major versions of the library`
@@ -46,7 +47,7 @@ composer require egulias/email-validator
## Getting Started ##
`EmailValidator` requires you to decide which (or combination of them) validation/s strategy/ies you'd like to follow for each [validation](#available-validations).
`EmailValidator`requires you to decide which (or combination of them) validation/s strategy/ies you'd like to follow for each [validation](#available-validations).
A basic example with the RFC validation
```php
@@ -64,12 +65,12 @@ $validator->isValid("example@example.com", new RFCValidation()); //true
1. [RFCValidation](/src/Validation/RFCValidation.php): Standard RFC-like email validation.
2. [NoRFCWarningsValidation](/src/Validation/NoRFCWarningsValidation.php): RFC-like validation that will fail when warnings* are found.
3. [DNSCheckValidation](/src/Validation/DNSCheckValidation.php): Will check if there are DNS records that signal that the server accepts emails. This does not entail that the email exists.
3. [DNSCheckValidation](/src/Validation/DNSCheckValidation.php): Will check if there are DNS records that signal that the server accepts emails. This does not entails that the email exists.
5. [MultipleValidationWithAnd](/src/Validation/MultipleValidationWithAnd.php): It is a validation that operates over other validations performing a logical and (&&) over the result of each validation.
6. [MessageIDValidation](/src/Validation/MessageIDValidation.php): Follows [RFC2822 for message-id](https://tools.ietf.org/html/rfc2822#section-3.6.4) to validate that field, that has some differences in the domain part.
7. [Your own validation](#how-to-extend): You can extend the library behaviour by implementing your own validations.
*warnings: Warnings are deviations from the RFC that in a broader interpretation are accepted.
*warnings: Warnings are deviations from the RFC that in a broader interpretation are acceptded.
```php
<?php
@@ -84,7 +85,7 @@ $multipleValidations = new MultipleValidationWithAnd([
new RFCValidation(),
new DNSCheckValidation()
]);
//ietf.org has MX records signaling a server with email capabilities
//ietf.org has MX records signaling a server with email capabilites
$validator->isValid("example@ietf.org", $multipleValidations); //true
```
Generated
+748 -1282
View File
File diff suppressed because it is too large Load Diff
+30 -16
View File
@@ -1,17 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" executionOrder="defects" processIsolation="false" stopOnFailure="false">
<coverage>
<include>
<directory>./src/</directory>
</include>
<exclude>
<directory suffix=".php">./src/Result/Reason</directory>
</exclude>
</coverage>
<testsuites>
<testsuite name="EmailValidator Test Suite">
<directory>./tests/EmailValidator</directory>
<exclude>./vendor/</exclude>
</testsuite>
</testsuites>
</phpunit>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
executionOrder="defects"
processIsolation="false"
stopOnFailure="false"
>
<testsuites>
<testsuite name="EmailValidator Test Suite">
<directory>./tests/EmailValidator</directory>
<exclude>./vendor/</exclude>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/</directory>
<exclude>
<directory suffix=".php">./src/Result/Reason</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
+102 -80
View File
@@ -61,7 +61,7 @@ class EmailLexer extends AbstractLexer
*
* @var array
*/
protected $charValue = [
protected $charValue = array(
'{' => self::S_OPENCURLYBRACES,
'}' => self::S_CLOSECURLYBRACES,
'(' => self::S_OPENPARENTHESIS,
@@ -105,29 +105,11 @@ class EmailLexer extends AbstractLexer
'?' => self::QUESTIONMARK,
'#' => self::NUMBER_SIGN,
'¡' => self::INVERT_EXCLAMATION,
];
);
const INVALID_CHARS_REGEX = "/[^\p{S}\p{C}\p{Cc}]+/iu";
const VALID_UTF8_REGEX = '/\p{Cc}+/u';
const CATCHABLE_PATTERNS = [
'[a-zA-Z]+[46]?', //ASCII and domain literal
'[^\x00-\x7F]', //UTF-8
'[0-9]+',
'\r\n',
'::',
'\s+?',
'.',
];
const NON_CATCHABLE_PATTERNS = [
'[\xA0-\xff]+',
];
const MODIFIERS = 'iu';
/** @var bool */
/**
* @var bool
*/
protected $hasInvalidTokens = false;
/**
@@ -155,17 +137,23 @@ class EmailLexer extends AbstractLexer
*/
public $lookahead;
/** @psalm-var array{value:'', type:null, position:0} */
/**
* @psalm-var array{value:'', type:null, position:0}
*/
private static $nullToken = [
'value' => '',
'type' => null,
'position' => 0,
];
/** @var string */
/**
* @var string
*/
private $accumulator = '';
/** @var bool */
/**
* @var bool
*/
private $hasToRecord = false;
public function __construct()
@@ -174,13 +162,24 @@ class EmailLexer extends AbstractLexer
$this->lookahead = null;
}
public function reset() : void
/**
* @return void
*/
public function reset()
{
$this->hasInvalidTokens = false;
parent::reset();
$this->previous = $this->token = self::$nullToken;
}
/**
* @return bool
*/
public function hasInvalidTokens()
{
return $this->hasInvalidTokens;
}
/**
* @param int $type
* @throws \UnexpectedValueException
@@ -188,7 +187,7 @@ class EmailLexer extends AbstractLexer
*
* @psalm-suppress InvalidScalarArgument
*/
public function find($type) : bool
public function find($type)
{
$search = clone $this;
$search->skipUntil($type);
@@ -199,24 +198,30 @@ class EmailLexer extends AbstractLexer
return true;
}
/**
* getPrevious
*
* @return array
*/
public function getPrevious()
{
return $this->previous;
}
/**
* moveNext
*
* @return boolean
*/
public function moveNext() : bool
public function moveNext()
{
if ($this->hasToRecord && $this->previous === self::$nullToken) {
$this->accumulator .= $this->token['value'];
}
$this->previous = $this->token;
if($this->lookahead === null) {
$this->lookahead = self::$nullToken;
}
$hasNext = parent::moveNext();
$this->token = $this->token ?: self::$nullToken;
if ($this->hasToRecord) {
$this->accumulator .= $this->token['value'];
@@ -225,6 +230,36 @@ class EmailLexer extends AbstractLexer
return $hasNext;
}
/**
* Lexical catchable patterns.
*
* @return string[]
*/
protected function getCatchablePatterns()
{
return array(
'[a-zA-Z]+[46]?', //ASCII and domain literal
'[^\x00-\x7F]', //UTF-8
'[0-9]+',
'\r\n',
'::',
'\s+?',
'.',
);
}
/**
* Lexical non-catchable patterns.
*
* @return string[]
*/
protected function getNonCatchablePatterns()
{
return [
'[\xA0-\xff]+',
];
}
/**
* Retrieve token type. Also processes the token value if necessary.
*
@@ -257,64 +292,51 @@ class EmailLexer extends AbstractLexer
return self::GENERIC;
}
protected function isValid(string $value) : bool
{
return isset($this->charValue[$value]);
}
protected function isNullType(string $value) : bool
{
return $value === "\0";
}
protected function isInvalidChar(string $value) : bool
{
return !preg_match(self::INVALID_CHARS_REGEX, $value);
if(preg_match("/[^\p{S}\p{C}\p{Cc}]+/iu", $value) ) {
return false;
}
return true;
}
protected function isValid(string $value) : bool
{
if (isset($this->charValue[$value])) {
return true;
}
return false;
}
/**
* @param string $value
* @return bool
*/
protected function isNullType($value)
{
if ($value === "\0") {
return true;
}
return false;
}
protected function isUTF8Invalid(string $value) : bool
{
return preg_match(self::VALID_UTF8_REGEX, $value) !== false;
}
if (preg_match('/\p{Cc}+/u', $value)) {
return true;
}
public function hasInvalidTokens() : bool
{
return $this->hasInvalidTokens;
return false;
}
/**
* getPrevious
*
* @return array
* @return string
*/
public function getPrevious() : array
protected function getModifiers()
{
return $this->previous;
}
/**
* Lexical catchable patterns.
*
* @return string[]
*/
protected function getCatchablePatterns() : array
{
return self::CATCHABLE_PATTERNS;
}
/**
* Lexical non-catchable patterns.
*
* @return string[]
*/
protected function getNonCatchablePatterns() : array
{
return self::NON_CATCHABLE_PATTERNS;
}
protected function getModifiers() : string
{
return self::MODIFIERS;
return 'iu';
}
public function getAccumulatedValues() : string
+1
View File
@@ -3,6 +3,7 @@
namespace Egulias\EmailValidator;
use Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Result\Result;
use Egulias\EmailValidator\Parser\IDLeftPart;
use Egulias\EmailValidator\Parser\IDRightPart;
+15 -14
View File
@@ -22,15 +22,6 @@ use Egulias\EmailValidator\Warning\DomainLiteral as WarningDomainLiteral;
class DomainLiteral extends PartParser
{
const IPV4_REGEX = '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
const OBSOLETE_WARNINGS = [
EmailLexer::INVALID,
EmailLexer::C_DEL,
EmailLexer::S_LF,
EmailLexer::S_BACKSLASH
];
public function parse() : Result
{
$this->addTagWarnings();
@@ -147,8 +138,11 @@ class DomainLiteral extends PartParser
public function convertIPv4ToIPv6(string $addressLiteralIPv4) : string
{
$matchesIP = [];
$IPv4Match = preg_match(self::IPV4_REGEX, $addressLiteralIPv4, $matchesIP);
$matchesIP = array();
$IPv4Match = preg_match(
'/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/',
$addressLiteralIPv4,
$matchesIP);
// Extract IPv4 part from the end of the address-literal (if there is one)
if ($IPv4Match > 0) {
@@ -170,8 +164,11 @@ class DomainLiteral extends PartParser
*/
protected function checkIPV4Tag($addressLiteral) : bool
{
$matchesIP = [];
$IPv4Match = preg_match(self::IPV4_REGEX, $addressLiteral, $matchesIP);
$matchesIP = array();
$IPv4Match = preg_match(
'/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/',
$addressLiteral,
$matchesIP);
// Extract IPv4 part from the end of the address-literal (if there is one)
@@ -189,7 +186,11 @@ class DomainLiteral extends PartParser
private function addObsoleteWarnings() : void
{
if(in_array($this->lexer->token['type'], self::OBSOLETE_WARNINGS)) {
if ($this->lexer->token['type'] === EmailLexer::INVALID ||
$this->lexer->token['type'] === EmailLexer::C_DEL ||
$this->lexer->token['type'] === EmailLexer::S_LF ||
$this->lexer->token['type'] === EmailLexer::S_BACKSLASH
) {
$this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT();
}
}
+1 -1
View File
@@ -280,9 +280,9 @@ class DomainPart extends PartParser
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT || $isEndOfDomain) {
if ($this->isLabelTooLong($this->label)) {
$this->label = '';
return new InvalidEmail(new LabelTooLong(), $this->lexer->token['value']);
}
$this->label = '';
}
$this->label .= $this->lexer->token['value'];
return new ValidEmail();
+4 -5
View File
@@ -19,19 +19,18 @@ class DoubleQuote extends PartParser
$validQuotedString = $this->checkDQUOTE();
if($validQuotedString->isInvalid()) return $validQuotedString;
$special = [
$special = array(
EmailLexer::S_CR => true,
EmailLexer::S_HTAB => true,
EmailLexer::S_LF => true
];
);
$invalid = [
$invalid = array(
EmailLexer::C_NUL => true,
EmailLexer::S_HTAB => true,
EmailLexer::S_CR => true,
EmailLexer::S_LF => true
];
);
$setSpecialsWarning = true;
$this->lexer->moveNext();
+5 -9
View File
@@ -15,14 +15,6 @@ use Egulias\EmailValidator\Result\ValidEmail;
class FoldingWhiteSpace extends PartParser
{
const FWS_TYPES = [
EmailLexer::S_SP,
EmailLexer::S_HTAB,
EmailLexer::S_CR,
EmailLexer::S_LF,
EmailLexer::CRLF
];
public function parse() : Result
{
if (!$this->isFWS()) {
@@ -81,6 +73,10 @@ class FoldingWhiteSpace extends PartParser
return false;
}
return in_array($this->lexer->token['type'], self::FWS_TYPES);
return $this->lexer->token['type'] === EmailLexer::S_SP ||
$this->lexer->token['type'] === EmailLexer::S_HTAB ||
$this->lexer->token['type'] === EmailLexer::S_CR ||
$this->lexer->token['type'] === EmailLexer::S_LF ||
$this->lexer->token['type'] === EmailLexer::CRLF;
}
}
+2 -2
View File
@@ -12,14 +12,14 @@ class IDRightPart extends DomainPart
{
protected function validateTokens(bool $hasComments) : Result
{
$invalidDomainTokens = [
$invalidDomainTokens = array(
EmailLexer::S_DQUOTE => true,
EmailLexer::S_SQUOTE => true,
EmailLexer::S_BACKTICK => true,
EmailLexer::S_SEMICOLON => true,
EmailLexer::S_GREATERTHAN => true,
EmailLexer::S_LOWERTHAN => true,
];
);
if (isset($invalidDomainTokens[$this->lexer->token['type']])) {
return new InvalidEmail(new ExpectingATEXT('Invalid token in domain: ' . $this->lexer->token['value']), $this->lexer->token['value']);
+11 -12
View File
@@ -15,17 +15,6 @@ use Egulias\EmailValidator\Parser\CommentStrategy\LocalComment;
class LocalPart extends PartParser
{
const INVALID_TOKENS = [
EmailLexer::S_COMMA => EmailLexer::S_COMMA,
EmailLexer::S_CLOSEBRACKET => EmailLexer::S_CLOSEBRACKET,
EmailLexer::S_OPENBRACKET => EmailLexer::S_OPENBRACKET,
EmailLexer::S_GREATERTHAN => EmailLexer::S_GREATERTHAN,
EmailLexer::S_LOWERTHAN => EmailLexer::S_LOWERTHAN,
EmailLexer::S_COLON => EmailLexer::S_COLON,
EmailLexer::S_SEMICOLON => EmailLexer::S_SEMICOLON,
EmailLexer::INVALID => EmailLexer::INVALID
];
/**
* @var string
*/
@@ -99,7 +88,17 @@ class LocalPart extends PartParser
protected function validateTokens(bool $hasComments) : Result
{
if (isset(self::INVALID_TOKENS[$this->lexer->token['type']])) {
$invalidTokens = array(
EmailLexer::S_COMMA => EmailLexer::S_COMMA,
EmailLexer::S_CLOSEBRACKET => EmailLexer::S_CLOSEBRACKET,
EmailLexer::S_OPENBRACKET => EmailLexer::S_OPENBRACKET,
EmailLexer::S_GREATERTHAN => EmailLexer::S_GREATERTHAN,
EmailLexer::S_LOWERTHAN => EmailLexer::S_LOWERTHAN,
EmailLexer::S_COLON => EmailLexer::S_COLON,
EmailLexer::S_SEMICOLON => EmailLexer::S_SEMICOLON,
EmailLexer::INVALID => EmailLexer::INVALID
);
if (isset($invalidTokens[$this->lexer->token['type']])) {
return new InvalidEmail(new ExpectingATEXT('Invalid token found'), $this->lexer->token['value']);
}
return new ValidEmail();
+2 -4
View File
@@ -2,7 +2,7 @@
namespace Egulias\EmailValidator\Result;
use Egulias\EmailValidator\Result\Reason\EmptyReason;
use Egulias\EmailValidator\Result\InvalidEmail;
use Egulias\EmailValidator\Result\Reason\Reason;
/**
@@ -34,9 +34,7 @@ class MultipleErrors extends InvalidEmail
public function reason() : Reason
{
return 0 !== count($this->reasons)
? current($this->reasons)
: new EmptyReason();
return $this->reasons[0];
}
public function description() : string
-16
View File
@@ -1,16 +0,0 @@
<?php
namespace Egulias\EmailValidator\Result\Reason;
class EmptyReason implements Reason
{
public function code() : int
{
return 0;
}
public function description() : string
{
return 'Empty reason';
}
}
+1 -1
View File
@@ -11,6 +11,6 @@ class UnOpenedComment implements Reason
public function description(): string
{
return 'Missing opening comment parentheses - https://tools.ietf.org/html/rfc5322#section-3.2.2';
return 'Missing openning comment parentheses - https://tools.ietf.org/html/rfc5322#section-3.2.2';
}
}
+23 -24
View File
@@ -17,29 +17,6 @@ class DNSCheckValidation implements EmailValidation
*/
protected const DNS_RECORD_TYPES_TO_CHECK = DNS_MX + DNS_A + DNS_AAAA;
/**
* Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2),
* mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G)
*/
const RESERVED_DNS_TOP_LEVEL_NAMES = [
// Reserved Top Level DNS Names
'test',
'example',
'invalid',
'localhost',
// mDNS
'local',
// Private DNS Namespaces
'intranet',
'internal',
'private',
'corp',
'home',
'lan',
];
/**
* @var array
*/
@@ -55,6 +32,7 @@ class DNSCheckValidation implements EmailValidation
*/
private $mxRecords = [];
public function __construct()
{
if (!function_exists('idn_to_ascii')) {
@@ -75,8 +53,29 @@ class DNSCheckValidation implements EmailValidation
// Get the domain parts
$hostParts = explode('.', $host);
// Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2),
// mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G)
$reservedTopLevelDnsNames = [
// Reserved Top Level DNS Names
'test',
'example',
'invalid',
'localhost',
// mDNS
'local',
// Private DNS Namespaces
'intranet',
'internal',
'private',
'corp',
'home',
'lan',
];
$isLocalDomain = count($hostParts) <= 1;
$isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], self::RESERVED_DNS_TOP_LEVEL_NAMES, true);
$isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], $reservedTopLevelDnsNames, true);
// Exclude reserved top level DNS names
if ($isLocalDomain || $isReservedTopLevel) {
+1 -1
View File
@@ -21,7 +21,7 @@ interface EmailValidation
/**
* Returns the validation error.
*
* @return InvalidEmail|null
* @return InvalidEmail
*/
public function getError() : ?InvalidEmail;
+1 -1
View File
@@ -10,7 +10,7 @@ use Egulias\EmailValidator\Result\MultipleErrors;
class MultipleValidationWithAnd implements EmailValidation
{
/**
* If one of validations fails, the remaining validations will be skipped.
* If one of validations fails, the remaining validations will be skept.
* This means MultipleErrors will only contain a single error, the first found.
*/
const STOP_ON_ERROR = 0;
+1 -1
View File
@@ -42,6 +42,6 @@ abstract class Warning
public function __toString()
{
return $this->message() . " rfc: " . $this->rfcNumber . "internal code: " . static::CODE;
return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE;
}
}
@@ -2,11 +2,10 @@
namespace Egulias\EmailValidator\Tests\EmailValidator\Reason;
use PHPUnit\Framework\TestCase;
use Egulias\EmailValidator\Result\MultipleErrors;
use Egulias\EmailValidator\Result\Reason\EmptyReason;
use Egulias\EmailValidator\Tests\EmailValidator\Dummy\AnotherDummyReason;
use Egulias\EmailValidator\Tests\EmailValidator\Dummy\DummyReason;
use PHPUnit\Framework\TestCase;
class MultipleErrorsTest extends TestCase
{
@@ -36,31 +35,4 @@ class MultipleErrorsTest extends TestCase
$this->assertEquals($expectedReason, $multiError->description());
$this->assertEquals($error1, $multiError->reason());
}
public function testRetrieveFirstReasonWithReasonCodeEqualsZero(): void
{
$error1 = new DummyReason();
$multiError = new MultipleErrors();
$multiError->addReason($error1);
$this->assertEquals($error1, $multiError->reason());
}
public function testRetrieveFirstReasonWithReasonCodeDistinctToZero(): void
{
$error1 = new AnotherDummyReason();
$multiError = new MultipleErrors();
$multiError->addReason($error1);
$this->assertEquals($error1, $multiError->reason());
}
public function testRetrieveFirstReasonWithNoReasonAdded()
{
$emptyReason = new EmptyReason();
$multiError = new MultipleErrors();
$this->assertEquals($emptyReason, $multiError->reason());
}
}
@@ -109,7 +109,7 @@ class DNSCheckValidationTest extends TestCase
}
/**
* @group flaky
* @group slow
*/
public function testUnableToGetDNSRecord()
{
@@ -76,7 +76,6 @@ class RFCValidationDomainPartTest extends TestCase
['validipv4@[127.0.0.0]'],
['validipv4@127.0.0.0'],
['withhyphen@domain-exam.com'],
['valid_long_domain@71846jnrsoj91yfhc18rkbrf90ue3onl8y46js38kae8inz0t1.5a-xdycuau.na49.le.example.com']
);
}