CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-email-validator

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

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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)
        }
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/email-validator@2.3.x
Publish Source
CLI
Badge
tessl/pypi-email-validator badge