Last active
August 29, 2015 13:56
-
-
Save ernado/8870444 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # coding=utf-8 | |
| # python 2.7.6 | |
| # Alexander Razumov (ernado) | |
| # с подсветкой кода: https://gist.github.com/ernado/8870444#file-check-py | |
| """ | |
| 1. e-mail состоит из имени и доменной части, эти части разделяются символом "@"; | |
| 2. доменная часть не короче 3 символов и не длиннее 256, является набором непустых строк, состоящих из символов a-z 0-9_- и разделенных точкой; | |
| 3. каждый компонент доменной части не может начинаться или заканчиваться символом "-"; | |
| 4. имя (до @) не длиннее 128 символов, состоит из символов a-z0-9"._-; | |
| 5. в имени не допускаются две точки подряд; | |
| 6. если в имени есть двойные кавычки ", то они должны быть парными; | |
| 7. в имени могут встречаться символы "!,:", но только между парными двойными кавычками. | |
| """ | |
| import string | |
| DOMAIN_DICT = string.ascii_letters.lower() + string.digits + '_-.' | |
| NAME_DICT = DOMAIN_DICT + '"' | |
| NAME_COMMA_DICT = NAME_DICT + '!,:' | |
| def contains_bad_chars(s, dictionary): | |
| """ | |
| Checks that string contains only allowed chars | |
| Returns True if string is valid, else returns False | |
| :param s: input string | |
| :param dictionary: allowed characters | |
| :return: is invalid | |
| """ | |
| for char in s: | |
| if char not in dictionary: | |
| return True | |
| return False | |
| def check(s): | |
| """ | |
| Email validation. Returns True if email is valid, else - False | |
| :type s: str | |
| :param s: email | |
| :return: email is valid | |
| """ | |
| assert isinstance(s, str) | |
| email_parts = s.split('@') | |
| if len(email_parts) != 2: | |
| return False | |
| # split email into username and domain | |
| username, domain = email_parts | |
| if len(domain) > 256 or len(domain) < 3: | |
| return False | |
| for domain_part in domain.split('.'): | |
| if len(domain_part) == 0: | |
| return False | |
| # check first and last char != - | |
| if domain_part[0] == '-' or domain_part[-1] == '-': | |
| return False | |
| if len(username) > 128 or not username: | |
| return False | |
| if username.find('..') != -1: | |
| return False | |
| quote_separated = username.split('"') | |
| # check pairs for quotes | |
| if (len(quote_separated) % 2) == 0: | |
| return False | |
| quote_first = 0 | |
| if username.find('"') == 0: | |
| quote_first = 1 | |
| if contains_bad_chars(domain, DOMAIN_DICT): | |
| return False | |
| if contains_bad_chars(username, NAME_COMMA_DICT): | |
| return False | |
| for i, s in enumerate(quote_separated): | |
| dictionary = NAME_COMMA_DICT | |
| if i % 2 == quote_first: | |
| # not quoted | |
| dictionary = NAME_DICT | |
| if contains_bad_chars(s, dictionary): | |
| return False | |
| return True |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # coding=utf-8 | |
| # python 2.7.6 | |
| # Alexander Razumov (ernado) | |
| # с подсветкой кода: https://gist.github.com/ernado/8870444#file-tests-py | |
| import unittest | |
| from check import check | |
| class CheckTest(unittest.TestCase): | |
| # e-mail состоит из имени и доменной части, эти части разделяются символом "@" | |
| def test_check_at(self): | |
| self.assertTrue(check('[email protected]')) | |
| self.assertTrue(check('[email protected]')) | |
| self.assertFalse(check('@noname.com')) | |
| self.assertFalse(check('nothing')) | |
| self.assertFalse(check('nodomen@')) | |
| self.assertFalse(check('double@[email protected]')) | |
| # доменная часть не короче 3 символов и не длиннее 256 | |
| def test_domain_length(self): | |
| self.assertFalse(check('[email protected]')) | |
| self.assertTrue(check('test@' + 's'*256)) | |
| self.assertFalse(check('test@' + 's'*257)) | |
| # является набором непустых строк, состоящих из символов a-z 0-9_- и разделенных точкой | |
| def test_domain_chars(self): | |
| self.assertTrue(check('test@abcde09-test_lan.dot.com.ru')) | |
| self.assertFalse(check('test@abcde&.ru')) | |
| self.assertFalse(check('[email protected]')) | |
| self.assertFalse(check('test@test.ру')) | |
| # каждый компонент доменной части не может начинаться или заканчиваться символом "-" | |
| def test_domain_dash(self): | |
| self.assertFalse(check('[email protected]')) | |
| self.assertFalse(check('[email protected]')) | |
| self.assertFalse(check('[email protected]')) | |
| self.assertTrue(check('[email protected]')) | |
| # имя не длиннее 128 символов | |
| def test_username_length(self): | |
| self.assertTrue(check('s'*128 + '@yandex.ru')) | |
| self.assertFalse(check('s'*129 + '@yandex.ru')) | |
| # имя состоит из символов a-z0-9"._- | |
| def test_username_chars(self): | |
| self.assertFalse(check('et#[email protected]')) | |
| self.assertFalse(check('e%#[email protected]')) | |
| self.assertFalse(check('e!,:[email protected]')) | |
| self.assertTrue(check('"test.test-test_test"[email protected]')) | |
| # в имени не допускаются две точки подряд; | |
| def test_username_dots(self): | |
| self.assertFalse(check('[email protected]')) | |
| self.assertFalse(check('[email protected]')) | |
| self.assertFalse(check('[email protected]')) | |
| self.assertTrue(check('[email protected]')) | |
| # если в имени есть двойные кавычки ", то они должны быть парными | |
| def test_username_paired_quotes(self): | |
| self.assertTrue(check('test"test"test"testtest"[email protected]')) | |
| self.assertFalse(check('test"test"testtesttest"[email protected]')) | |
| # в имени могут встречаться символы "!,:", но только между парными двойными кавычками. | |
| def test_username_quoted(self): | |
| self.assertTrue(check('test"te!,:st"[email protected]')) | |
| self.assertFalse(check('testte!,:st"test"@ya.ru')) | |
| self.assertFalse(check('tes"tte!",:[email protected]')) | |
| if __name__ == '__main__': | |
| unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment