Skip to content

Commit

Permalink
small tweaks to email validation
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin committed Nov 9, 2019
1 parent caa270a commit f23f2f4
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 12 deletions.
18 changes: 6 additions & 12 deletions pydantic/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,19 +353,17 @@ def validate(cls, value: NetworkType) -> Union[IPv4Network, IPv6Network]:
raise errors.IPvAnyNetworkError()


pretty_email_regex = re.compile(r'([\w ]*?) *<(.*)> *')
pretty_email_regex = re.compile(r' *([\w ]*?) *<(.+?)> *')


def validate_email(value: str) -> Tuple[str, str]:
"""
Brutally simple email address validation. Note unlike most email address validation
Email address validation using https://pypi.org/project/email-validator/
Notes:
* raw ip address (literal) domain parts are not allowed.
* "John Doe <local_part@domain.com>" style "pretty" email addresses are processed
* the local part check is extremely basic. This raises the possibility of unicode spoofing, but no better
solution is really possible.
* spaces are striped from the beginning and end of addresses but no error is raised
See RFC 5322 but treat it with suspicion, there seems to exist no universally acknowledged test for a valid email!
"""
if email_validator is None:
raise ImportError('email-validator is not installed, run `pip install pydantic[email]`')
Expand All @@ -378,12 +376,8 @@ def validate_email(value: str) -> Tuple[str, str]:
email = value.strip()

try:
email_validator.validate_email(email, check_deliverability=False)
parts = email_validator.validate_email(email, check_deliverability=False)
except email_validator.EmailNotValidError as e:
raise errors.EmailError() from e

at_index = email.index('@')
local_part = email[:at_index] # RFC 5321, local part must be case-sensitive.
global_part = email[at_index:].lower()

return name or local_part, local_part + global_part
return name or parts['local'], parts['email']
9 changes: 9 additions & 0 deletions tests/test_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ class Model(BaseModel):
('foo.bar@example.com ', 'foo.bar', 'foo.bar@example.com'),
('foo BAR <foobar@example.com >', 'foo BAR', 'foobar@example.com'),
('FOO bar <foobar@example.com> ', 'FOO bar', 'foobar@example.com'),
(' Whatever <foobar@example.com>', 'Whatever', 'foobar@example.com'),
('Whatever < foobar@example.com>', 'Whatever', 'foobar@example.com'),
('Whatever < foobar@example.com>', 'Whatever', 'foobar@example.com'),
('<FOOBAR@example.com> ', 'FOOBAR', 'FOOBAR@example.com'),
('ñoñó@example.com', 'ñoñó', 'ñoñó@example.com'),
('我買@example.com', '我買', '我買@example.com'),
Expand All @@ -334,6 +337,9 @@ class Model(BaseModel):
('foo.bar@example.com', 'foo.bar', 'foo.bar@example.com'),
('foo.bar@exam-ple.com ', 'foo.bar', 'foo.bar@exam-ple.com'),
('ιωάννης@εεττ.gr', 'ιωάννης', 'ιωάννης@εεττ.gr'),
('foobar@аррӏе.com', 'foobar', 'foobar@аррӏе.com'),
('аррӏе@example.com', 'аррӏе', 'аррӏе@example.com'),
('葉士豪@臺網中心.tw', '葉士豪', '葉士豪@臺網中心.tw'),
],
)
def test_address_valid(value, name, email):
Expand Down Expand Up @@ -363,6 +369,9 @@ def test_address_valid(value, name, email):
'\"@example.com',
',@example.com',
'foobar <foobar<@example.com>',
'foobar <foobar@example.com>>',
'foobar <<foobar<@example.com>',
'foobar <>',
],
)
def test_address_invalid(value):
Expand Down

0 comments on commit f23f2f4

Please sign in to comment.