Skip to content

Commit 80b7f64

Browse files
author
Adam Robbins-Pianka
committed
ENH: Bring email validation closer to specs
Fix #1179 This doesn't fully account for all valid email addresses (doing so is too much of a headache to implement, at least until it becomes necessary...), but it's closer, and will pass for the majority of email addresses.
1 parent da407f6 commit 80b7f64

File tree

1 file changed

+42
-9
lines changed

1 file changed

+42
-9
lines changed

qiita_db/user.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# The full license is in the file LICENSE, distributed with this software.
2929
# -----------------------------------------------------------------------------
3030
from __future__ import division
31-
from re import match
31+
from re import sub
3232

3333
from qiita_core.exceptions import (IncorrectEmailError, IncorrectPasswordError,
3434
IncompetentQiitaDeveloperError)
@@ -461,10 +461,18 @@ def validate_email(email):
461461
462462
Notes
463463
-----
464-
A valid email must be of the form "string AT string" where the first string
465-
must be not empty, and consists of [a-zA-Z0-9.+]. The AT is the '@' symbol.
466-
The second string must be not empty, consist of [a-zA-Z0-9.], and is
467-
required to have at least one '.'.
464+
An email address is of the form local-part@domain_part
465+
For our purposes:
466+
467+
- No quoted strings are allowed
468+
- No unicode strings are allowed
469+
- There must be exactly one @ symbol
470+
- Neither local-part nor domain-part can be blank
471+
- The local-part cannot start or end with a dot
472+
- The local-part must be composed of the following characters:
473+
a-zA-Z0-9#_~!$&'()*+,;=:.-
474+
- The domain-part must be a valid hostname, composed of:
475+
a-zA-Z0-9.
468476
469477
Parameters
470478
----------
@@ -476,15 +484,40 @@ def validate_email(email):
476484
bool
477485
Whether or not the email is valid
478486
"""
479-
valid_chars = "a-zA-Z0-9\.\+\-"
480-
pattern = r"[%s]+@[%s]+\.[%s]+" % (valid_chars, valid_chars, valid_chars)
481-
487+
# Do not accept email addresses that have unicode characters
482488
try:
483489
email.encode('ascii')
484490
except UnicodeError:
485491
return False
486492

487-
return True if match(pattern, email) is not None else False
493+
# we are not allowing quoted strings in the email address
494+
if '"' in email:
495+
return False
496+
497+
# Must have exactly 1 @ symbol
498+
if email.count('@') != 1:
499+
return False
500+
501+
local_part, domain_part = email.split('@')
502+
503+
# Neither part can be blank
504+
if not (local_part and domain_part):
505+
return False
506+
507+
# The local part cannot begin or end with a dot
508+
if local_part.startswith('.') or local_part.endswith('.'):
509+
return False
510+
511+
# This is the full set of allowable characters for the local part.
512+
local_valid_chars = "[a-zA-Z0-9#_~!$&'()*+,;=:.-]"
513+
if len(sub(local_valid_chars, '', local_part)):
514+
return False
515+
516+
domain_valid_chars = "[a-zA-Z0-9.]"
517+
if len(sub(domain_valid_chars, '', domain_part)):
518+
return False
519+
520+
return True
488521

489522

490523
def validate_password(password):

0 commit comments

Comments
 (0)