75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
import re
|
|
|
|
from .utils import validator
|
|
|
|
user_regex = re.compile(
|
|
# dot-atom
|
|
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+"
|
|
r"(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$"
|
|
# quoted-string
|
|
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|'
|
|
r"""\\[\001-\011\013\014\016-\177])*"$)""",
|
|
re.IGNORECASE
|
|
)
|
|
domain_regex = re.compile(
|
|
# domain
|
|
r'(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+'
|
|
r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?$)'
|
|
# literal form, ipv4 address (SMTP 4.1.3)
|
|
r'|^\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)'
|
|
r'(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$',
|
|
re.IGNORECASE)
|
|
domain_whitelist = ['localhost']
|
|
|
|
|
|
@validator
|
|
def email(value, whitelist=None):
|
|
"""
|
|
Validate an email address.
|
|
|
|
This validator is based on `Django's email validator`_. Returns
|
|
``True`` on success and :class:`~validators.utils.ValidationFailure`
|
|
when validation fails.
|
|
|
|
Examples::
|
|
|
|
>>> email('someone@example.com')
|
|
True
|
|
|
|
>>> email('bogus@@')
|
|
ValidationFailure(func=email, ...)
|
|
|
|
.. _Django's email validator:
|
|
https://github.com/django/django/blob/master/django/core/validators.py
|
|
|
|
.. versionadded:: 0.1
|
|
|
|
:param value: value to validate
|
|
:param whitelist: domain names to whitelist
|
|
|
|
:copyright: (c) Django Software Foundation and individual contributors.
|
|
:license: BSD
|
|
"""
|
|
|
|
if whitelist is None:
|
|
whitelist = domain_whitelist
|
|
|
|
if not value or '@' not in value:
|
|
return False
|
|
|
|
user_part, domain_part = value.rsplit('@', 1)
|
|
|
|
if not user_regex.match(user_part):
|
|
return False
|
|
|
|
if len(user_part.encode("utf-8")) > 64:
|
|
return False
|
|
|
|
if domain_part not in whitelist and not domain_regex.match(domain_part):
|
|
# Try for possible IDN domain-part
|
|
try:
|
|
domain_part = domain_part.encode('idna').decode('ascii')
|
|
return domain_regex.match(domain_part)
|
|
except UnicodeError:
|
|
return False
|
|
return True
|