2828# The full license is in the file LICENSE, distributed with this software.
2929# -----------------------------------------------------------------------------
3030from __future__ import division
31- from re import match
31+ from re import sub
3232
3333from 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
490523def validate_password (password ):
0 commit comments