mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-22 02:17:26 +00:00
move the email address syntax validation for users and aliases into my new email_validator library (https://github.com/JoshData/python-email-validator)
This commit is contained in:
parent
6bb8f5d889
commit
5efd5abbe4
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import subprocess, shutil, os, sqlite3, re
|
import subprocess, shutil, os, sqlite3, re
|
||||||
import utils
|
import utils
|
||||||
|
from email_validator import validate_email as validate_email_, EmailNotValidError
|
||||||
|
|
||||||
def validate_email(email, mode=None):
|
def validate_email(email, mode=None):
|
||||||
# Checks that an email address is syntactically valid. Returns True/False.
|
# Checks that an email address is syntactically valid. Returns True/False.
|
||||||
@ -15,60 +16,25 @@ def validate_email(email, mode=None):
|
|||||||
# When mode=="alias", we're allowing anything that can be in a Postfix
|
# When mode=="alias", we're allowing anything that can be in a Postfix
|
||||||
# alias table, i.e. omitting the local part ("@domain.tld") is OK.
|
# alias table, i.e. omitting the local part ("@domain.tld") is OK.
|
||||||
|
|
||||||
# Check that the address isn't absurdly long.
|
# Check the syntax of the address.
|
||||||
if len(email) > 255: return False
|
try:
|
||||||
|
validate_email_(email,
|
||||||
|
allow_smtputf8=False,
|
||||||
|
check_deliverability=False,
|
||||||
|
allow_empty_local=(mode=="alias")
|
||||||
|
)
|
||||||
|
except EmailNotValidError:
|
||||||
|
return False
|
||||||
|
|
||||||
if mode == 'user':
|
if mode == 'user':
|
||||||
# There are a lot of characters permitted in email addresses, but
|
# There are a lot of characters permitted in email addresses, but
|
||||||
# Dovecot's sqlite driver seems to get confused if there are any
|
# Dovecot's sqlite auth driver seems to get confused if there are any
|
||||||
# unusual characters in the address. Bah. Also note that since
|
# unusual characters in the address. Bah. Also note that since
|
||||||
# the mailbox path name is based on the email address, the address
|
# the mailbox path name is based on the email address, the address
|
||||||
# shouldn't be absurdly long and must not have a forward slash.
|
# shouldn't be absurdly long and must not have a forward slash.
|
||||||
ATEXT = r'[a-zA-Z0-9_\-]+'
|
if len(email) > 255: return False
|
||||||
elif mode in (None, 'alias'):
|
if re.search(r'[^\@\.a-zA-Z0-9_\-]+', email):
|
||||||
# For aliases, we can allow any valid email address.
|
return False
|
||||||
# Based on RFC 2822 and https://github.com/SyrusAkbary/validate_email/blob/master/validate_email.py,
|
|
||||||
# these characters are permitted in email addresses.
|
|
||||||
ATEXT = r'[a-zA-Z0-9_!#$%&\'\*\+\-/=\?\^`\{\|\}~]+' # see 3.2.4
|
|
||||||
else:
|
|
||||||
raise ValueError(mode)
|
|
||||||
|
|
||||||
# per RFC 2822 3.2.4
|
|
||||||
DOT_ATOM_TEXT_LOCAL = ATEXT + r'(?:\.' + ATEXT + r')*'
|
|
||||||
if mode == 'alias':
|
|
||||||
# For aliases, Postfix accepts '@domain.tld' format for
|
|
||||||
# catch-all addresses on the source side and domain aliases
|
|
||||||
# on the destination side. Make the local part optional.
|
|
||||||
DOT_ATOM_TEXT_LOCAL = '(?:' + DOT_ATOM_TEXT_LOCAL + ')?'
|
|
||||||
|
|
||||||
# The domain part of the email address has a few more restrictions.
|
|
||||||
|
|
||||||
# In addition to the characters allowed by RFC 2822, the domain part
|
|
||||||
# must also satisfy the requirements of RFC 952/RFC 1123 which restrict
|
|
||||||
# the allowed characters of hostnames further. These are a subset of
|
|
||||||
# the Dovecot-allowed characters, fortunately. The hyphen cannot be at
|
|
||||||
# the beginning or end of a component of a hostname either, but we aren't
|
|
||||||
# testing that.
|
|
||||||
ATEXT2 = r'[a-zA-Z0-9\-]+'
|
|
||||||
|
|
||||||
# We can require that the host part have at least one period in it.
|
|
||||||
# We also know that all TLDs are at least two characters and end with a letter.
|
|
||||||
DOT_ATOM_TEXT_HOST = ATEXT2 + r'(?:\.' + ATEXT2 + r')*' + r'(?:\.' + ATEXT2 + r'[A-Za-z])'
|
|
||||||
|
|
||||||
# per RFC 2822 3.4.1
|
|
||||||
ADDR_SPEC = '^(%s)@(%s)$' % (DOT_ATOM_TEXT_LOCAL, DOT_ATOM_TEXT_HOST)
|
|
||||||
|
|
||||||
# Check the regular expression.
|
|
||||||
m = re.match(ADDR_SPEC, email)
|
|
||||||
if not m: return False
|
|
||||||
|
|
||||||
# Check that the domain part is valid IDNA.
|
|
||||||
localpart, domainpart = m.groups()
|
|
||||||
try:
|
|
||||||
domainpart.encode('ascii').decode("idna")
|
|
||||||
except:
|
|
||||||
# Domain is not valid IDNA.
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Everything looks good.
|
# Everything looks good.
|
||||||
return True
|
return True
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
source setup/functions.sh
|
source setup/functions.sh
|
||||||
|
|
||||||
apt_install python3-flask links duplicity libyaml-dev python3-dnspython python3-dateutil
|
apt_install python3-flask links duplicity libyaml-dev python3-dnspython python3-dateutil
|
||||||
hide_output pip3 install rtyaml
|
hide_output pip3 install rtyaml "email_validator==0.1.0-rc1"
|
||||||
|
|
||||||
# Create a backup directory and a random key for encrypting backups.
|
# Create a backup directory and a random key for encrypting backups.
|
||||||
mkdir -p $STORAGE_ROOT/backup
|
mkdir -p $STORAGE_ROOT/backup
|
||||||
|
Loading…
Reference in New Issue
Block a user