Spaces:
Sleeping
Sleeping
File size: 1,864 Bytes
bfdf549 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | """
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, ""
|