Certificates-Generator / backend /utils /email_validator.py
saifisvibin's picture
Add email format and DNS validation to detect invalid emails before sending
bfdf549
"""
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, ""