""" Email validation utilities - Format and DNS validation """ import re import socket from typing import Tuple def validate_email_format(email: str) -> Tuple[bool, str]: """ Validate email format using regex. Returns (is_valid, error_message) """ if not email or not email.strip(): return False, "Email is empty" email = email.strip().lower() # Basic email regex pattern pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' if not re.match(pattern, email): return False, f"Invalid email format: {email}" return True, "" def validate_email_domain(email: str) -> Tuple[bool, str]: """ Validate that the email domain has valid MX or A records. Returns (is_valid, error_message) """ try: domain = email.split('@')[1] # Try to get MX records first try: socket.getaddrinfo(domain, None, socket.AF_INET) return True, "" except socket.gaierror: pass # If no A record, try with 'mail.' prefix (common mail server) try: socket.getaddrinfo(f"mail.{domain}", None, socket.AF_INET) return True, "" except socket.gaierror: pass return False, f"Domain does not exist: {domain}" except Exception as e: return False, f"Domain validation error: {str(e)}" def validate_email(email: str) -> Tuple[bool, str]: """ Full email validation - format and domain. Returns (is_valid, error_message) """ # First check format is_valid, error = validate_email_format(email) if not is_valid: return False, error # Then check domain is_valid, error = validate_email_domain(email) if not is_valid: return False, error return True, ""