Code

Ticket #4833: 4833-5.diff

File 4833-5.diff, 4.2 KB (added by claudep, 3 years ago)

Make domain whitelist parametrizable

Line 
1commit 99d66413e937620049cd8a1e4115d3d12f719b91
2Author: Claude Paroz <claude@2xlibre.net>
3Date:   Sat Jul 9 22:53:42 2011 +0200
4
5    Validate email addresses with localhost as domain
6
7diff --git a/django/core/validators.py b/django/core/validators.py
8index de415d6..d90956a 100644
9--- a/django/core/validators.py
10+++ b/django/core/validators.py
11@@ -140,29 +140,50 @@ def validate_integer(value):
12     except (ValueError, TypeError):
13         raise ValidationError('')
14 
15-class EmailValidator(RegexValidator):
16+class EmailValidator(object):
17+    message = _(u'Enter a valid e-mail address.')
18+    code = 'invalid'
19+    user_regex = re.compile(
20+        r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$"  # dot-atom
21+        r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"$)', # quoted-string
22+        re.IGNORECASE)
23+    domain_regex = re.compile(
24+        r'(^(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)'  # domain
25+        # literal form, ipv4 address (SMTP 4.1.3)
26+        r'|^\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$',
27+        re.IGNORECASE)
28+    domain_whitelist = ['localhost']
29+
30+    def __init__(self, message=None, code=None, whitelist=None):
31+        if message is not None:
32+            self.message = message
33+        if code is not None:
34+            self.code = code
35+        if whitelist is not None:
36+            self.domain_whitelist = whitelist
37 
38     def __call__(self, value):
39-        try:
40-            super(EmailValidator, self).__call__(value)
41-        except ValidationError, e:
42-            # Trivial case failed. Try for possible IDN domain-part
43-            if value and u'@' in value:
44-                parts = value.split(u'@')
45+        if value and u'@' in value:
46+            user_part, domain_part = value.split(u'@', 1)
47+            res = self.user_regex.search(smart_unicode(user_part))
48+            if not self.user_regex.search(smart_unicode(user_part)):
49+                raise ValidationError(self.message, code=self.code)
50+            if (not smart_unicode(domain_part) in self.domain_whitelist and
51+                    not self.domain_regex.search(smart_unicode(domain_part))):
52+                # Try for possible IDN domain-part
53                 try:
54-                    parts[-1] = parts[-1].encode('idna')
55+                    domain_part = domain_part.encode('idna')
56+                    if not self.domain_regex.search(smart_unicode(domain_part)):
57+                        raise ValidationError(self.message, code=self.code)
58+                    else:
59+                        return
60                 except UnicodeError:
61-                    raise e
62-                super(EmailValidator, self).__call__(u'@'.join(parts))
63-            else:
64-                raise
65+                    pass
66+                raise ValidationError(self.message, code=self.code)
67+        else:
68+            raise ValidationError(self.message, code=self.code)
69 
70-email_re = re.compile(
71-    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
72-    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
73-    r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)'  # domain
74-    r'|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$', re.IGNORECASE)  # literal form, ipv4 address (SMTP 4.1.3)
75-validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')
76+validate_email = EmailValidator()
77 
78 slug_re = re.compile(r'^[-\w]+$')
79 validate_slug = RegexValidator(slug_re, _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."), 'invalid')
80diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py
81index 9e254b9..ed8bdfb 100644
82--- a/tests/modeltests/validators/tests.py
83+++ b/tests/modeltests/validators/tests.py
84@@ -23,6 +23,7 @@ TEST_DATA = (
85     (validate_email, 'email@here.com', None),
86     (validate_email, 'weirder-email@here.and.there.com', None),
87     (validate_email, 'email@[127.0.0.1]', None),
88+    (validate_email, 'email@localhost', None),
89 
90     (validate_email, None, ValidationError),
91     (validate_email, '', ValidationError),