or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-email-validator

A robust email address syntax and deliverability validation library for Python.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/email-validator@2.3.x

To install, run

npx @tessl/cli install tessl/pypi-email-validator@2.3.0

index.mddocs/

Email Validator

A robust email address syntax and deliverability validation library for Python 3.8+. This library validates that a string is of the form name@example.com and optionally checks that the domain name is set up to receive email, providing friendly error messages and normalized email addresses.

Package Information

  • Package Name: email-validator
  • Language: Python
  • Installation: pip install email-validator

Core Imports

from email_validator import validate_email, EmailNotValidError

Import validation exceptions:

from email_validator import EmailSyntaxError, EmailUndeliverableError

Import helper functions and types:

from email_validator import ValidatedEmail, caching_resolver, __version__

Basic Usage

from email_validator import validate_email, EmailNotValidError

email = "user@example.com"

try:
    # Validate email address with deliverability checking
    validated_email = validate_email(email)
    
    # Use the normalized form for storage/comparison
    normalized = validated_email.normalized
    print(f"Valid email: {normalized}")
    
    # Access additional information
    print(f"Local part: {validated_email.local_part}")
    print(f"Domain: {validated_email.domain}")
    print(f"ASCII email: {validated_email.ascii_email}")
    
except EmailNotValidError as e:
    print(f"Invalid email: {e}")

Architecture

The email-validator library provides a single main validation function that performs comprehensive email address validation in multiple stages:

  1. Input Processing: Handles both string and bytes input, converting to Unicode as needed
  2. Syntax Parsing: Splits email into display name, local part, and domain components
  3. Local Part Validation: Validates local part syntax with support for internationalization and quoted strings
  4. Domain Validation: Validates domain syntax supporting both domain names and IP literals
  5. Deliverability Checking: Optional DNS-based validation to verify domain can receive email
  6. Normalization: Returns normalized forms suitable for storage and comparison

Capabilities

Email Validation

Core email validation functionality that validates email address syntax and optionally checks deliverability.

def validate_email(
    email: Union[str, bytes],
    /,  # prior arguments are positional-only
    *,  # subsequent arguments are keyword-only
    allow_smtputf8: Optional[bool] = None,
    allow_empty_local: Optional[bool] = None,
    allow_quoted_local: Optional[bool] = None,
    allow_domain_literal: Optional[bool] = None,
    allow_display_name: Optional[bool] = None,
    strict: Optional[bool] = None,
    check_deliverability: Optional[bool] = None,
    test_environment: Optional[bool] = None,
    globally_deliverable: Optional[bool] = None,
    timeout: Optional[int] = None,
    dns_resolver: Optional[object] = None
) -> ValidatedEmail:
    """
    Validate an email address and return normalized information.

    Parameters:
    - email: Email address to validate (str or bytes)
    - allow_smtputf8: Allow internationalized email addresses (default: True)
    - allow_empty_local: Allow empty local part like @example.com (default: False)
    - allow_quoted_local: Allow quoted local parts with special characters (default: False)
    - allow_domain_literal: Allow bracketed IP addresses in domain (default: False)
    - allow_display_name: Allow display name format like "Name <email>" (default: False)
    - strict: Enable additional syntax checks like length limits (default: False)
    - check_deliverability: Perform DNS checks on domain (default: True)
    - test_environment: Allow test domains and disable DNS checks (default: False)
    - globally_deliverable: Require globally routable domains (default: True)
    - timeout: DNS query timeout in seconds (default: 15)
    - dns_resolver: Custom DNS resolver instance (default: None)

    Returns:
    ValidatedEmail: Object containing normalized email and metadata

    Raises:
    EmailSyntaxError: Email syntax is invalid
    EmailUndeliverableError: Domain fails deliverability checks
    """

Command-Line Interface

The email-validator package provides a command-line interface for testing and batch validation of email addresses.

