Ticket #4833: 4833-5.diff

File 4833-5.diff, 4.2 KB (added by Claude Paroz, 13 years ago)

Make domain whitelist parametrizable

  • django/core/validators.py

    commit 99d66413e937620049cd8a1e4115d3d12f719b91
    Author: Claude Paroz <claude@2xlibre.net>
    Date:   Sat Jul 9 22:53:42 2011 +0200
    
        Validate email addresses with localhost as domain
    
    diff --git a/django/core/validators.py b/django/core/validators.py
    index de415d6..d90956a 100644
    a b def validate_integer(value):  
    140140    except (ValueError, TypeError):
    141141        raise ValidationError('')
    142142
    143 class EmailValidator(RegexValidator):
     143class EmailValidator(object):
     144    message = _(u'Enter a valid e-mail address.')
     145    code = 'invalid'
     146    user_regex = re.compile(
     147        r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$"  # dot-atom
     148        r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"$)', # quoted-string
     149        re.IGNORECASE)
     150    domain_regex = re.compile(
     151        r'(^(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)'  # domain
     152        # literal form, ipv4 address (SMTP 4.1.3)
     153        r'|^\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$',
     154        re.IGNORECASE)
     155    domain_whitelist = ['localhost']
     156
     157    def __init__(self, message=None, code=None, whitelist=None):
     158        if message is not None:
     159            self.message = message
     160        if code is not None:
     161            self.code = code
     162        if whitelist is not None:
     163            self.domain_whitelist = whitelist
    144164
    145165    def __call__(self, value):
    146         try:
    147             super(EmailValidator, self).__call__(value)
    148         except ValidationError, e:
    149             # Trivial case failed. Try for possible IDN domain-part
    150             if value and u'@' in value:
    151                 parts = value.split(u'@')
     166        if value and u'@' in value:
     167            user_part, domain_part = value.split(u'@', 1)
     168            res = self.user_regex.search(smart_unicode(user_part))
     169            if not self.user_regex.search(smart_unicode(user_part)):
     170                raise ValidationError(self.message, code=self.code)
     171            if (not smart_unicode(domain_part) in self.domain_whitelist and
     172                    not self.domain_regex.search(smart_unicode(domain_part))):
     173                # Try for possible IDN domain-part
    152174                try:
    153                     parts[-1] = parts[-1].encode('idna')
     175                    domain_part = domain_part.encode('idna')
     176                    if not self.domain_regex.search(smart_unicode(domain_part)):
     177                        raise ValidationError(self.message, code=self.code)
     178                    else:
     179                        return
    154180                except UnicodeError:
    155                     raise e
    156                 super(EmailValidator, self).__call__(u'@'.join(parts))
    157             else:
    158                 raise
     181                    pass
     182                raise ValidationError(self.message, code=self.code)
     183        else:
     184            raise ValidationError(self.message, code=self.code)
    159185
    160 email_re = re.compile(
    161     r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
    162     r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
    163     r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)'  # domain
    164     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)
    165 validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')
     186validate_email = EmailValidator()
    166187
    167188slug_re = re.compile(r'^[-\w]+$')
    168189validate_slug = RegexValidator(slug_re, _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."), 'invalid')
  • tests/modeltests/validators/tests.py

    diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py
    index 9e254b9..ed8bdfb 100644
    a b TEST_DATA = (  
    2323    (validate_email, 'email@here.com', None),
    2424    (validate_email, 'weirder-email@here.and.there.com', None),
    2525    (validate_email, 'email@[127.0.0.1]', None),
     26    (validate_email, 'email@localhost', None),
    2627
    2728    (validate_email, None, ValidationError),
    2829    (validate_email, '', ValidationError),
Back to Top