55import re
66
77# local
8+ from .hostname import hostname
89from .utils import validator
9- from .domain import domain
1010
1111
1212@validator
13- def email (value : str , / ):
13+ def email (
14+ value : str ,
15+ / ,
16+ * ,
17+ simple_host : bool = False ,
18+ ip_address : bool = False ,
19+ rfc_1034 : bool = False ,
20+ rfc_2782 : bool = False ,
21+ ):
1422 """Validate an email address.
1523
1624 This was inspired from [Django's email validator][1].
@@ -30,6 +38,16 @@ def email(value: str, /):
3038 Args:
3139 value:
3240 eMail string to validate.
41+ simple_host:
42+ When the domain part is a simple hostname.
43+ ip_address:
44+ When the domain part is an IP address.
45+ rfc_1034:
46+ Allow trailing dot in domain name.
47+ Ref: [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034).
48+ rfc_2782:
49+ Domain name is of type service record.
50+ Ref: [RFC 2782](https://www.rfc-editor.org/rfc/rfc2782).
3351
3452 Returns:
3553 (Literal[True]):
@@ -48,14 +66,31 @@ def email(value: str, /):
4866 # ref: RFC 1034 and 5231
4967 return False
5068
69+ if ip_address :
70+ if domain_part .startswith ("[" ) and domain_part .endswith ("]" ):
71+ # ref: RFC 5321
72+ domain_part = domain_part .lstrip ("[" ).rstrip ("]" )
73+ else :
74+ return False
75+
5176 return (
52- bool (domain (domain_part ))
53- if re .compile (
77+ bool (
78+ hostname (
79+ domain_part ,
80+ skip_ip_addr = not ip_address ,
81+ may_have_port = False ,
82+ maybe_simple = simple_host ,
83+ rfc_1034 = rfc_1034 ,
84+ rfc_2782 = rfc_2782 ,
85+ )
86+ )
87+ if re .match (
5488 # dot-atom
5589 r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$"
5690 # quoted-string
5791 + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"$)' ,
92+ username_part ,
5893 re .IGNORECASE ,
59- ). match ( username_part )
94+ )
6095 else False
6196 )
0 commit comments