def main(dns_resolver: Optional[object] = None) -> None:
    """
    Command-line interface for email validation.
    
    Usage:
    python -m email_validator user@example.com
    python -m email_validator < email_list.txt
    
    Environment Variables:
    ALLOW_SMTPUTF8, ALLOW_EMPTY_LOCAL, ALLOW_QUOTED_LOCAL,
    ALLOW_DOMAIN_LITERAL, ALLOW_DISPLAY_NAME, GLOBALLY_DELIVERABLE,
    CHECK_DELIVERABILITY, TEST_ENVIRONMENT, DEFAULT_TIMEOUT
    """

DNS Resolver Utilities

Helper function for creating cached DNS resolvers for improved performance when validating many email addresses.

def caching_resolver(
    *,
    timeout: Optional[int] = None,
    cache: Optional[object] = None,
    dns_resolver: Optional[object] = None
) -> object:
    """
    Create a DNS resolver with caching for improved performance.

    Parameters:
    - timeout: DNS query timeout in seconds (default: 15)
    - cache: Cache instance to use (default: LRUCache)
    - dns_resolver: Base resolver to configure (default: system resolver)

    Returns:
    dns.resolver.Resolver: Configured resolver with caching
    """

Types

class ValidatedEmail:
    """
    Result object containing normalized email address and validation metadata.
    """
    
    # Core email components
    original: str                        # Original input email address
    normalized: str                      # Normalized email address (recommended for use)
    local_part: str                     # Local part after normalization
    domain: str                         # Domain part after normalization
    
    # ASCII representations
    ascii_email: Optional[str]          # ASCII-only form if available
    ascii_local_part: Optional[str]     # ASCII-only local part if available
    ascii_domain: str                   # ASCII-only domain part
    
    # Metadata
    smtputf8: bool                      # True if SMTPUTF8 extension required
    display_name: Optional[str]         # Display name if present
    domain_address: Optional[object]    # IPv4Address/IPv6Address for domain literals
    
    # Deliverability information (if checked)
    mx: Optional[List[Tuple[int, str]]] # MX records as (priority, domain) tuples
    mx_fallback_type: Optional[str]     # Fallback record type ('A' or 'AAAA')
    spf: Optional[str]                  # SPF record if found during deliverability check
    
    def as_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
    
    def __repr__(self) -> str:
        """String representation showing normalized email."""

Exceptions

class EmailNotValidError(ValueError):
    """
    Base exception for all email validation failures.
    Contains human-readable error message explaining why validation failed.
    """

class EmailSyntaxError(EmailNotValidError):
    """
    Exception raised when email address has invalid syntax.
    Includes detailed explanation of syntax problems.
    """

class EmailUndeliverableError(EmailNotValidError):
    """
    Exception raised when email domain fails deliverability checks.
    Indicates DNS resolution problems or undeliverable domains.
    """

Configuration Constants

Global configuration constants that set default behavior for all validation calls:

# Validation behavior defaults
ALLOW_SMTPUTF8: bool = True           # Allow internationalized addresses
ALLOW_EMPTY_LOCAL: bool = False       # Allow empty local parts
ALLOW_QUOTED_LOCAL: bool = False      # Allow quoted local parts
ALLOW_DOMAIN_LITERAL: bool = False    # Allow IP address domains
ALLOW_DISPLAY_NAME: bool = False      # Allow display name format
STRICT: bool = False                  # Enable strict validation mode

# Deliverability defaults
CHECK_DELIVERABILITY: bool = True     # Perform DNS deliverability checks
GLOBALLY_DELIVERABLE: bool = True     # Require globally routable domains
TEST_ENVIRONMENT: bool = False        # Enable test environment mode
DEFAULT_TIMEOUT: int = 15             # DNS query timeout in seconds

# Special domain handling
SPECIAL_USE_DOMAIN_NAMES: List[str]   # List of rejected special-use domains

# Version information
__version__: str                      # Package version string

