( email: string, config: EmailValidationConfig = DEFAULT_EMAIL_CONFIG, )
| 29 | * Comprehensive email validation |
| 30 | */ |
| 31 | export function validateEmail( |
| 32 | email: string, |
| 33 | config: EmailValidationConfig = DEFAULT_EMAIL_CONFIG, |
| 34 | ): { valid: boolean; error?: string } { |
| 35 | if (!email || typeof email !== 'string') { |
| 36 | return { valid: false, error: 'Email is required' }; |
| 37 | } |
| 38 | |
| 39 | // Length check |
| 40 | const maxLength = config.maxLength || DEFAULT_EMAIL_CONFIG.maxLength!; |
| 41 | if (email.length > maxLength) { |
| 42 | return { |
| 43 | valid: false, |
| 44 | error: `Email must be less than ${maxLength} characters`, |
| 45 | }; |
| 46 | } |
| 47 | |
| 48 | // Basic format validation |
| 49 | const emailRegex = config.allowInternational |
| 50 | ? /^[^\s@]+@[^\s@]+\.[^\s@]+$/ // Basic international-friendly regex |
| 51 | : /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; // ASCII only |
| 52 | |
| 53 | if (!emailRegex.test(email)) { |
| 54 | return { valid: false, error: 'Invalid email format' }; |
| 55 | } |
| 56 | |
| 57 | // Domain validation |
| 58 | const domain = email.split('@')[1]?.toLowerCase(); |
| 59 | if (config.blockedDomains?.includes(domain)) { |
| 60 | return { valid: false, error: 'Email domain is not allowed' }; |
| 61 | } |
| 62 | |
| 63 | // Plus addressing check (if disabled) |
| 64 | if (!config.allowPlusAddressing && email.includes('+')) { |
| 65 | return { valid: false, error: 'Plus addressing is not allowed' }; |
| 66 | } |
| 67 | |
| 68 | return { valid: true }; |
| 69 | } |
| 70 | |
| 71 | /** |
| 72 | * Zod schema for password validation |
no outgoing calls
no test coverage detected