Skip to main content

Network and Identity Validation

This project provides specialized validators for verifying complex network-related strings such as email addresses, domain names, and URLs. These validators are located in django/core/validators.py and are designed to be RFC-compliant while remaining flexible for custom requirements.

Email Validation

The EmailValidator class handles the verification of email addresses. It ensures that an address follows the standard user@domain format and adheres to length constraints defined in RFC 3696.

Core Logic

The validation process in EmailValidator.__call__ follows these steps:

  1. Length Check: Ensures the total length does not exceed 320 characters.
  2. Split: Divides the string into a user_part and a domain_part at the last @ symbol.
  3. User Validation: Matches the user_part against user_regex, which supports both "dot-atom" and "quoted-string" formats.
  4. Domain Validation: Checks the domain_part against an allowlist or validates it using validate_domain_part.

Customizing Domains

By default, the validator allows localhost via the domain_allowlist. You can extend this to support internal or non-standard domains that might not pass the standard domain regex.

from django.core.validators import EmailValidator

# Allow internal server domains
validator = EmailValidator(allowlist=["internal.server", "local.dev"])
validator("admin@internal.server") # Valid

The validate_domain_part method also supports literal IP addresses (IPv4 and IPv6) enclosed in brackets, such as user@[192.168.1.1].

URL Validation

The URLValidator class is a RegexValidator subclass that provides comprehensive verification for URLs, including scheme, authentication, host, port, and path.

Validation Workflow

Unlike simple regex validators, URLValidator performs several distinct checks:

  • Scheme Verification: It extracts the scheme (the part before ://) and ensures it exists in the schemes list (default: http, https, ftp, ftps).
  • Regex Match: It uses a complex regex to verify the overall structure, including optional user/password authentication and ports.
  • Host Constraints: It uses urlsplit to extract the hostname and ensures it does not exceed 253 characters (per RFC 1034).
  • IPv6 Handling: If the host appears to be an IPv6 address (enclosed in brackets), it calls validate_ipv6_address for specialized verification.

Custom Schemes

You can instantiate URLValidator with a custom list of allowed protocols:

from django.core.validators import URLValidator

# Validate git and ssh protocols
validate_git = URLValidator(schemes=["git", "ssh"])
validate_git("git://github.com/django/django.git")

Domain Name Validation

The DomainNameValidator is used to verify that a string is a valid domain name. It is the foundation for domain checks in both EmailValidator and URLValidator.

Internationalized Domain Names (IDNA)

By default, DomainNameValidator supports Unicode characters in domain names (IDNA). This is controlled by the accept_idna parameter. When True, it uses regex patterns that include the Unicode range \u00a1-\uffff.

If you require strict ASCII-only domain validation, you can disable this:

from django.core.validators import DomainNameValidator

# Reject Unicode domains
strict_validator = DomainNameValidator(accept_idna=False)
# strict_validator("ıçğü.com") would raise ValidationError

Constraints

  • Label Length: Individual domain labels (parts between dots) are limited to 63 characters.
  • Total Length: The entire domain name is limited to 255 characters.
  • Structure: It ensures domains do not start or end with dashes and includes TLD (Top-Level Domain) verification.

Integration with Model Fields

These validators are automatically integrated into Django's model layer through specialized fields in django/db/models/fields/__init__.py.

  • EmailField: Uses the pre-instantiated validate_email (an instance of EmailValidator). It defaults to a max_length of 254 to be compliant with RFCs 3696 and 5321.
  • URLField: Uses URLValidator() as a default validator and defaults to a max_length of 200.
from django.db import models

class Profile(models.Model):
website = models.URLField() # Uses URLValidator
contact_email = models.EmailField() # Uses EmailValidator

When these fields are used, validation occurs both at the database model level and when generating corresponding form fields.