diff --git a/django/core/validators.py b/django/core/validators.py index 47557ed271..8ac9a96cc7 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -1,4 +1,8 @@ +import re + from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import smart_unicode # These values, if given to to_python(), will trigger the self.required check. EMPTY_VALUES = (None, '') @@ -8,3 +12,12 @@ def validate_integer(value, all_values={}, model_instance=None): int(value) except (ValueError, TypeError), e: raise ValidationError('') + +email_re = re.compile( + r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string + r')@(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain + +def validate_email(value, all_values={}, model_instance=None): + if not email_re.search(smart_unicode(value)): + raise ValidationError(_(u'Enter a valid e-mail address.')) diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py index ffeaeb979a..3a6e223310 100644 --- a/tests/modeltests/validators/tests.py +++ b/tests/modeltests/validators/tests.py @@ -1,7 +1,7 @@ from unittest import TestCase from django.core.exceptions import ValidationError -from django.core.validators import validate_integer +from django.core.validators import validate_integer, validate_email class TestSimpleValidators(TestCase): pass @@ -13,9 +13,16 @@ SIMPLE_VALIDATORS_VALUES = ( (validate_integer, -42.5, None), (validate_integer, None, ValidationError), (validate_integer, 'a', ValidationError), + (validate_email, 'email@here.com', None), + (validate_email, 'weirder-email@here.and.there.com', None), + (validate_email, None, ValidationError), + (validate_email, '', ValidationError), + (validate_email, 'abc', ValidationError), + (validate_email, 'a @x.cz', ValidationError), + (validate_email, 'something@@somewhere.com', ValidationError), ) -def get_simple_test_func(expected, value, num): +def get_simple_test_func(validator, expected, value, num): if isinstance(expected, type) and issubclass(expected, ValidationError): test_mask = 'test_%s_raises_error_%d' def test_func(self): @@ -30,4 +37,4 @@ def get_simple_test_func(expected, value, num): test_counter = {} for validator, value, expected in SIMPLE_VALIDATORS_VALUES: num = test_counter[validator] = test_counter.setdefault(validator, 0) + 1 - setattr(TestSimpleValidators, *get_simple_test_func(expected, value, num)) + setattr(TestSimpleValidators, *get_simple_test_func(validator, expected, value, num))