mirror of
https://github.com/egulias/EmailValidator.git
synced 2026-08-31 20:50:01 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de448a30fa | |||
| a7b385301d | |||
| f6447f8b99 | |||
| d4001715b2 | |||
| 4b7fcf6796 | |||
| 2a1145ffbf | |||
| af864423f5 | |||
| 12f16f70aa | |||
| 0afaa6a3b6 | |||
| 5631c3fe2e | |||
| c383717824 | |||
| aabed98198 | |||
| 3b0fd01aa3 | |||
| 4efe697504 | |||
| 7a4c5714f5 | |||
| 0a26375a7a | |||
| 773fe5f4a3 | |||
| 4a209951ee | |||
| a8b0bab5aa | |||
| cc0b91f311 | |||
| 8092ecaeff | |||
| f19defb373 | |||
| 9a518fb1bd | |||
| 9b184605e8 | |||
| 7a4842c60f | |||
| 687ab6a66e | |||
| 116d4054fa | |||
| af9417f765 | |||
| ab0bcfb424 | |||
| 833b3e7924 | |||
| fec1609458 | |||
| add559b99c | |||
| 19e390d863 | |||
| 5320c26b38 | |||
| 3b6ab3bcd5 | |||
| 7a64ea18af | |||
| 9103f4f99b | |||
| 3f623e9006 | |||
| 833eb65135 | |||
| e61481fefb |
+19
-3
@@ -1,3 +1,5 @@
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
php:
|
||||
@@ -5,11 +7,25 @@ php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- wget http://getcomposer.org/composer.phar
|
||||
- php composer.phar install --dev --no-interaction
|
||||
env:
|
||||
global:
|
||||
- deps=no
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.3
|
||||
env: deps=low
|
||||
- php: 5.6
|
||||
env: deps=high
|
||||
|
||||
install:
|
||||
- if [ "$deps" = "no" ]; then composer install; fi
|
||||
- if [ "$deps" = "low" ]; then composer update --prefer-lowest; fi
|
||||
- if [ "$deps" = "high" ]; then composer update; fi
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
|
||||
@@ -1,56 +1,59 @@
|
||||
EmailValidator [](https://travis-ci.org/egulias/EmailValidator) [](https://coveralls.io/r/egulias/EmailValidator?branch=master) [](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)[](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master)
|
||||
=============================
|
||||
|
||||
##Installation##
|
||||
|
||||
Run the command below to install via Composer
|
||||
|
||||
```shell
|
||||
composer require egulias/email-validator
|
||||
```
|
||||
|
||||
##Usage##
|
||||
|
||||
Simple example:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
|
||||
$validator = new EmailValidator;
|
||||
if ($validator->isValid($email)) {
|
||||
echo $email . ' is a valid email address';
|
||||
}
|
||||
```
|
||||
|
||||
More advanced example (returns detailed diagnostic error codes):
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
|
||||
$validator = new EmailValidator;
|
||||
$email = 'dominic@sayers.cc';
|
||||
$result = $validator->isValid($email);
|
||||
|
||||
if ($result) {
|
||||
echo $email . ' is a valid email address';
|
||||
} else if ($validator->hasWarnings()) {
|
||||
echo 'Warning! ' . $email . ' has unusual/deprecated features (result code ' . var_export($validator->getWarnings(), true) . ')';
|
||||
} else {
|
||||
echo $email . ' is not a valid email address (result code ' . $validator->getError() . ')';
|
||||
}
|
||||
```
|
||||
|
||||
##Contributors##
|
||||
As this is a port from another library and work, here are other people related to the previous:
|
||||
|
||||
* Ricard Clau [@ricardclau](http://github.com/ricardclau): Performance against PHP built-in filter_var
|
||||
* Josepf Bielawski [@stloyd](http://github.com/stloyd): For its first re-work of Dominic's lib
|
||||
* Dominic Sayers [@dominicsayers](http://github.com/dominicsayers): The original isemail function
|
||||
|
||||
##License##
|
||||
Released under the MIT License attached with this code.
|
||||
|
||||
#EmailValidator
|
||||
[](https://travis-ci.org/egulias/EmailValidator) [](https://coveralls.io/r/egulias/EmailValidator?branch=master) [](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master) [](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)
|
||||
=============================
|
||||
With the help of
|
||||
|
||||

|
||||
##Installation##
|
||||
|
||||
Run the command below to install via Composer
|
||||
|
||||
```shell
|
||||
composer require egulias/email-validator "~1.2"
|
||||
```
|
||||
|
||||
##Usage##
|
||||
|
||||
Simple example:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
|
||||
$validator = new EmailValidator;
|
||||
if ($validator->isValid($email)) {
|
||||
echo $email . ' is a valid email address';
|
||||
}
|
||||
```
|
||||
|
||||
More advanced example (returns detailed diagnostic error codes):
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
|
||||
$validator = new EmailValidator;
|
||||
$email = 'dominic@sayers.cc';
|
||||
$result = $validator->isValid($email);
|
||||
|
||||
if ($result) {
|
||||
echo $email . ' is a valid email address';
|
||||
} else if ($validator->hasWarnings()) {
|
||||
echo 'Warning! ' . $email . ' has unusual/deprecated features (result code ' . var_export($validator->getWarnings(), true) . ')';
|
||||
} else {
|
||||
echo $email . ' is not a valid email address (result code ' . $validator->getError() . ')';
|
||||
}
|
||||
```
|
||||
|
||||
##Contributors##
|
||||
As this is a port from another library and work, here are other people related to the previous:
|
||||
|
||||
* Ricard Clau [@ricardclau](http://github.com/ricardclau): Performance against PHP built-in filter_var
|
||||
* Josepf Bielawski [@stloyd](http://github.com/stloyd): For its first re-work of Dominic's lib
|
||||
* Dominic Sayers [@dominicsayers](http://github.com/dominicsayers): The original isemail function
|
||||
|
||||
##License##
|
||||
Released under the MIT License attached with this code.
|
||||
|
||||
|
||||
+5
-4
@@ -3,22 +3,23 @@
|
||||
"description": "A library for validating emails",
|
||||
"homepage": "https://github.com/egulias/EmailValidator",
|
||||
"type": "Library",
|
||||
"keywords": ["email", "validation", "validator"],
|
||||
"keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Eduardo Gulias Davis"}
|
||||
],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3.x-dev"
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">= 5.3.3",
|
||||
"doctrine/lexer": "~1.0"
|
||||
"doctrine/lexer": "~1.0,>=1.0.1"
|
||||
},
|
||||
"require-dev" : {
|
||||
"satooshi/php-coveralls": "dev-master"
|
||||
"satooshi/php-coveralls": "dev-master",
|
||||
"phpunit/phpunit": "~4.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
|
||||
Generated
+1037
-123
File diff suppressed because it is too large
Load Diff
@@ -1,89 +1,89 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>The BNF from RFC 5321 defining parts of a valid SMTP address</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre style="font-size:11px;">
|
||||
Mailbox = Local-part "@" ( Domain / address-literal )
|
||||
|
||||
Local-part = Dot-string / Quoted-string
|
||||
; MAY be case-sensitive
|
||||
|
||||
|
||||
Dot-string = Atom *("." Atom)
|
||||
|
||||
Atom = 1*atext
|
||||
|
||||
Quoted-string = DQUOTE *QcontentSMTP DQUOTE
|
||||
|
||||
QcontentSMTP = qtextSMTP / quoted-pairSMTP
|
||||
|
||||
quoted-pairSMTP = %d92 %d32-126
|
||||
; i.e., backslash followed by any ASCII
|
||||
; graphic (including itself) or SPace
|
||||
|
||||
qtextSMTP = %d32-33 / %d35-91 / %d93-126
|
||||
; i.e., within a quoted string, any
|
||||
; ASCII graphic or space is permitted
|
||||
; without blackslash-quoting except
|
||||
; double-quote and the backslash itself.
|
||||
|
||||
Domain = sub-domain *("." sub-domain)
|
||||
|
||||
sub-domain = Let-dig [Ldh-str]
|
||||
|
||||
Let-dig = ALPHA / DIGIT
|
||||
|
||||
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
|
||||
|
||||
address-literal = "[" ( IPv4-address-literal /
|
||||
IPv6-address-literal /
|
||||
General-address-literal ) "]"
|
||||
; See Section 4.1.3
|
||||
|
||||
IPv4-address-literal = Snum 3("." Snum)
|
||||
|
||||
IPv6-address-literal = "IPv6:" IPv6-addr
|
||||
|
||||
General-address-literal = Standardized-tag ":" 1*dcontent
|
||||
|
||||
Standardized-tag = Ldh-str
|
||||
; Standardized-tag MUST be specified in a
|
||||
; Standards-Track RFC and registered with IANA
|
||||
|
||||
dcontent = %d33-90 / ; Printable US-ASCII
|
||||
%d94-126 ; excl. "[", "\", "]"
|
||||
|
||||
Snum = 1*3DIGIT
|
||||
; representing a decimal integer
|
||||
; value in the range 0 through 255
|
||||
|
||||
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
|
||||
|
||||
IPv6-hex = 1*4HEXDIG
|
||||
|
||||
IPv6-full = IPv6-hex 7(":" IPv6-hex)
|
||||
|
||||
IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *5(":" IPv6-hex)]
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 6 groups in addition to the
|
||||
; "::" may be present.
|
||||
|
||||
IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
|
||||
|
||||
IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *3(":" IPv6-hex) ":"]
|
||||
IPv4-address-literal
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 4 groups in addition to the
|
||||
; "::" and IPv4-address-literal may be present.
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>The BNF from RFC 5321 defining parts of a valid SMTP address</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre style="font-size:11px;">
|
||||
Mailbox = Local-part "@" ( Domain / address-literal )
|
||||
|
||||
Local-part = Dot-string / Quoted-string
|
||||
; MAY be case-sensitive
|
||||
|
||||
|
||||
Dot-string = Atom *("." Atom)
|
||||
|
||||
Atom = 1*atext
|
||||
|
||||
Quoted-string = DQUOTE *QcontentSMTP DQUOTE
|
||||
|
||||
QcontentSMTP = qtextSMTP / quoted-pairSMTP
|
||||
|
||||
quoted-pairSMTP = %d92 %d32-126
|
||||
; i.e., backslash followed by any ASCII
|
||||
; graphic (including itself) or SPace
|
||||
|
||||
qtextSMTP = %d32-33 / %d35-91 / %d93-126
|
||||
; i.e., within a quoted string, any
|
||||
; ASCII graphic or space is permitted
|
||||
; without blackslash-quoting except
|
||||
; double-quote and the backslash itself.
|
||||
|
||||
Domain = sub-domain *("." sub-domain)
|
||||
|
||||
sub-domain = Let-dig [Ldh-str]
|
||||
|
||||
Let-dig = ALPHA / DIGIT
|
||||
|
||||
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
|
||||
|
||||
address-literal = "[" ( IPv4-address-literal /
|
||||
IPv6-address-literal /
|
||||
General-address-literal ) "]"
|
||||
; See Section 4.1.3
|
||||
|
||||
IPv4-address-literal = Snum 3("." Snum)
|
||||
|
||||
IPv6-address-literal = "IPv6:" IPv6-addr
|
||||
|
||||
General-address-literal = Standardized-tag ":" 1*dcontent
|
||||
|
||||
Standardized-tag = Ldh-str
|
||||
; Standardized-tag MUST be specified in a
|
||||
; Standards-Track RFC and registered with IANA
|
||||
|
||||
dcontent = %d33-90 / ; Printable US-ASCII
|
||||
%d94-126 ; excl. "[", "\", "]"
|
||||
|
||||
Snum = 1*3DIGIT
|
||||
; representing a decimal integer
|
||||
; value in the range 0 through 255
|
||||
|
||||
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
|
||||
|
||||
IPv6-hex = 1*4HEXDIG
|
||||
|
||||
IPv6-full = IPv6-hex 7(":" IPv6-hex)
|
||||
|
||||
IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *5(":" IPv6-hex)]
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 6 groups in addition to the
|
||||
; "::" may be present.
|
||||
|
||||
IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
|
||||
|
||||
IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *3(":" IPv6-hex) ":"]
|
||||
IPv4-address-literal
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 4 groups in addition to the
|
||||
; "::" and IPv4-address-literal may be present.
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
+141
-141
@@ -1,141 +1,141 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>The BNF from RFC 5322 defining parts of a valid internet message address</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre style="font-size:11px;">
|
||||
addr-spec = local-part "@" domain
|
||||
|
||||
local-part = dot-atom / quoted-string / obs-local-part
|
||||
|
||||
dot-atom = [CFWS] dot-atom-text [CFWS]
|
||||
|
||||
CFWS = (1*([FWS] comment) [FWS]) / FWS
|
||||
|
||||
FWS = ([*WSP CRLF] 1*WSP) / obs-FWS
|
||||
; Folding white space
|
||||
|
||||
WSP = SP / HTAB ; white space
|
||||
|
||||
obs-FWS = 1*([CRLF] WSP) ; As amended in erratum #1908
|
||||
|
||||
ctext = %d33-39 / ; Printable US-ASCII
|
||||
%d42-91 / ; characters not including
|
||||
%d93-126 / ; "(", ")", or "\"
|
||||
obs-ctext
|
||||
|
||||
obs-ctext = obs-NO-WS-CTL
|
||||
ccontent = ctext / quoted-pair / comment
|
||||
|
||||
comment = "(" *([FWS] ccontent) [FWS] ")"
|
||||
|
||||
dot-atom-text = 1*atext *("." 1*atext)
|
||||
|
||||
atext = ALPHA / DIGIT / ; Printable US-ASCII
|
||||
"!" / "#" / ; characters not including
|
||||
"$" / "%" / ; specials. Used for atoms.
|
||||
"&" / "'" /
|
||||
"*" / "+" /
|
||||
"-" / "/" /
|
||||
"=" / "?" /
|
||||
"^" / "_" /
|
||||
"`" / "{" /
|
||||
"|" / "}" /
|
||||
"~"
|
||||
|
||||
specials = "(" / ")" / ; Special characters that do
|
||||
"<" / ">" / ; not appear in atext
|
||||
"[" / "]" /
|
||||
":" / ";" /
|
||||
"@" / "\" /
|
||||
"," / "." /
|
||||
DQUOTE
|
||||
|
||||
quoted-string = [CFWS]
|
||||
DQUOTE *([FWS] qcontent) [FWS] DQUOTE
|
||||
[CFWS]
|
||||
|
||||
qcontent = qtext / quoted-pair
|
||||
|
||||
qtext = %d33 / ; Printable US-ASCII
|
||||
%d35-91 / ; characters not including
|
||||
%d93-126 / ; "\" or the quote character
|
||||
obs-qtext
|
||||
|
||||
obs-qtext = obs-NO-WS-CTL
|
||||
|
||||
obs-NO-WS-CTL = %d1-8 / ; US-ASCII control
|
||||
%d11 / ; characters that do not
|
||||
%d12 / ; include the carriage
|
||||
%d14-31 / ; return, line feed, and
|
||||
%d127 ; white space characters
|
||||
|
||||
quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
|
||||
|
||||
VCHAR = %x21-7E ; visible (printing) characters
|
||||
|
||||
obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)
|
||||
|
||||
obs-local-part = word *("." word)
|
||||
|
||||
word = atom / quoted-string
|
||||
|
||||
atom = [CFWS] 1*atext [CFWS]
|
||||
|
||||
domain = dot-atom / domain-literal / obs-domain
|
||||
|
||||
domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
|
||||
|
||||
dtext = %d33-90 / ; Printable US-ASCII
|
||||
%d94-126 / ; characters not including
|
||||
obs-dtext ; "[", "]", or "\"
|
||||
|
||||
obs-dtext = obs-NO-WS-CTL / quoted-pair
|
||||
|
||||
obs-domain = atom *("." atom)
|
||||
|
||||
NB For SMTP mail, the domain-literal is restricted by RFC5321 as follows:
|
||||
|
||||
Mailbox = Local-part "@" ( Domain / address-literal )
|
||||
|
||||
address-literal = "[" ( IPv4-address-literal /
|
||||
IPv6-address-literal /
|
||||
General-address-literal ) "]"
|
||||
|
||||
IPv4-address-literal = Snum 3("." Snum)
|
||||
|
||||
IPv6-address-literal = "IPv6:" IPv6-addr
|
||||
|
||||
Snum = 1*3DIGIT
|
||||
; representing a decimal integer
|
||||
; value in the range 0 through 255
|
||||
|
||||
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
|
||||
|
||||
IPv6-hex = 1*4HEXDIG
|
||||
|
||||
IPv6-full = IPv6-hex 7(":" IPv6-hex)
|
||||
|
||||
IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *5(":" IPv6-hex)]
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 6 groups in addition to the
|
||||
; "::" may be present.
|
||||
|
||||
IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
|
||||
|
||||
IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *3(":" IPv6-hex) ":"]
|
||||
IPv4-address-literal
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 4 groups in addition to the
|
||||
; "::" and IPv4-address-literal may be present.
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>The BNF from RFC 5322 defining parts of a valid internet message address</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre style="font-size:11px;">
|
||||
addr-spec = local-part "@" domain
|
||||
|
||||
local-part = dot-atom / quoted-string / obs-local-part
|
||||
|
||||
dot-atom = [CFWS] dot-atom-text [CFWS]
|
||||
|
||||
CFWS = (1*([FWS] comment) [FWS]) / FWS
|
||||
|
||||
FWS = ([*WSP CRLF] 1*WSP) / obs-FWS
|
||||
; Folding white space
|
||||
|
||||
WSP = SP / HTAB ; white space
|
||||
|
||||
obs-FWS = 1*([CRLF] WSP) ; As amended in erratum #1908
|
||||
|
||||
ctext = %d33-39 / ; Printable US-ASCII
|
||||
%d42-91 / ; characters not including
|
||||
%d93-126 / ; "(", ")", or "\"
|
||||
obs-ctext
|
||||
|
||||
obs-ctext = obs-NO-WS-CTL
|
||||
ccontent = ctext / quoted-pair / comment
|
||||
|
||||
comment = "(" *([FWS] ccontent) [FWS] ")"
|
||||
|
||||
dot-atom-text = 1*atext *("." 1*atext)
|
||||
|
||||
atext = ALPHA / DIGIT / ; Printable US-ASCII
|
||||
"!" / "#" / ; characters not including
|
||||
"$" / "%" / ; specials. Used for atoms.
|
||||
"&" / "'" /
|
||||
"*" / "+" /
|
||||
"-" / "/" /
|
||||
"=" / "?" /
|
||||
"^" / "_" /
|
||||
"`" / "{" /
|
||||
"|" / "}" /
|
||||
"~"
|
||||
|
||||
specials = "(" / ")" / ; Special characters that do
|
||||
"<" / ">" / ; not appear in atext
|
||||
"[" / "]" /
|
||||
":" / ";" /
|
||||
"@" / "\" /
|
||||
"," / "." /
|
||||
DQUOTE
|
||||
|
||||
quoted-string = [CFWS]
|
||||
DQUOTE *([FWS] qcontent) [FWS] DQUOTE
|
||||
[CFWS]
|
||||
|
||||
qcontent = qtext / quoted-pair
|
||||
|
||||
qtext = %d33 / ; Printable US-ASCII
|
||||
%d35-91 / ; characters not including
|
||||
%d93-126 / ; "\" or the quote character
|
||||
obs-qtext
|
||||
|
||||
obs-qtext = obs-NO-WS-CTL
|
||||
|
||||
obs-NO-WS-CTL = %d1-8 / ; US-ASCII control
|
||||
%d11 / ; characters that do not
|
||||
%d12 / ; include the carriage
|
||||
%d14-31 / ; return, line feed, and
|
||||
%d127 ; white space characters
|
||||
|
||||
quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
|
||||
|
||||
VCHAR = %x21-7E ; visible (printing) characters
|
||||
|
||||
obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)
|
||||
|
||||
obs-local-part = word *("." word)
|
||||
|
||||
word = atom / quoted-string
|
||||
|
||||
atom = [CFWS] 1*atext [CFWS]
|
||||
|
||||
domain = dot-atom / domain-literal / obs-domain
|
||||
|
||||
domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
|
||||
|
||||
dtext = %d33-90 / ; Printable US-ASCII
|
||||
%d94-126 / ; characters not including
|
||||
obs-dtext ; "[", "]", or "\"
|
||||
|
||||
obs-dtext = obs-NO-WS-CTL / quoted-pair
|
||||
|
||||
obs-domain = atom *("." atom)
|
||||
|
||||
NB For SMTP mail, the domain-literal is restricted by RFC5321 as follows:
|
||||
|
||||
Mailbox = Local-part "@" ( Domain / address-literal )
|
||||
|
||||
address-literal = "[" ( IPv4-address-literal /
|
||||
IPv6-address-literal /
|
||||
General-address-literal ) "]"
|
||||
|
||||
IPv4-address-literal = Snum 3("." Snum)
|
||||
|
||||
IPv6-address-literal = "IPv6:" IPv6-addr
|
||||
|
||||
Snum = 1*3DIGIT
|
||||
; representing a decimal integer
|
||||
; value in the range 0 through 255
|
||||
|
||||
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
|
||||
|
||||
IPv6-hex = 1*4HEXDIG
|
||||
|
||||
IPv6-full = IPv6-hex 7(":" IPv6-hex)
|
||||
|
||||
IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *5(":" IPv6-hex)]
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 6 groups in addition to the
|
||||
; "::" may be present.
|
||||
|
||||
IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
|
||||
|
||||
IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
|
||||
[IPv6-hex *3(":" IPv6-hex) ":"]
|
||||
IPv4-address-literal
|
||||
; The "::" represents at least 2 16-bit groups of
|
||||
; zeros. No more than 4 groups in addition to the
|
||||
; "::" and IPv4-address-literal may be present.
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -67,16 +67,12 @@ class EmailLexer extends AbstractLexer
|
||||
"\n" => self::S_LF,
|
||||
"\r\n" => self::CRLF,
|
||||
'IPv6' => self::S_IPV6TAG,
|
||||
'<' => self::S_LOWERTHAN,
|
||||
'>' => self::S_GREATERTHAN,
|
||||
'{' => self::S_OPENQBRACKET,
|
||||
'}' => self::S_CLOSEQBRACKET,
|
||||
'' => self::S_EMPTY,
|
||||
'\0' => self::C_NUL,
|
||||
);
|
||||
|
||||
protected $invalidASCII = array(226 => 1,);
|
||||
|
||||
protected $hasInvalidTokens = false;
|
||||
|
||||
protected $previous;
|
||||
@@ -138,12 +134,12 @@ class EmailLexer extends AbstractLexer
|
||||
protected function getCatchablePatterns()
|
||||
{
|
||||
return array(
|
||||
'[a-zA-Z_]+[46]?',
|
||||
'[a-zA-Z_]+[46]?', //ASCII and domain literal
|
||||
'[^\x00-\x7F]', //UTF-8
|
||||
'[0-9]+',
|
||||
'\r\n',
|
||||
'::',
|
||||
'\s+',
|
||||
'[\x10-\x1F]+',
|
||||
'\s+?',
|
||||
'.',
|
||||
);
|
||||
}
|
||||
@@ -155,7 +151,7 @@ class EmailLexer extends AbstractLexer
|
||||
*/
|
||||
protected function getNonCatchablePatterns()
|
||||
{
|
||||
return array('[\x7f-\xff]+');
|
||||
return array('[\xA0-\xff]+');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,16 +163,15 @@ class EmailLexer extends AbstractLexer
|
||||
*/
|
||||
protected function getType(&$value)
|
||||
{
|
||||
|
||||
if ($this->isNullType($value)) {
|
||||
return self::C_NUL;
|
||||
}
|
||||
|
||||
if (isset($this->charValue[$value])) {
|
||||
if ($this->isValid($value)) {
|
||||
return $this->charValue[$value];
|
||||
}
|
||||
|
||||
if ($this->isInvalid($value)) {
|
||||
if ($this->isUTF8Invalid($value)) {
|
||||
$this->hasInvalidTokens = true;
|
||||
return self::INVALID;
|
||||
}
|
||||
@@ -184,8 +179,18 @@ class EmailLexer extends AbstractLexer
|
||||
return self::GENERIC;
|
||||
}
|
||||
|
||||
protected function isValid($value)
|
||||
{
|
||||
if (isset($this->charValue[$value])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function isNullType($value)
|
||||
{
|
||||
@@ -197,18 +202,20 @@ class EmailLexer extends AbstractLexer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function isInvalid($value)
|
||||
protected function isUTF8Invalid($value)
|
||||
{
|
||||
if (preg_match('/[\x10-\x1F]+/', $value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset($this->invalidASCII[ord($value)])) {
|
||||
if (preg_match('/\p{Cc}+/u', $value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getModifiers()
|
||||
{
|
||||
return 'iu';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ class EmailParser
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param $str
|
||||
* @return array
|
||||
*/
|
||||
public function parse($str)
|
||||
{
|
||||
@@ -39,15 +40,16 @@ class EmailParser
|
||||
throw new \InvalidArgumentException('ERR_NOLOCALPART');
|
||||
}
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
throw new \InvalidArgumentException('ERR_INVALID_ATEXT');
|
||||
}
|
||||
|
||||
$this->localPartParser->parse($str);
|
||||
$this->domainPartParser->parse($str);
|
||||
|
||||
$this->setParts($str);
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
throw new \InvalidArgumentException('ERR_INVALID_ATEXT');
|
||||
}
|
||||
|
||||
return array('local' => $this->localPart, 'domain' => $this->domainPart);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ class EmailValidator
|
||||
const ERR_FWS_CRLF_END = 149;
|
||||
const ERR_CR_NO_LF = 150;
|
||||
const ERR_DEPREC_REACHED = 151;
|
||||
const ERR_UNOPENEDCOMMENT = 152;
|
||||
const RFC5321_TLD = 9;
|
||||
const RFC5321_TLDNUMERIC = 10;
|
||||
const RFC5321_QUOTEDSTRING = 11;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Parser\Parser;
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
|
||||
class DomainPart extends Parser
|
||||
@@ -103,6 +102,7 @@ class DomainPart extends Parser
|
||||
protected function doParseDomainPart()
|
||||
{
|
||||
$domain = '';
|
||||
$openedParenthesis = 0;
|
||||
do {
|
||||
$prev = $this->lexer->getPrevious();
|
||||
|
||||
@@ -112,7 +112,19 @@ class DomainPart extends Parser
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||
$this->parseComments();
|
||||
$openedParenthesis += $this->getOpenedParenthesis();
|
||||
$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();
|
||||
@@ -179,7 +191,7 @@ class DomainPart extends Parser
|
||||
}
|
||||
|
||||
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) {
|
||||
$this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
|
||||
@@ -217,9 +229,6 @@ class DomainPart extends Parser
|
||||
return $addressLiteral;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $addressLiteral
|
||||
*/
|
||||
protected function checkIPV4Tag($addressLiteral)
|
||||
{
|
||||
$matchesIP = array();
|
||||
@@ -245,6 +254,17 @@ class DomainPart extends Parser
|
||||
|
||||
protected function checkDomainPartExceptions($prev)
|
||||
{
|
||||
$invalidDomainTokens = array(
|
||||
EmailLexer::S_DQUOTE => true,
|
||||
EmailLexer::S_SEMICOLON => true,
|
||||
EmailLexer::S_GREATERTHAN => true,
|
||||
EmailLexer::S_LOWERTHAN => true,
|
||||
);
|
||||
|
||||
if (isset($invalidDomainTokens[$this->lexer->token['type']])) {
|
||||
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
||||
}
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_COMMA) {
|
||||
throw new \InvalidArgumentException('ERR_COMMA_IN_DOMAIN');
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
use \InvalidArgumentException;
|
||||
|
||||
|
||||
class LocalPart extends Parser
|
||||
{
|
||||
@@ -13,9 +11,9 @@ class LocalPart extends Parser
|
||||
{
|
||||
$parseDQuote = true;
|
||||
$closingQuote = false;
|
||||
$openedParenthesis = 0;
|
||||
|
||||
while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
|
||||
throw new \InvalidArgumentException('ERR_DOT_START');
|
||||
}
|
||||
@@ -27,12 +25,19 @@ class LocalPart extends Parser
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||
$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();
|
||||
|
||||
if (
|
||||
$this->lexer->token['type'] === EmailLexer::S_DOT &&
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
|
||||
$this->lexer->isNextToken(EmailLexer::S_AT)
|
||||
) {
|
||||
throw new \InvalidArgumentException('ERR_DOT_END');
|
||||
@@ -83,7 +88,7 @@ class LocalPart extends Parser
|
||||
$this->lexer->moveNext();
|
||||
|
||||
if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) {
|
||||
throw new InvalidArgumentException("ERR_EXPECTED_ATEXT");
|
||||
throw new \InvalidArgumentException('ERR_EXPECTED_ATEXT');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,12 +96,12 @@ class LocalPart extends Parser
|
||||
|
||||
if ($prev['type'] === EmailLexer::S_BACKSLASH) {
|
||||
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) {
|
||||
throw new \InvalidArgumentException("ERR_EXPECED_AT");
|
||||
throw new \InvalidArgumentException('ERR_EXPECED_AT');
|
||||
}
|
||||
|
||||
return $parseAgain;
|
||||
|
||||
@@ -9,6 +9,7 @@ abstract class Parser
|
||||
{
|
||||
protected $warnings = array();
|
||||
protected $lexer;
|
||||
protected $openedParenthesis = 0;
|
||||
|
||||
public function __construct(EmailLexer $lexer)
|
||||
{
|
||||
@@ -20,7 +21,13 @@ abstract class Parser
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
abstract function parse($str);
|
||||
abstract public function parse($str);
|
||||
|
||||
/** @return int */
|
||||
public function getOpenedParenthesis()
|
||||
{
|
||||
return $this->openedParenthesis;
|
||||
}
|
||||
|
||||
/**
|
||||
* validateQuotedPair
|
||||
@@ -35,15 +42,15 @@ abstract class Parser
|
||||
$this->warnings[] = EmailValidator::DEPREC_QP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the the comment
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function parseComments()
|
||||
{
|
||||
$this->openedParenthesis = 1;
|
||||
$this->isUnclosedComment();
|
||||
$this->warnings[] = EmailValidator::CFWS_COMMENT;
|
||||
while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
|
||||
if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
|
||||
$this->openedParenthesis++;
|
||||
}
|
||||
$this->warnEscaping();
|
||||
$this->lexer->moveNext();
|
||||
}
|
||||
@@ -75,11 +82,11 @@ abstract class Parser
|
||||
$this->checkCRLFInFWS();
|
||||
|
||||
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) {
|
||||
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) {
|
||||
@@ -160,7 +167,7 @@ abstract class Parser
|
||||
return $hasClosingQuote;
|
||||
}
|
||||
$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');
|
||||
}
|
||||
|
||||
@@ -181,10 +188,10 @@ abstract class Parser
|
||||
return;
|
||||
}
|
||||
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))) {
|
||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
|
||||
throw new \InvalidArgumentException('ERR_FWS_CRLF_END');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,73 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($token, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function testLexerParsesMultipleSpaces()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput(' ');
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::S_SP, $lexer->token['type']);
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::S_SP, $lexer->token['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidUTF8CharsProvider
|
||||
*/
|
||||
public function testLexerParsesInvalidUTF8($char)
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput($char);
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
|
||||
$this->assertEquals(EmailLexer::INVALID, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function invalidUTF8CharsProvider()
|
||||
{
|
||||
$chars = array();
|
||||
for ($i = 0; $i < 0x100; ++$i) {
|
||||
$c = $this->utf8Chr($i);
|
||||
if (preg_match('/(?=\p{Cc})(?=[^\t\n\n\r])/u', $c) && !preg_match('/\x{0000}/u', $c)) {
|
||||
$chars[] = array($c);
|
||||
}
|
||||
}
|
||||
|
||||
return $chars;
|
||||
}
|
||||
|
||||
protected function utf8Chr($code_point)
|
||||
{
|
||||
|
||||
if ($code_point < 0 || 0x10FFFF < $code_point || (0xD800 <= $code_point && $code_point <= 0xDFFF)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($code_point < 0x80) {
|
||||
$hex[0] = $code_point;
|
||||
$ret = chr($hex[0]);
|
||||
} elseif ($code_point < 0x800) {
|
||||
$hex[0] = 0x1C0 | $code_point >> 6;
|
||||
$hex[1] = 0x80 | $code_point & 0x3F;
|
||||
$ret = chr($hex[0]).chr($hex[1]);
|
||||
} elseif ($code_point < 0x10000) {
|
||||
$hex[0] = 0xE0 | $code_point >> 12;
|
||||
$hex[1] = 0x80 | $code_point >> 6 & 0x3F;
|
||||
$hex[2] = 0x80 | $code_point & 0x3F;
|
||||
$ret = chr($hex[0]).chr($hex[1]).chr($hex[2]);
|
||||
} else {
|
||||
$hex[0] = 0xF0 | $code_point >> 18;
|
||||
$hex[1] = 0x80 | $code_point >> 12 & 0x3F;
|
||||
$hex[2] = 0x80 | $code_point >> 6 & 0x3F;
|
||||
$hex[3] = 0x80 | $code_point & 0x3F;
|
||||
$ret = chr($hex[0]).chr($hex[1]).chr($hex[2]).chr($hex[3]);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function testLexerForTab()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
@@ -36,6 +103,17 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(EmailLexer::S_HTAB, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function testLexerForUTF8()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput("áÇ@bar.com");
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::GENERIC, $lexer->token['type']);
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::GENERIC, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function testLexerSearchToken()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
@@ -44,15 +122,6 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue($lexer->find(EmailLexer::S_HTAB));
|
||||
}
|
||||
|
||||
public function testLexerHasInvalidTokens()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput(chr(226));
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
$this->assertTrue($lexer->hasInvalidTokens());
|
||||
}
|
||||
|
||||
public function getTokens()
|
||||
{
|
||||
return array(
|
||||
@@ -85,7 +154,7 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||
array('}', EmailLexer::S_CLOSEQBRACKET),
|
||||
array('', EmailLexer::S_EMPTY),
|
||||
array(chr(31), EmailLexer::INVALID),
|
||||
array(chr(226), EmailLexer::INVALID),
|
||||
array(chr(226), EmailLexer::GENERIC),
|
||||
array(chr(0), EmailLexer::C_NUL)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,9 +26,18 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue($this->validator->isValid($email));
|
||||
}
|
||||
|
||||
public function testInvalidUTF8Email()
|
||||
{
|
||||
$validator = new EmailValidator;
|
||||
$email = "\x80\x81\x82@\x83\x84\x85.\x86\x87\x88";
|
||||
|
||||
$this->assertFalse($validator->isValid($email));
|
||||
}
|
||||
|
||||
public function getValidEmails()
|
||||
{
|
||||
return array(
|
||||
array('â@iana.org'),
|
||||
array('fabien@symfony.com'),
|
||||
array('example@example.co.uk'),
|
||||
array('fabien_potencier@example.fr'),
|
||||
@@ -47,6 +56,13 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
array('"test\ test"@iana.org'),
|
||||
array('""@iana.org'),
|
||||
array('"\""@iana.org'),
|
||||
array('müller@möller.de'),
|
||||
array('test@email*'),
|
||||
array('test@email!'),
|
||||
array('test@email&'),
|
||||
array('test@email^'),
|
||||
array('test@email%'),
|
||||
array('test@email$'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,7 +77,9 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
public function getInvalidEmails()
|
||||
{
|
||||
return array(
|
||||
|
||||
array('test@example.com test'),
|
||||
array('user name@example.com'),
|
||||
array('user name@example.com'),
|
||||
array('example.@example.co.uk'),
|
||||
array('example@example@example.co.uk'),
|
||||
array('(test_exampel@example.fr)'),
|
||||
@@ -98,6 +116,13 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
array('test@iana.org \r\n\r\n'),
|
||||
array('test@iana.org \r\n\r\n '),
|
||||
array('test@iana/icann.org'),
|
||||
array('test@foo;bar.com'),
|
||||
array('test;123@foobar.com'),
|
||||
array('test@example..com'),
|
||||
array('email.email@email."'),
|
||||
array('test@email>'),
|
||||
array('test@email<'),
|
||||
array('test@email{'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,6 +152,11 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
array(EmailValidator::ERR_DOT_END, 'example@localhost.'),
|
||||
array(EmailValidator::ERR_DOT_END, 'example.@example.co.uk'),
|
||||
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_EXPECTING_ATEXT, 'exa"mple@localhost'),
|
||||
//This was the original. But atext is not allowed after \n
|
||||
@@ -163,13 +193,32 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
public function getInvalidEmailsWithWarnings()
|
||||
{
|
||||
return array(
|
||||
array(array( EmailValidator::DEPREC_CFWS_NEAR_AT,), 'example @example.co.uk'),
|
||||
array(array( EmailValidator::DEPREC_CFWS_NEAR_AT,), 'example@ example.co.uk'),
|
||||
array(array( EmailValidator::CFWS_COMMENT,), 'example@example(examplecomment).co.uk'),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::DEPREC_CFWS_NEAR_AT,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'example @example.co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::DEPREC_CFWS_NEAR_AT,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'example@ example.co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::CFWS_COMMENT,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'example@example(examplecomment).co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::CFWS_COMMENT,
|
||||
EmailValidator::DEPREC_CFWS_NEAR_AT,
|
||||
EmailValidator::DNSWARN_NO_RECORD,
|
||||
),
|
||||
'example(examplecomment)@example.co.uk'
|
||||
),
|
||||
@@ -177,6 +226,7 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
array(
|
||||
EmailValidator::RFC5321_QUOTEDSTRING,
|
||||
EmailValidator::CFWS_FWS,
|
||||
EmailValidator::DNSWARN_NO_RECORD,
|
||||
),
|
||||
"\"\t\"@example.co.uk"
|
||||
),
|
||||
@@ -184,6 +234,7 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
array(
|
||||
EmailValidator::RFC5321_QUOTEDSTRING,
|
||||
EmailValidator::CFWS_FWS,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
"\"\r\"@example.co.uk"
|
||||
),
|
||||
@@ -275,12 +326,14 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
array(
|
||||
array(
|
||||
EmailValidator::RFC5321_QUOTEDSTRING,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'"example"@example.co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::RFC5322_LOCAL_TOOLONG,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'too_long_localpart_too_long_localpart_too_long_localpart_too_long_localpart@example.co.uk'
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user