Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions qiita_db/test/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_validate_email(self):
valid3 = 'w00t@123.456.789.com'
invalid1 = '@stuff.com'
invalid2 = 'asdasdásd@things.com'
invalid3 = 'asdas@com'
invalid3 = '.asdas@com'

self.assertTrue(validate_email(valid1))
self.assertTrue(validate_email(valid2))
Expand Down Expand Up @@ -180,9 +180,9 @@ def test_exists(self):
def test_exists_notindb(self):
self.assertFalse(User.exists("notexist@foo.bar"))

def test_exists_invaid_email(self):
def test_exists_invalid_email(self):
with self.assertRaises(IncorrectEmailError):
User.exists("notanemail@badformat")
User.exists("notanemail.@badformat")

def test_get_email(self):
self.assertEqual(self.user.email, 'admin@foo.bar')
Expand Down
51 changes: 42 additions & 9 deletions qiita_db/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
# The full license is in the file LICENSE, distributed with this software.
# -----------------------------------------------------------------------------
from __future__ import division
from re import match
from re import sub

from qiita_core.exceptions import (IncorrectEmailError, IncorrectPasswordError,
IncompetentQiitaDeveloperError)
Expand Down Expand Up @@ -461,10 +461,18 @@ def validate_email(email):

Notes
-----
A valid email must be of the form "string AT string" where the first string
must be not empty, and consists of [a-zA-Z0-9.+]. The AT is the '@' symbol.
The second string must be not empty, consist of [a-zA-Z0-9.], and is
required to have at least one '.'.
An email address is of the form local-part@domain_part
For our purposes:

- No quoted strings are allowed
- No unicode strings are allowed
- There must be exactly one @ symbol
- Neither local-part nor domain-part can be blank
- The local-part cannot start or end with a dot
- The local-part must be composed of the following characters:
a-zA-Z0-9#_~!$&'()*+,;=:.-
- The domain-part must be a valid hostname, composed of:
a-zA-Z0-9.

Parameters
----------
Expand All @@ -476,15 +484,40 @@ def validate_email(email):
bool
Whether or not the email is valid
"""
valid_chars = "a-zA-Z0-9\.\+\-"
pattern = r"[%s]+@[%s]+\.[%s]+" % (valid_chars, valid_chars, valid_chars)

# Do not accept email addresses that have unicode characters
try:
email.encode('ascii')
except UnicodeError:
return False

return True if match(pattern, email) is not None else False
# we are not allowing quoted strings in the email address
if '"' in email:
return False

# Must have exactly 1 @ symbol
if email.count('@') != 1:
return False

local_part, domain_part = email.split('@')

# Neither part can be blank
if not (local_part and domain_part):
return False

# The local part cannot begin or end with a dot
if local_part.startswith('.') or local_part.endswith('.'):
return False

# This is the full set of allowable characters for the local part.
local_valid_chars = "[a-zA-Z0-9#_~!$&'()*+,;=:.-]"
if len(sub(local_valid_chars, '', local_part)):
return False

domain_valid_chars = "[a-zA-Z0-9.]"
if len(sub(domain_valid_chars, '', domain_part)):
return False

return True


def validate_password(password):
Expand Down