Usage Examples

Basic Email Validation

from email_validator import validate_email, EmailNotValidError

def validate_user_email(email_input):
    try:
        result = validate_email(email_input)
        return result.normalized
    except EmailNotValidError as e:
        print(f"Invalid email: {e}")
        return None

# Usage
email = validate_user_email("user@example.com")
if email:
    print(f"Validated email: {email}")

Registration Form Validation

from email_validator import validate_email, EmailNotValidError

def validate_registration_email(email):
    """Validate email for new user registration with deliverability checking."""
    try:
        result = validate_email(
            email,
            check_deliverability=True,  # Check DNS for registration
            allow_quoted_local=False,   # Reject confusing quoted formats
            allow_display_name=False    # Reject display name format
        )
        return result.normalized
    except EmailNotValidError as e:
        raise ValueError(f"Please enter a valid email address: {e}")

Login Form Validation

from email_validator import validate_email, EmailSyntaxError

def validate_login_email(email):
    """Validate email for login with minimal checks for performance."""
    try:
        result = validate_email(
            email,
            check_deliverability=False  # Skip DNS checks for login
        )
        return result.normalized
    except EmailSyntaxError as e:
        raise ValueError("Invalid email format")

Batch Validation with Caching

from email_validator import validate_email, caching_resolver, EmailNotValidError

def validate_email_list(email_list):
    """Validate multiple emails efficiently using cached DNS resolver."""
    # Create cached resolver for better performance
    resolver = caching_resolver(timeout=10)
    
    validated_emails = []
    for email in email_list:
        try:
            result = validate_email(email, dns_resolver=resolver)
            validated_emails.append(result.normalized)
        except EmailNotValidError as e:
            print(f"Skipping invalid email {email}: {e}")
    
    return validated_emails

International Email Support

from email_validator import validate_email, EmailNotValidError

def validate_international_email(email):
    """Validate international email addresses with full Unicode support."""
    try:
        result = validate_email(
            email,
            allow_smtputf8=True,        # Allow international characters
            globally_deliverable=True   # Ensure globally routable
        )
        
        print(f"Normalized: {result.normalized}")
        print(f"ASCII form: {result.ascii_email}")
        print(f"Requires SMTPUTF8: {result.smtputf8}")
        
        return result.normalized
    except EmailNotValidError as e:
        print(f"Invalid international email: {e}")
        return None

# Examples
validate_international_email("用户@example.com")  # Chinese characters
validate_international_email("user@測試.com")     # International domain

Custom Configuration

import email_validator
from email_validator import validate_email

# Modify global defaults
email_validator.CHECK_DELIVERABILITY = False  # Disable DNS checks globally
email_validator.ALLOW_QUOTED_LOCAL = True     # Allow quoted formats globally

# Allow test domains for development
email_validator.SPECIAL_USE_DOMAIN_NAMES.remove("test")

# Now all validation calls use these defaults
result = validate_email("developer@test")  # Would normally be rejected

Error Handling Patterns

from email_validator import (
    validate_email, 
    EmailNotValidError, 
    EmailSyntaxError, 
    EmailUndeliverableError
)

def comprehensive_email_validation(email):
    """Demonstrate different error handling approaches."""
    try:
        result = validate_email(email)
        return {
            'valid': True,
            'normalized': result.normalized,
            'metadata': {
                'local_part': result.local_part,
                'domain': result.domain,
                'smtputf8': result.smtputf8,
                'mx_records': getattr(result, 'mx', None)
            }
        }
    except EmailSyntaxError as e:
        return {
            'valid': False,
            'error_type': 'syntax',
            'message': str(e)
        }
    except EmailUndeliverableError as e:
        return {
            'valid': False,
            'error_type': 'deliverability',
            'message': str(e)
        }
    except EmailNotValidError as e:
        return {
            'valid': False,
            'error_type': 'general',
            'message': str(e)
        }