moon
moon

Reputation: 45

How to allow registrations from specific email domains only like 'gmail' in django?

I tried what the docs said in here by using whitelist but it's not working, here's what I tried:

from django.core.validators import EmailValidator

email = models.EmailField(max_length=60, validators=[EmailValidator(whitelist=["gmail", "yahoo", "hotmail"])])

I tried registering with gail.com and I registered normally, so how can I fix this

Upvotes: 4

Views: 1839

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

You misunderstand the documentation. The documentation on whitelist=… says:

Whitelist of email domains to allow. By default, a regular expression (the domain_regex attribute) is used to validate whatever appears after the @ sign. However, if that string appears in the whitelist, this validation is bypassed. If not provided, the default whitelist is ['localhost']. Other domains that don't contain a dot won’t pass validation, so you’d need to whitelist them as necessary.

This thus means that all domains that contain a dot are considered valid, the whitelist only will allow some extra domains (like @localhost), if you whitelist these.

You can make your own validator by subclassing the EmailValidator and alter the .validate_domain_part(…) method [GitHub] however with:

from django.core.validators import EmailValidator
from django.utils.deconstruct import deconstructible

@deconstructible
class WhitelistEmailValidator(EmailValidator):

    def validate_domain_part(self, domain_part):
        return False

    def __eq__(self, other):
        return isinstance(other, WhitelistEmailValidator) and super().__eq__(other)

So then we can make use of the WhitelistEmailValidator to do proper validation.

For example:

>>> wl = WhitelistEmailValidator(whitelist=['gmail.com'])
>>> wl('[email protected]')
>>> wl('[email protected]')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/python/env/lib/python3.6/site-packages/django/core/validators.py", line 208, in __call__
    raise ValidationError(self.message, code=self.code)
django.core.exceptions.ValidationError: ['Enter a valid email address.']

In your field, you thus add this to the validators:

class MyModel(models.Model):
    email = models.EmailField(
        max_length=60,
        validators=[WhitelistEmailValidator(whitelist=['gmail.com', 'yahoo.com', 'hotmail.com'])]
    )

Upvotes: 3

Related Questions