Compare commits

...

12 Commits

Author SHA1 Message Date
Eduardo Gulias Davis b115554301 Fix Readme style 2024-12-27 01:36:43 +01:00
Eduardo Gulias Davis c67e8e655f Fix Readme style 2024-12-27 01:27:39 +01:00
Eduardo Gulias Davis 2647beedf3 Removed stale changelog 2024-12-27 01:17:25 +01:00
Eduardo Gulias Davis e25ccf7e74 Add depandabot 2024-12-27 00:36:05 +01:00
Eduardo Gulias Davis d379dc240b Update readme 2024-12-27 00:31:08 +01:00
Eduardo Gulias Davis 621d46003b Fix github action (#396)
* Fix github action

* PHP8.4 is too new

* Revert log storage
2024-12-27 00:28:29 +01:00
chris 87db43e4ff docs: fix build status in README.md (#392) 2024-10-16 23:10:38 +02:00
chris c118cc7666 ci: fix deprecation for github actions (#391) 2024-10-08 19:20:25 +02:00
Arnt Gulbrandsen b4a1a0e5a6 Regularise a test. (#389)
The validEmailsProvider contained n-1 valid email addresses and 1 domain;
this replaces the domain with two valid email addresses in that domain, so
that all entries match the name.
2024-09-15 22:03:00 +02:00
Danny van der Sluijs 92c1ab0cc1 Update GitHub Actions to V4 (#383)
* Update tests.yml using actions/checkout@v4

* Update static-analysis.yml usingactions/checkout@v4
2024-05-01 15:20:12 +02:00
Daniel 8775776563 chore: replace scalar with more precise type specification (#369)
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
2023-10-22 23:56:40 +02:00
Andrew Ivchenkov 87b8b8506e Used the most strict psalm level and fixed all psalm errors (#377) 2023-10-15 23:39:26 +02:00
17 changed files with 97 additions and 105 deletions
-1
View File
@@ -3,5 +3,4 @@
/.* export-ignore /.* export-ignore
/phpunit.xml.dist export-ignore /phpunit.xml.dist export-ignore
/psalm.xml export-ignore /psalm.xml export-ignore
/psalm.baseline.xml export-ignore
/README.md export-ignore /README.md export-ignore
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Setup PHP - name: Setup PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
+8 -6
View File
@@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Setup PHP - name: Setup PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
@@ -38,7 +38,7 @@ jobs:
coverage: xdebug coverage: xdebug
- name: Install dependencies - name: Install dependencies
uses: ramsey/composer-install@v2 uses: ramsey/composer-install@v3
with: with:
dependency-versions: ${{ matrix.deps }} dependency-versions: ${{ matrix.deps }}
@@ -47,15 +47,17 @@ jobs:
- name: Execute tests - name: Execute tests
run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml --exclude-group flaky run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml --exclude-group flaky
- name: Coverage - name: Coverage
if: ${{ matrix.php == '8.1' && matrix.deps == 'lowest' }} if: ${{ matrix.php == '8.1' && matrix.deps == 'lowest' }}
shell: bash shell: bash
env: env:
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
run: bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r build/logs/clover.xml run: bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r build/logs/clover.xml
- name: Store artifacts - name: Store artifacts
uses: actions/upload-artifact@v3 if: ${{ matrix.php == '8.1' && matrix.deps == 'lowest' }}
uses: actions/upload-artifact@v4
with: with:
name: logs name: clover.xml
path: build/logs path: build/logs
-32
View File
@@ -1,32 +0,0 @@
# EmailValidator Changelog
## New Features
* Access to local part and domain part from EmailParser
* Validations outside of the scope of the RFC will be considered "extra" validations, thus opening the door for adding new; will live in their own folder "extra" (as requested in #248, #195, #183).
## Breaking changes
* PHP version upgraded to match Symfony's (as of 12/2020).
* DNSCheckValidation now fails for missing MX records. While the RFC argues that the existence of only A records to be valid, starting in v3 they will be considered invalid.
* Emails domain part are now intenteded to be RFC 1035 compliant, rendering previous valid emails (e.g example@examp&) invalid.
## PHP versions upgrade policy
PHP version upgrade requirement will happen via MINOR (3.x) version upgrades of the library, following the adoption level by major frameworks.
## Changes
* #235
* #215
* #130
* #258
* #188
* #181
* #217
* #214
* #249
* #236
* #257
* #210
## Thanks
To contributors, be it with PRs, reporting issues or supporting otherwise.
+53 -31
View File
@@ -1,8 +1,9 @@
# EmailValidator # EmailValidator
[![Build Status](https://github.com/egulias/EmailValidator/workflows/tests/badge.svg?branch=4.x)](https://github.com/egulias/EmailValidator/actions) [![Build Status](https://github.com/egulias/EmailValidator/actions/workflows/tests.yml/badge.svg)](https://github.com/egulias/EmailValidator/actions/workflows/tests.yml)
[![Quality Badge](https://app.codacy.com/project/badge/Grade/55d44898c7e44ebdb4e457523563ad63)](https://app.codacy.com/gh/egulias/EmailValidator/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Quality Badge](https://app.codacy.com/project/badge/Grade/55d44898c7e44ebdb4e457523563ad63)](https://app.codacy.com/gh/egulias/EmailValidator/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[![Test Coverage](https://app.codacy.com/project/badge/Coverage/55d44898c7e44ebdb4e457523563ad63)](https://app.codacy.com/gh/egulias/EmailValidator/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) [![Test Coverage](https://app.codacy.com/project/badge/Coverage/55d44898c7e44ebdb4e457523563ad63)](https://app.codacy.com/gh/egulias/EmailValidator/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
![Latest Release](https://img.shields.io/github/v/release/egulias/EmailValidator)
A library for validating emails against several RFC. A library for validating emails against several RFC.
@@ -10,32 +11,36 @@ A library for validating emails against several RFC.
This library aims to support RFCs: This library aims to support RFCs:
* [5321](https://tools.ietf.org/html/rfc5321), * [5321](https://tools.ietf.org/html/rfc5321),
* [5322](https://tools.ietf.org/html/rfc5322), * [5322](https://tools.ietf.org/html/rfc5322),
* [6530](https://tools.ietf.org/html/rfc6530), * [6530](https://tools.ietf.org/html/rfc6530),
* [6531](https://tools.ietf.org/html/rfc6531), * [6531](https://tools.ietf.org/html/rfc6531),
* [6532](https://tools.ietf.org/html/rfc6532), * [6532](https://tools.ietf.org/html/rfc6532),
* [1035](https://tools.ietf.org/html/rfc1035) * [1035](https://tools.ietf.org/html/rfc1035)
## Supported versions ## Supported versions
**Current major version with full support is v3**
| Version | Released | EOL | Only critical bug fixes | Full | | Version | Released | EOL | Only critical bug fixes | Full |
|:-------:|:----------:|:---:|:-----------------------:|:----:| |:-------:|:----------:|:---:|:-----------------------:|:----:|
| v4.x | 2023/01/07 | - | X | X | |**v4.x** |**2023/01/07** | - | **X** |**X** |
| v3.x | 2020/12/29 | - | X | | | v3.x | 2020/12/29 | YES | | |
| v2.1.x | 2016/05/16 | YES | | | | v2.1.x | 2016/05/16 | YES | | |
| v1.2 | 2013/19/05 | YES | | | | v1.2 | 2013/19/05 | YES | | |
## Requirements ## Requirements
* PHP 8.1 * PHP 8.1
* [Composer](https://getcomposer.org) is required for installation * [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/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)
**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` **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`
## Installation ## Installation
@@ -47,9 +52,12 @@ composer require egulias/email-validator
## Getting Started ## 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 A basic example with the RFC validation
```php ```php
<?php <?php
@@ -60,17 +68,22 @@ $validator = new EmailValidator();
$validator->isValid("example@example.com", new RFCValidation()); //true $validator->isValid("example@example.com", new RFCValidation()); //true
``` ```
### Available validations ### Available validations
1. [RFCValidation](/src/Validation/RFCValidation.php): Standard RFC-like email validation. 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. 2. [NoRFCWarningsValidation](/src/Validation/NoRFCWarningsValidation.php):
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. RFC-like validation that will fail when warnings* are found.
4. [MultipleValidationWithAnd](/src/Validation/MultipleValidationWithAnd.php): It is a validation that operates over other validations performing a logical and (&&) over the result of each validation. 3. [DNSCheckValidation](/src/Validation/DNSCheckValidation.php):
5. [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. Will check if there are DNS records that signal that the server accepts emails. This does not entail that the email exists.
6. [Your own validation](#how-to-extend): You can extend the library behaviour by implementing your own validations. 4. [MultipleValidationWithAnd](/src/Validation/MultipleValidationWithAnd.php):
It is a validation that operates over other validations performing a logical and (&&) over the result of each validation.
5. [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.
6. [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 accepted.
```php ```php
<?php <?php
@@ -90,29 +103,38 @@ $validator->isValid("example@ietf.org", $multipleValidations); //true
``` ```
#### Additional validations #### Additional validations
Validations not present in the RFCs
1. [SpoofCheckValidation](/src/Validation/Extra/SpoofCheckValidation.php): Will check for multi-utf-8 chars that can signal an erroneous email name. Validations not present in the RFCs
1. [SpoofCheckValidation](/src/Validation/Extra/SpoofCheckValidation.php):
Will check for multi-utf-8 chars that can signal an erroneous email name.
### How to extend ### How to extend
It's easy! You just need to implement [EmailValidation](/src/Validation/EmailValidation.php) and you can use your own validation. It's easy! You just need to implement
[EmailValidation](/src/Validation/EmailValidation.php) and you can use your own
validation.
## Contributing ## Contributing
Please follow the [Contribution guide](CONTRIBUTING.md). Is short and simple and will help a lot. Please follow the [Contribution guide](CONTRIBUTING.md).
Is short and simple and will help a lot.
## Other Contributors ## Other Contributors
(You can find current contributors [here](https://github.com/egulias/EmailValidator/graphs/contributors)) (You can find current contributors
[here](https://github.com/egulias/EmailValidator/graphs/contributors))
As this is a port from another library and work, here are other people related to the previous one: As this is a port from another library and work, here are other people related to the previous one:
* Ricard Clau [@ricardclau](https://github.com/ricardclau): Performance against PHP built-in filter_var (v2 and earlier) * Ricard Clau [@ricardclau](https://github.com/ricardclau):
* Josepf Bielawski [@stloyd](https://github.com/stloyd): For its first re-work of Dominic's lib Performance against PHP built-in filter_var (v2 and earlier)
* Dominic Sayers [@dominicsayers](https://github.com/dominicsayers): The original isemail function * Josepf Bielawski [@stloyd](https://github.com/stloyd):
For its first re-work of Dominic's lib
* Dominic Sayers [@dominicsayers](https://github.com/dominicsayers):
The original `isemail` function
## License ## License
Released under the MIT License attached with this code. Released under the MIT License attached with this code.
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.4.0@62db5d4f6a7ae0a20f7cc5a4952d730272fc0863">
<file src="src/Parser/DomainPart.php">
<RedundantConditionGivenDocblockType occurrences="1">
<code>null !== $this-&gt;lexer-&gt;token['type']</code>
</RedundantConditionGivenDocblockType>
</file>
</files>
+5 -10
View File
@@ -3,7 +3,11 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config" xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config ./vendor/vimeo/psalm/config.xsd" xsi:schemaLocation="https://getpsalm.org/schema/config ./vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm.baseline.xml" errorLevel="1"
findUnusedCode="false"
findUnusedPsalmSuppress="true"
disableSuppressAll="true"
findUnusedVariablesAndParams="true"
> >
<projectFiles> <projectFiles>
<directory name="src" /> <directory name="src" />
@@ -11,13 +15,4 @@
<directory name="vendor" /> <directory name="vendor" />
</ignoreFiles> </ignoreFiles>
</projectFiles> </projectFiles>
<issueHandlers>
<DeprecatedMethod>
<errorLevel type="suppress">
<!-- This issue needs to be resolved before upgrading to Lexer 3 -->
<referencedMethod name="Doctrine\Common\Lexer\Token::offsetGet"/>
</errorLevel>
</DeprecatedMethod>
</issueHandlers>
</psalm> </psalm>
+1 -2
View File
@@ -61,7 +61,7 @@ class EmailLexer extends AbstractLexer
/** /**
* US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3) * US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3)
* *
* @var array * @var array<string, int>
*/ */
protected $charValue = [ protected $charValue = [
'{' => self::S_OPENCURLYBRACES, '{' => self::S_OPENCURLYBRACES,
@@ -177,7 +177,6 @@ class EmailLexer extends AbstractLexer
* @throws \UnexpectedValueException * @throws \UnexpectedValueException
* @return boolean * @return boolean
* *
* @psalm-suppress InvalidScalarArgument
*/ */
public function find($type): bool public function find($type): bool
{ {
+2 -1
View File
@@ -8,11 +8,12 @@ use Egulias\EmailValidator\Result\ValidEmail;
use Egulias\EmailValidator\Warning\CFWSNearAt; use Egulias\EmailValidator\Warning\CFWSNearAt;
use Egulias\EmailValidator\Result\InvalidEmail; use Egulias\EmailValidator\Result\InvalidEmail;
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT; use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
use Egulias\EmailValidator\Warning\Warning;
class LocalComment implements CommentStrategy class LocalComment implements CommentStrategy
{ {
/** /**
* @var array * @var array<int, Warning>
*/ */
private $warnings = []; private $warnings = [];
+1
View File
@@ -307,6 +307,7 @@ class DomainPart extends PartParser
{ {
if (preg_match('/[^\x00-\x7F]/', $label)) { if (preg_match('/[^\x00-\x7F]/', $label)) {
idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo); idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
/** @psalm-var array{errors: int, ...} $idnaInfo */
return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG); return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG);
} }
return strlen($label) > self::LABEL_MAX_LENGTH; return strlen($label) > self::LABEL_MAX_LENGTH;
+1 -2
View File
@@ -7,13 +7,12 @@ class DNSGetRecordWrapper
/** /**
* @param string $host * @param string $host
* @param int $type * @param int $type
* *
* @return DNSRecords * @return DNSRecords
*/ */
public function getRecords(string $host, int $type): DNSRecords public function getRecords(string $host, int $type): DNSRecords
{ {
// A workaround to fix https://bugs.php.net/bug.php?id=73149 // A workaround to fix https://bugs.php.net/bug.php?id=73149
/** @psalm-suppress InvalidArgument */
set_error_handler( set_error_handler(
static function (int $errorLevel, string $errorMessage): never { static function (int $errorLevel, string $errorMessage): never {
throw new \RuntimeException("Unable to get DNS record for the host: $errorMessage"); throw new \RuntimeException("Unable to get DNS record for the host: $errorMessage");
+2 -2
View File
@@ -5,7 +5,7 @@ namespace Egulias\EmailValidator\Validation;
class DNSRecords class DNSRecords
{ {
/** /**
* @param array $records * @param list<array<array-key, mixed>> $records
* @param bool $error * @param bool $error
*/ */
public function __construct(private readonly array $records, private readonly bool $error = false) public function __construct(private readonly array $records, private readonly bool $error = false)
@@ -13,7 +13,7 @@ class DNSRecords
} }
/** /**
* @return array * @return list<array<array-key, mixed>>
*/ */
public function getRecords(): array public function getRecords(): array
{ {
@@ -22,9 +22,6 @@ class SpoofCheckValidation implements EmailValidation
} }
} }
/**
* @psalm-suppress InvalidArgument
*/
public function isValid(string $email, EmailLexer $emailLexer) : bool public function isValid(string $email, EmailLexer $emailLexer) : bool
{ {
$checker = new Spoofchecker(); $checker = new Spoofchecker();
+12 -2
View File
@@ -2,16 +2,26 @@
namespace Egulias\EmailValidator\Warning; namespace Egulias\EmailValidator\Warning;
use UnitEnum;
class QuotedPart extends Warning class QuotedPart extends Warning
{ {
public const CODE = 36; public const CODE = 36;
/** /**
* @param scalar|null $prevToken * @param UnitEnum|string|int|null $prevToken
* @param scalar|null $postToken * @param UnitEnum|string|int|null $postToken
*/ */
public function __construct($prevToken, $postToken) public function __construct($prevToken, $postToken)
{ {
if ($prevToken instanceof UnitEnum) {
$prevToken = $prevToken->name;
}
if ($postToken instanceof UnitEnum) {
$postToken = $postToken->name;
}
$this->message = "Deprecated Quoted String found between $prevToken and $postToken"; $this->message = "Deprecated Quoted String found between $prevToken and $postToken";
} }
} }
+2 -2
View File
@@ -7,8 +7,8 @@ class QuotedString extends Warning
public const CODE = 11; public const CODE = 11;
/** /**
* @param scalar $prevToken * @param string|int $prevToken
* @param scalar $postToken * @param string|int $postToken
*/ */
public function __construct($prevToken, $postToken) public function __construct($prevToken, $postToken)
{ {
@@ -32,8 +32,9 @@ class DNSCheckValidationTest extends TestCase
['"Fred\ Bloggs"@ietf.org'], ['"Fred\ Bloggs"@ietf.org'],
['"Joe.\\Blow"@ietf.org'], ['"Joe.\\Blow"@ietf.org'],
// unicide // unicode
['ñandu.cl'], ['info@ñandu.cl'],
['ñandu@ñandu.cl'],
]; ];
} }