I'm currently using the default EmailField
attribute on my form. The issue I'm running into is that the form considers an invalid email such as [email protected]
to be valid. Do I need to implement my own validators
on this field to make it work correctly?
I was under the impression that having:
#models.py
email = models.EmailField(max_length=254, blank=False, unique=True,
error_messages={'required': 'Please provide your email address.',
'unique': 'An account with this email exist.'},)
Or having:
#forms.py
email = forms.EmailField()
will take care of this type of validation for me but it doesn't seem so.
You can see the used regex here.
I think it doesn't discard 100% of the wrong emails. That's why in the docs it says:
Validates that the given value is a valid email address, using a moderately complex regular expression.
What I understand from this is that it doesn't do a perfect validation due to a design decision (it would be a performance trade-off).
Finally, I'm pretty sure that your example [email protected]
is a valid email. The domain part of an email address can be an IP (both IPv4 and IPv6) or a hostname. See here for further info in the subject.
For DB level only validation you will have to call full_clean
manually.
Three important citations from documentation:
How validators are run
See the form validation for more information on how validators are run in forms, and Validating objects for how they’re run in models. Note that validators will not be run automatically when you save a model, but if you are using a ModelForm, it will run your validators on any fields that are included in your form. See the ModelForm documentation for information on how model validation interacts with forms.
Model.clean_fields
The second step full_clean() performs is to call Model.clean(). This method should be overridden to perform custom validation on your model.
Model.full_clean
Note that full_clean() will not be called automatically when you call your model’s save() method. You’ll need to call it manually when you want to run one-step model validation for your own manually created models.
from django.db import models
class MyTable(models.Model):
email = models.EmailField(unique=True)
def save(self, *args, **kwargs):
super().full_clean()
super().save(*args, **kwargs)
Indeed, [email protected]
email is a valid email for django EmailValidator
, see no errors:
>>> from django.core.validators import validate_email
>>> validate_email("[email protected]")
>>>
Django (1.5.1) uses the following regular expression for validating email address:
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
# quoted-string, see also https://www.rfc-editor.org/rfc/rfc2822#section-3.2.5
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)$)' # domain
r'|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$'
And it actually follows RFC2822 standard.
If you want to make [email protected]
fail during validation, you can create your own validator, and add it to EmailField
validators with built-in validate_email
validator, like this:
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
def custom_validate_email(value):
if <custom_check>:
raise ValidationError('Email format is incorrect')
...
email = models.EmailField(max_length=254, blank=False, unique=True, validators=[validate_email, custom_validate_email)
And, FYI, you can always file a ticket in django ticket system or ask about the issue on django IRC channel (irc://irc.freenode.net/django).
See also: Writing validators.
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With