From 80b7f641639c18c2e9e53aea9a2a346f1a2d2261 Mon Sep 17 00:00:00 2001 From: Adam Robbins-Pianka Date: Thu, 14 May 2015 15:33:24 -0600 Subject: [PATCH 1/3] 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. --- qiita_db/user.py | 51 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/qiita_db/user.py b/qiita_db/user.py index 58a570469..99ecc1fb6 100644 --- a/qiita_db/user.py +++ b/qiita_db/user.py @@ -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) @@ -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 ---------- @@ -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): From c69df6c184e22cb354354bf4c119bf813d79b77e Mon Sep 17 00:00:00 2001 From: Adam Robbins-Pianka Date: Thu, 14 May 2015 15:47:39 -0600 Subject: [PATCH 2/3] These are not invalid email addresses The domain part of the email address does not have to have a dot in it; even if it did, the last domain specified cannot be assured to be a TLD. --- qiita_db/test/test_user.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiita_db/test/test_user.py b/qiita_db/test/test_user.py index 3c2c4c502..38f68a1ec 100644 --- a/qiita_db/test/test_user.py +++ b/qiita_db/test/test_user.py @@ -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)) @@ -182,7 +182,7 @@ def test_exists_notindb(self): def test_exists_invaid_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') From 2895b300683a6aba22ea2f72bc816c7a38a126f9 Mon Sep 17 00:00:00 2001 From: Adam Robbins-Pianka Date: Thu, 14 May 2015 15:49:06 -0600 Subject: [PATCH 3/3] Fix misspelling of a test name --- qiita_db/test/test_user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiita_db/test/test_user.py b/qiita_db/test/test_user.py index 38f68a1ec..b90917ee2 100644 --- a/qiita_db/test/test_user.py +++ b/qiita_db/test/test_user.py @@ -180,7 +180,7 @@ 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")