bouncevalidator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +483 -0
- package/dist/bin/cli.js +2229 -0
- package/dist/index.d.mts +398 -0
- package/dist/index.d.ts +398 -0
- package/dist/index.js +2105 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2041 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/normalize.ts","../src/utils/suggestions.ts","../src/validators/syntax.ts","../src/validators/dns.ts","../src/utils/cache.ts","../src/validators/smtp.ts","../src/validators/misc.ts","../src/data/disposable.ts","../src/data/roles.ts","../src/data/free-providers.ts"],"sourcesContent":["import type {\n ValidationResult,\n ValidationOptions,\n BulkValidationOptions,\n Reachability,\n} from \"./types.js\";\n\nimport { validateSyntax, isValidSyntax } from \"./validators/syntax.js\";\nimport { verifyMx, hasMxRecords, getMxRecords } from \"./validators/dns.js\";\nimport { verifySmtpWithFallback, SmtpErrorType } from \"./validators/smtp.js\";\nimport { checkMisc, checkDisposable, checkRoleAccount, checkFreeProvider } from \"./validators/misc.js\";\nimport { globalDnsCache } from \"./utils/cache.js\";\nimport { normalizeEmail, extractParts } from \"./utils/normalize.js\";\nimport { getSuggestion, getEmailSuggestion } from \"./utils/suggestions.js\";\n\n// Re-export types\nexport type {\n ValidationResult,\n ValidationOptions,\n BulkValidationOptions,\n Reachability,\n SyntaxResult,\n MxResult,\n SmtpResult,\n SmtpError,\n MiscResult,\n DnsCacheEntry,\n} from \"./types.js\";\n\n// Re-export utilities\nexport { DnsCache, globalDnsCache } from \"./utils/cache.js\";\nexport { normalizeEmail, extractParts } from \"./utils/normalize.js\";\nexport { getSuggestion, getEmailSuggestion } from \"./utils/suggestions.js\";\n\n// Re-export validators\nexport { validateSyntax, isValidSyntax } from \"./validators/syntax.js\";\nexport { verifyMx, hasMxRecords, getMxRecords } from \"./validators/dns.js\";\nexport { verifySmtpWithFallback as verifySmtp, SmtpErrorType } from \"./validators/smtp.js\";\nexport {\n checkMisc,\n checkDisposable,\n checkRoleAccount,\n checkFreeProvider,\n} from \"./validators/misc.js\";\n\n// Re-export data\nexport { isDisposableDomain, disposableDomains } from \"./data/disposable.js\";\nexport { isRolePrefix, rolePrefixes } from \"./data/roles.js\";\nexport { isFreeProvider, freeProviders } from \"./data/free-providers.js\";\n\n/**\n * Default validation options\n */\nconst defaultOptions: Omit<Required<ValidationOptions>, \"proxy\"> & { proxy?: ValidationOptions[\"proxy\"] } = {\n smtpTimeout: 10000,\n verifySmtp: true,\n checkDisposable: true,\n checkRoleAccount: true,\n checkFreeProvider: true,\n checkGravatar: false,\n heloHost: \"\",\n senderAddress: \"\",\n dnsCacheTtl: 300000,\n useDnsCache: true,\n detectCatchAll: true,\n proxy: undefined,\n};\n\n/**\n * Determine the reachability status based on validation results\n */\nfunction determineReachability(\n syntaxValid: boolean,\n mxValid: boolean,\n smtpResult: { isDeliverable: boolean; isCatchAll: boolean; canConnectSmtp: boolean; error: { type: string } | null } | null,\n options: ValidationOptions\n): Reachability {\n // Invalid syntax = invalid\n if (!syntaxValid) {\n return \"invalid\";\n }\n\n // No MX records = invalid\n if (!mxValid) {\n return \"invalid\";\n }\n\n // If SMTP verification is disabled, we can only say it's risky\n if (options.verifySmtp === false) {\n return \"risky\";\n }\n\n // No SMTP result (shouldn't happen, but handle it)\n if (!smtpResult) {\n return \"unknown\";\n }\n\n // Catch-all domains are risky\n if (smtpResult.isCatchAll) {\n return \"risky\";\n }\n\n // Mailbox verified = safe\n if (smtpResult.isDeliverable) {\n return \"safe\";\n }\n\n // Could not connect to SMTP = unknown\n if (!smtpResult.canConnectSmtp) {\n return \"unknown\";\n }\n\n // Mailbox not found = invalid\n if (smtpResult.error?.type === SmtpErrorType.MAILBOX_NOT_FOUND) {\n return \"invalid\";\n }\n\n // Greylisted = risky (might be valid, just temporarily blocked)\n if (smtpResult.error?.type === SmtpErrorType.GREYLISTED) {\n return \"risky\";\n }\n\n // Other SMTP errors = risky\n return \"risky\";\n}\n\n/**\n * Validate a single email address\n *\n * @param email The email address to validate\n * @param options Validation options\n * @returns Promise resolving to ValidationResult\n *\n * @example\n * ```typescript\n * import { validate } from 'bouncevalidator';\n *\n * const result = await validate('user@example.com');\n * console.log(result.isReachable); // 'safe', 'invalid', 'risky', or 'unknown'\n * ```\n */\nexport async function validate(\n email: string,\n options: ValidationOptions = {}\n): Promise<ValidationResult> {\n const opts = { ...defaultOptions, ...options };\n\n // Configure DNS cache TTL if specified\n if (opts.useDnsCache && opts.dnsCacheTtl) {\n globalDnsCache.setTtl(opts.dnsCacheTtl);\n }\n\n // Step 1: Syntax validation\n const syntaxResult = validateSyntax(email);\n\n // Early return if syntax is invalid\n if (!syntaxResult.isValidSyntax) {\n return {\n input: email,\n isReachable: \"invalid\",\n syntax: syntaxResult,\n mx: {\n acceptsMail: false,\n records: [],\n },\n smtp: {\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: null,\n },\n misc: {\n isDisposable: false,\n isRoleAccount: false,\n isFreeProvider: false,\n gravatarUrl: null,\n },\n };\n }\n\n // Step 2: MX verification\n const mxResult = await verifyMx(syntaxResult.domain, opts);\n\n // Early return if no MX records\n if (!mxResult.acceptsMail) {\n const miscResult = await checkMisc(email, opts);\n return {\n input: email,\n isReachable: \"invalid\",\n syntax: syntaxResult,\n mx: mxResult,\n smtp: {\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: \"NoMxRecords\",\n message: \"Domain does not accept mail\",\n },\n },\n misc: miscResult,\n };\n }\n\n // Step 3: SMTP verification (if enabled)\n let smtpResult = {\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: null as { type: string; message: string } | null,\n };\n\n if (opts.verifySmtp) {\n smtpResult = await verifySmtpWithFallback(email, mxResult.records, opts);\n }\n\n // Step 4: Miscellaneous checks\n const miscResult = await checkMisc(email, opts);\n\n // Determine overall reachability\n const isReachable = determineReachability(\n syntaxResult.isValidSyntax,\n mxResult.acceptsMail,\n smtpResult,\n opts\n );\n\n return {\n input: email,\n isReachable,\n syntax: syntaxResult,\n mx: mxResult,\n smtp: smtpResult,\n misc: miscResult,\n };\n}\n\n/**\n * Validate multiple email addresses\n *\n * @param emails Array of email addresses to validate\n * @param options Bulk validation options\n * @returns Promise resolving to array of ValidationResults\n *\n * @example\n * ```typescript\n * import { validateBulk } from 'bouncevalidator';\n *\n * const results = await validateBulk([\n * 'user1@example.com',\n * 'user2@example.com'\n * ], { concurrency: 5 });\n * ```\n */\nexport async function validateBulk(\n emails: string[],\n options: BulkValidationOptions = {}\n): Promise<ValidationResult[]> {\n const { concurrency = 5, delayBetween = 0, onProgress, ...validateOptions } = options;\n\n const results: ValidationResult[] = [];\n let completed = 0;\n\n // Process emails in batches based on concurrency\n for (let i = 0; i < emails.length; i += concurrency) {\n const batch = emails.slice(i, i + concurrency);\n\n const batchPromises = batch.map(async (email) => {\n const result = await validate(email, validateOptions);\n completed++;\n\n if (onProgress) {\n onProgress(completed, emails.length, result);\n }\n\n return result;\n });\n\n const batchResults = await Promise.all(batchPromises);\n results.push(...batchResults);\n\n // Add delay between batches if specified\n if (delayBetween > 0 && i + concurrency < emails.length) {\n await new Promise((resolve) => setTimeout(resolve, delayBetween));\n }\n }\n\n return results;\n}\n\n/**\n * Quick validation - only checks syntax and MX records\n * Much faster than full validation as it skips SMTP verification\n *\n * @param email The email address to validate\n * @returns Promise resolving to ValidationResult\n */\nexport async function validateQuick(email: string): Promise<ValidationResult> {\n return validate(email, { verifySmtp: false });\n}\n\n/**\n * Clear the DNS cache\n */\nexport function clearDnsCache(): void {\n globalDnsCache.clear();\n}\n\n/**\n * Get the current DNS cache size\n */\nexport function getDnsCacheSize(): number {\n return globalDnsCache.size;\n}\n\n// Default export\nexport default {\n validate,\n validateBulk,\n validateQuick,\n clearDnsCache,\n getDnsCacheSize,\n // Utilities\n normalizeEmail,\n extractParts,\n getSuggestion,\n getEmailSuggestion,\n // Individual validators\n validateSyntax,\n isValidSyntax,\n verifyMx,\n hasMxRecords,\n getMxRecords,\n checkMisc,\n checkDisposable,\n checkRoleAccount,\n checkFreeProvider,\n};\n","/**\n * Normalize an email address\n * - Trims whitespace\n * - Converts to lowercase\n * - Removes dots from Gmail usernames (optional)\n *\n * @param email The email to normalize\n * @param options Normalization options\n * @returns Normalized email address\n */\nexport function normalizeEmail(\n email: string,\n options: {\n /** Remove dots from Gmail-style addresses */\n removeDots?: boolean;\n /** Remove plus addressing suffix */\n removePlusAddressing?: boolean;\n } = {}\n): string {\n let normalized = email.trim().toLowerCase();\n\n const atIndex = normalized.indexOf(\"@\");\n if (atIndex === -1) {\n return normalized;\n }\n\n let username = normalized.slice(0, atIndex);\n const domain = normalized.slice(atIndex + 1);\n\n // Remove plus addressing (e.g., user+tag@gmail.com -> user@gmail.com)\n if (options.removePlusAddressing) {\n const plusIndex = username.indexOf(\"+\");\n if (plusIndex !== -1) {\n username = username.slice(0, plusIndex);\n }\n }\n\n // Remove dots for Gmail addresses (gmail ignores dots in usernames)\n if (options.removeDots) {\n const gmailDomains = [\"gmail.com\", \"googlemail.com\"];\n if (gmailDomains.includes(domain)) {\n username = username.replace(/\\./g, \"\");\n }\n }\n\n return `${username}@${domain}`;\n}\n\n/**\n * Extract parts from an email address\n * @param email The email address\n * @returns Object with username and domain, or null if invalid\n */\nexport function extractParts(email: string): { username: string; domain: string } | null {\n const atIndex = email.indexOf(\"@\");\n if (atIndex === -1 || atIndex === 0 || atIndex === email.length - 1) {\n return null;\n }\n\n // Check for multiple @ signs\n if (email.indexOf(\"@\", atIndex + 1) !== -1) {\n return null;\n }\n\n return {\n username: email.slice(0, atIndex),\n domain: email.slice(atIndex + 1),\n };\n}\n\n/**\n * Clean a domain name (trim, lowercase, remove trailing dot)\n * @param domain The domain to clean\n * @returns Cleaned domain\n */\nexport function cleanDomain(domain: string): string {\n let cleaned = domain.trim().toLowerCase();\n\n // Remove trailing dot (FQDN format)\n if (cleaned.endsWith(\".\")) {\n cleaned = cleaned.slice(0, -1);\n }\n\n return cleaned;\n}\n","/**\n * Common domain typos and their corrections\n */\nconst domainTypos: Record<string, string> = {\n // Gmail typos\n \"gmial.com\": \"gmail.com\",\n \"gmal.com\": \"gmail.com\",\n \"gamil.com\": \"gmail.com\",\n \"gnail.com\": \"gmail.com\",\n \"gmaill.com\": \"gmail.com\",\n \"gmali.com\": \"gmail.com\",\n \"gmai.com\": \"gmail.com\",\n \"gmail.co\": \"gmail.com\",\n \"gmail.om\": \"gmail.com\",\n \"gmail.cm\": \"gmail.com\",\n \"gmail.cim\": \"gmail.com\",\n \"gmail.con\": \"gmail.com\",\n \"gmail.vom\": \"gmail.com\",\n \"gmail.xom\": \"gmail.com\",\n \"gmail.comm\": \"gmail.com\",\n \"gmail.ocm\": \"gmail.com\",\n \"gmaul.com\": \"gmail.com\",\n \"gmeil.com\": \"gmail.com\",\n \"gmsil.com\": \"gmail.com\",\n \"gmqil.com\": \"gmail.com\",\n \"gemail.com\": \"gmail.com\",\n \"g]mail.com\": \"gmail.com\",\n \"fmail.com\": \"gmail.com\",\n\n // Yahoo typos\n \"yaho.com\": \"yahoo.com\",\n \"yahooo.com\": \"yahoo.com\",\n \"yhoo.com\": \"yahoo.com\",\n \"yhaoo.com\": \"yahoo.com\",\n \"yaoo.com\": \"yahoo.com\",\n \"yahoo.co\": \"yahoo.com\",\n \"yahoo.om\": \"yahoo.com\",\n \"yahoo.cm\": \"yahoo.com\",\n \"yahoo.con\": \"yahoo.com\",\n \"yahoo.vom\": \"yahoo.com\",\n \"tahoo.com\": \"yahoo.com\",\n \"uahoo.com\": \"yahoo.com\",\n \"yagoo.com\": \"yahoo.com\",\n\n // Hotmail typos\n \"hotmial.com\": \"hotmail.com\",\n \"hotmal.com\": \"hotmail.com\",\n \"hotmai.com\": \"hotmail.com\",\n \"homail.com\": \"hotmail.com\",\n \"hotmil.com\": \"hotmail.com\",\n \"hotamail.com\": \"hotmail.com\",\n \"hotmaill.com\": \"hotmail.com\",\n \"hotmail.co\": \"hotmail.com\",\n \"hotmail.om\": \"hotmail.com\",\n \"hotmail.cm\": \"hotmail.com\",\n \"hotmail.con\": \"hotmail.com\",\n \"hitmail.com\": \"hotmail.com\",\n \"hormail.com\": \"hotmail.com\",\n \"hptmail.com\": \"hotmail.com\",\n \"hotmaiil.com\": \"hotmail.com\",\n\n // Outlook typos\n \"outlok.com\": \"outlook.com\",\n \"outloo.com\": \"outlook.com\",\n \"outlook.co\": \"outlook.com\",\n \"outlook.om\": \"outlook.com\",\n \"outlook.cm\": \"outlook.com\",\n \"outlook.con\": \"outlook.com\",\n \"outllook.com\": \"outlook.com\",\n \"outlookk.com\": \"outlook.com\",\n \"outloook.com\": \"outlook.com\",\n \"putlook.com\": \"outlook.com\",\n \"oitlook.com\": \"outlook.com\",\n \"outlool.com\": \"outlook.com\",\n\n // iCloud typos\n \"iclould.com\": \"icloud.com\",\n \"icloud.co\": \"icloud.com\",\n \"icloud.om\": \"icloud.com\",\n \"icoud.com\": \"icloud.com\",\n \"icloude.com\": \"icloud.com\",\n \"iclud.com\": \"icloud.com\",\n \"iclod.com\": \"icloud.com\",\n\n // Protonmail typos\n \"protonmal.com\": \"protonmail.com\",\n \"protonmial.com\": \"protonmail.com\",\n \"protonmai.com\": \"protonmail.com\",\n \"protonmail.co\": \"protonmail.com\",\n \"protonmail.om\": \"protonmail.com\",\n \"protonmail.cm\": \"protonmail.com\",\n \"protnmail.com\": \"protonmail.com\",\n \"protommail.com\": \"protonmail.com\",\n\n // AOL typos\n \"aol.co\": \"aol.com\",\n \"aol.om\": \"aol.com\",\n \"aol.cm\": \"aol.com\",\n \"ao.com\": \"aol.com\",\n \"aoll.com\": \"aol.com\",\n\n // Live typos\n \"live.co\": \"live.com\",\n \"live.om\": \"live.com\",\n \"live.cm\": \"live.com\",\n \"live.con\": \"live.com\",\n \"livve.com\": \"live.com\",\n\n // MSN typos\n \"msn.co\": \"msn.com\",\n \"msn.om\": \"msn.com\",\n \"msn.cm\": \"msn.com\",\n \"mns.com\": \"msn.com\",\n\n // Common TLD typos\n \".con\": \".com\",\n \".vom\": \".com\",\n \".cpm\": \".com\",\n \".ocm\": \".com\",\n \".co,\": \".com\",\n \".xom\": \".com\",\n \".cim\": \".com\",\n \".comm\": \".com\",\n \".ner\": \".net\",\n \".nte\": \".net\",\n \".nett\": \".net\",\n \".rog\": \".org\",\n \".ogr\": \".org\",\n \".orgg\": \".org\",\n};\n\n/**\n * Common popular domains for fuzzy matching\n */\nconst popularDomains = [\n \"gmail.com\",\n \"yahoo.com\",\n \"hotmail.com\",\n \"outlook.com\",\n \"icloud.com\",\n \"aol.com\",\n \"protonmail.com\",\n \"live.com\",\n \"msn.com\",\n \"mail.com\",\n \"zoho.com\",\n \"yandex.com\",\n \"gmx.com\",\n \"fastmail.com\",\n];\n\n/**\n * Calculate Levenshtein distance between two strings\n */\nfunction levenshteinDistance(str1: string, str2: string): number {\n const m = str1.length;\n const n = str2.length;\n const dp: number[][] = Array(m + 1)\n .fill(null)\n .map(() => Array(n + 1).fill(0));\n\n for (let i = 0; i <= m; i++) dp[i][0] = i;\n for (let j = 0; j <= n; j++) dp[0][j] = j;\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (str1[i - 1] === str2[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1];\n } else {\n dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);\n }\n }\n }\n\n return dp[m][n];\n}\n\n/**\n * Get a suggested correction for a domain\n * @param domain The domain to check for typos\n * @returns Suggested domain or null if no suggestion\n */\nexport function getSuggestion(domain: string): string | null {\n const lowerDomain = domain.toLowerCase();\n\n // Don't suggest alternatives for domains that are already valid popular domains\n if (popularDomains.includes(lowerDomain)) {\n return null;\n }\n\n // Check direct typo mapping\n if (domainTypos[lowerDomain]) {\n return domainTypos[lowerDomain];\n }\n\n // Check TLD typos\n for (const [typo, correction] of Object.entries(domainTypos)) {\n if (typo.startsWith(\".\") && lowerDomain.endsWith(typo)) {\n return lowerDomain.slice(0, -typo.length) + correction;\n }\n }\n\n // Fuzzy match against popular domains\n // Only suggest if distance is 1-2 (likely typo)\n let bestMatch: string | null = null;\n let bestDistance = Infinity;\n\n for (const popular of popularDomains) {\n const distance = levenshteinDistance(lowerDomain, popular);\n if (distance > 0 && distance <= 2 && distance < bestDistance) {\n bestDistance = distance;\n bestMatch = popular;\n }\n }\n\n return bestMatch;\n}\n\n/**\n * Get a suggestion for the full email address\n * @param email The email to check for typos\n * @returns Suggested email or null if no suggestion\n */\nexport function getEmailSuggestion(email: string): string | null {\n const atIndex = email.indexOf(\"@\");\n if (atIndex === -1) return null;\n\n const username = email.slice(0, atIndex);\n const domain = email.slice(atIndex + 1);\n\n const suggestedDomain = getSuggestion(domain);\n if (suggestedDomain && suggestedDomain !== domain.toLowerCase()) {\n return `${username}@${suggestedDomain}`;\n }\n\n return null;\n}\n","import type { SyntaxResult } from \"../types.js\";\nimport { normalizeEmail, extractParts } from \"../utils/normalize.js\";\nimport { getEmailSuggestion } from \"../utils/suggestions.js\";\n\n/**\n * RFC 5322 compliant email regex pattern\n * This is a simplified but practical version that covers most valid emails\n */\nconst EMAIL_REGEX =\n /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$/i;\n\n/**\n * Simpler regex for quick validation\n */\nconst SIMPLE_EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/**\n * Maximum email length per RFC 5321\n */\nconst MAX_EMAIL_LENGTH = 254;\n\n/**\n * Maximum local part length per RFC 5321\n */\nconst MAX_LOCAL_LENGTH = 64;\n\n/**\n * Maximum domain length\n */\nconst MAX_DOMAIN_LENGTH = 253;\n\n/**\n * Validate email syntax\n * @param email The email address to validate\n * @returns SyntaxResult with validation details\n */\nexport function validateSyntax(email: string): SyntaxResult {\n const trimmedEmail = email.trim();\n const normalizedEmail = normalizeEmail(trimmedEmail);\n\n // Default result for invalid emails\n const invalidResult: SyntaxResult = {\n address: trimmedEmail,\n domain: \"\",\n username: \"\",\n isValidSyntax: false,\n normalizedEmail,\n suggestion: getEmailSuggestion(normalizedEmail),\n };\n\n // Check for empty email\n if (!trimmedEmail) {\n return invalidResult;\n }\n\n // Check maximum length\n if (trimmedEmail.length > MAX_EMAIL_LENGTH) {\n return invalidResult;\n }\n\n // Extract parts\n const parts = extractParts(trimmedEmail);\n if (!parts) {\n return invalidResult;\n }\n\n const { username, domain } = parts;\n\n // Check local part length\n if (username.length > MAX_LOCAL_LENGTH) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Check domain length\n if (domain.length > MAX_DOMAIN_LENGTH) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Check for empty local part or domain\n if (!username || !domain) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Check domain has at least one dot (except for IP addresses)\n if (!domain.includes(\".\") && !domain.startsWith(\"[\")) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Validate domain labels\n const labels = domain.split(\".\");\n for (const label of labels) {\n // Each label must be 1-63 characters\n if (label.length === 0 || label.length > 63) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Labels cannot start or end with hyphen\n if (label.startsWith(\"-\") || label.endsWith(\"-\")) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Labels must be alphanumeric with hyphens\n if (!/^[a-z0-9-]+$/i.test(label)) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n }\n\n // TLD must be at least 2 characters and all alphabetic\n const tld = labels[labels.length - 1];\n if (tld.length < 2 || !/^[a-z]+$/i.test(tld)) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Quick regex validation\n if (!SIMPLE_EMAIL_REGEX.test(trimmedEmail)) {\n return {\n ...invalidResult,\n domain,\n username,\n };\n }\n\n // Full RFC 5322 validation (optional, for stricter validation)\n // Using the simpler regex for now as it covers most practical cases\n const isValid = EMAIL_REGEX.test(trimmedEmail);\n\n return {\n address: trimmedEmail,\n domain: domain.toLowerCase(),\n username,\n isValidSyntax: isValid,\n normalizedEmail,\n suggestion: isValid ? getEmailSuggestion(normalizedEmail) : invalidResult.suggestion,\n };\n}\n\n/**\n * Quick check if an email has valid syntax\n * @param email The email to check\n * @returns true if syntax is valid\n */\nexport function isValidSyntax(email: string): boolean {\n return validateSyntax(email).isValidSyntax;\n}\n","import dns from \"dns\";\nimport { promisify } from \"util\";\nimport type { MxResult, ValidationOptions } from \"../types.js\";\nimport { globalDnsCache, DnsCache } from \"../utils/cache.js\";\nimport { cleanDomain } from \"../utils/normalize.js\";\n\nconst resolveMx = promisify(dns.resolveMx);\nconst resolve4 = promisify(dns.resolve4);\nconst resolve6 = promisify(dns.resolve6);\n\n/**\n * MX record with priority\n */\ninterface MxRecord {\n priority: number;\n exchange: string;\n}\n\n/**\n * Sort MX records by priority (lower is better)\n */\nfunction sortMxRecords(records: MxRecord[]): string[] {\n return records\n .sort((a, b) => a.priority - b.priority)\n .map((r) => cleanDomain(r.exchange));\n}\n\n/**\n * Verify MX records for a domain\n * @param domain The domain to verify\n * @param options Validation options\n * @returns MxResult with verification details\n */\nexport async function verifyMx(\n domain: string,\n options: ValidationOptions = {},\n cache?: DnsCache\n): Promise<MxResult> {\n const cleanedDomain = cleanDomain(domain);\n const dnsCache = cache || globalDnsCache;\n\n // Check cache first\n if (options.useDnsCache !== false) {\n const cached = dnsCache.get(cleanedDomain);\n if (cached) {\n return {\n acceptsMail: cached.acceptsMail,\n records: cached.records,\n };\n }\n }\n\n try {\n // Try to resolve MX records\n const mxRecords = await resolveMx(cleanedDomain);\n\n if (!mxRecords || mxRecords.length === 0) {\n // No MX records, try A/AAAA fallback\n return await fallbackToAddressRecords(cleanedDomain, dnsCache, options);\n }\n\n // Check for null MX record (RFC 7505)\n // A null MX is indicated by a single MX record with priority 0 and empty exchange\n if (\n mxRecords.length === 1 &&\n mxRecords[0].priority === 0 &&\n (mxRecords[0].exchange === \"\" ||\n mxRecords[0].exchange === \".\" ||\n mxRecords[0].exchange === \"0.0.0.0\")\n ) {\n const result: MxResult = {\n acceptsMail: false,\n records: [],\n };\n\n // Cache the result\n if (options.useDnsCache !== false) {\n dnsCache.set(cleanedDomain, [], false);\n }\n\n return result;\n }\n\n // Sort and clean MX records\n const sortedRecords = sortMxRecords(mxRecords);\n\n // Filter out invalid records\n const validRecords = sortedRecords.filter(\n (r) => r && r !== \"\" && r !== \".\" && r !== \"0.0.0.0\" && r !== \"localhost\"\n );\n\n if (validRecords.length === 0) {\n // All MX records were invalid, try A/AAAA fallback\n return await fallbackToAddressRecords(cleanedDomain, dnsCache, options);\n }\n\n const result: MxResult = {\n acceptsMail: true,\n records: validRecords,\n };\n\n // Cache the result\n if (options.useDnsCache !== false) {\n dnsCache.set(cleanedDomain, validRecords, true);\n }\n\n return result;\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n\n // Handle specific DNS errors\n if (err.code === \"ENODATA\" || err.code === \"ENOTFOUND\") {\n // No MX records found, try A/AAAA fallback\n return await fallbackToAddressRecords(cleanedDomain, dnsCache, options);\n }\n\n if (err.code === \"ENOTFOUND\" || err.code === \"SERVFAIL\") {\n // Domain does not exist\n const result: MxResult = {\n acceptsMail: false,\n records: [],\n };\n\n // Cache the result\n if (options.useDnsCache !== false) {\n dnsCache.set(cleanedDomain, [], false);\n }\n\n return result;\n }\n\n // For other errors, return unknown state\n return {\n acceptsMail: false,\n records: [],\n };\n }\n}\n\n/**\n * Fallback to A/AAAA records when no MX records exist\n * Per RFC 5321, if no MX records exist, the domain itself can be used as the mail host\n */\nasync function fallbackToAddressRecords(\n domain: string,\n cache: DnsCache,\n options: ValidationOptions\n): Promise<MxResult> {\n try {\n // Try A record first\n const aRecords = await resolve4(domain);\n if (aRecords && aRecords.length > 0) {\n const result: MxResult = {\n acceptsMail: true,\n records: [domain], // Use the domain itself as the mail host\n };\n\n if (options.useDnsCache !== false) {\n cache.set(domain, [domain], true);\n }\n\n return result;\n }\n } catch {\n // A record lookup failed, try AAAA\n }\n\n try {\n // Try AAAA record\n const aaaaRecords = await resolve6(domain);\n if (aaaaRecords && aaaaRecords.length > 0) {\n const result: MxResult = {\n acceptsMail: true,\n records: [domain], // Use the domain itself as the mail host\n };\n\n if (options.useDnsCache !== false) {\n cache.set(domain, [domain], true);\n }\n\n return result;\n }\n } catch {\n // AAAA record lookup also failed\n }\n\n // No valid records found\n const result: MxResult = {\n acceptsMail: false,\n records: [],\n };\n\n if (options.useDnsCache !== false) {\n cache.set(domain, [], false);\n }\n\n return result;\n}\n\n/**\n * Check if a domain has valid MX records\n * @param domain The domain to check\n * @returns true if domain has valid MX records\n */\nexport async function hasMxRecords(domain: string): Promise<boolean> {\n const result = await verifyMx(domain);\n return result.acceptsMail;\n}\n\n/**\n * Get MX records for a domain, sorted by priority\n * @param domain The domain to lookup\n * @returns Array of MX hostnames sorted by priority\n */\nexport async function getMxRecords(domain: string): Promise<string[]> {\n const result = await verifyMx(domain);\n return result.records;\n}\n","import type { DnsCacheEntry } from \"../types.js\";\n\n/**\n * Simple in-memory DNS cache with TTL support\n */\nexport class DnsCache {\n private cache: Map<string, DnsCacheEntry> = new Map();\n private ttl: number;\n\n /**\n * Create a new DNS cache\n * @param ttl Time-to-live in milliseconds (default: 5 minutes)\n */\n constructor(ttl: number = 300000) {\n this.ttl = ttl;\n }\n\n /**\n * Get a cached entry for a domain\n * @param domain The domain to look up\n * @returns The cached entry or null if not found/expired\n */\n get(domain: string): DnsCacheEntry | null {\n const key = domain.toLowerCase();\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n // Check if entry has expired\n if (Date.now() - entry.timestamp > this.ttl) {\n this.cache.delete(key);\n return null;\n }\n\n return entry;\n }\n\n /**\n * Set a cache entry for a domain\n * @param domain The domain to cache\n * @param records The MX records\n * @param acceptsMail Whether the domain accepts mail\n */\n set(domain: string, records: string[], acceptsMail: boolean): void {\n const key = domain.toLowerCase();\n this.cache.set(key, {\n records,\n acceptsMail,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Clear all cached entries\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Remove expired entries from the cache\n */\n cleanup(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now - entry.timestamp > this.ttl) {\n this.cache.delete(key);\n }\n }\n }\n\n /**\n * Get the number of cached entries\n */\n get size(): number {\n return this.cache.size;\n }\n\n /**\n * Set the TTL for the cache\n * @param ttl Time-to-live in milliseconds\n */\n setTtl(ttl: number): void {\n this.ttl = ttl;\n }\n}\n\n// Global DNS cache instance\nexport const globalDnsCache = new DnsCache();\n","import net from \"net\";\nimport os from \"os\";\nimport type { SmtpResult, SmtpResponse, ValidationOptions } from \"../types.js\";\n\n/**\n * Default SMTP port\n */\nconst SMTP_PORT = 25;\n\n/**\n * Default timeout in milliseconds\n */\nconst DEFAULT_TIMEOUT = 10000;\n\n/**\n * SMTP error types\n */\nexport const SmtpErrorType = {\n CONNECTION_FAILED: \"ConnectionFailed\",\n TIMEOUT: \"Timeout\",\n INVALID_RESPONSE: \"InvalidResponse\",\n HELO_FAILED: \"HeloFailed\",\n MAIL_FROM_FAILED: \"MailFromFailed\",\n RCPT_TO_FAILED: \"RcptToFailed\",\n MAILBOX_NOT_FOUND: \"MailboxNotFound\",\n MAILBOX_DISABLED: \"MailboxDisabled\",\n GREYLISTED: \"Greylisted\",\n BLOCKED: \"Blocked\",\n UNKNOWN: \"Unknown\",\n} as const;\n\n/**\n * Parse an SMTP response line\n */\nfunction parseResponse(data: string): SmtpResponse {\n const lines = data.trim().split(\"\\r\\n\");\n const lastLine = lines[lines.length - 1];\n const code = parseInt(lastLine.substring(0, 3), 10);\n const message = lastLine.substring(4);\n\n return { code, message };\n}\n\n/**\n * Check if a response indicates success (2xx or 3xx)\n */\nfunction isSuccessResponse(code: number): boolean {\n return code >= 200 && code < 400;\n}\n\n/**\n * Send a command and wait for response\n */\nfunction sendCommand(\n socket: net.Socket,\n command: string,\n timeout: number\n): Promise<SmtpResponse> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(\"Command timeout\"));\n }, timeout);\n\n const onData = (data: Buffer) => {\n clearTimeout(timeoutId);\n socket.removeListener(\"data\", onData);\n socket.removeListener(\"error\", onError);\n\n const response = parseResponse(data.toString());\n resolve(response);\n };\n\n const onError = (err: Error) => {\n clearTimeout(timeoutId);\n socket.removeListener(\"data\", onData);\n reject(err);\n };\n\n socket.once(\"data\", onData);\n socket.once(\"error\", onError);\n\n if (command) {\n socket.write(command + \"\\r\\n\");\n }\n });\n}\n\n/**\n * Wait for server greeting\n */\nfunction waitForGreeting(socket: net.Socket, timeout: number): Promise<SmtpResponse> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(\"Greeting timeout\"));\n }, timeout);\n\n const onData = (data: Buffer) => {\n clearTimeout(timeoutId);\n socket.removeListener(\"data\", onData);\n socket.removeListener(\"error\", onError);\n\n const response = parseResponse(data.toString());\n resolve(response);\n };\n\n const onError = (err: Error) => {\n clearTimeout(timeoutId);\n socket.removeListener(\"data\", onData);\n reject(err);\n };\n\n socket.once(\"data\", onData);\n socket.once(\"error\", onError);\n });\n}\n\n/**\n * Generate a random email for catch-all detection\n */\nfunction generateRandomEmail(domain: string): string {\n const random = Math.random().toString(36).substring(2, 15);\n return `${random}@${domain}`;\n}\n\n/**\n * Verify an email address via SMTP\n * @param email The email address to verify\n * @param mxHost The MX host to connect to\n * @param options Validation options\n * @returns SmtpResult with verification details\n */\nexport async function verifySmtp(\n email: string,\n mxHost: string,\n options: ValidationOptions = {}\n): Promise<SmtpResult> {\n const timeout = options.smtpTimeout || DEFAULT_TIMEOUT;\n const heloHost = options.heloHost || os.hostname() || \"localhost\";\n const senderAddress = options.senderAddress || \"\";\n const detectCatchAll = options.detectCatchAll !== false;\n\n const domain = email.split(\"@\")[1];\n\n return new Promise((resolve) => {\n const socket = new net.Socket();\n let resolved = false;\n\n const cleanup = () => {\n if (!socket.destroyed) {\n try {\n socket.write(\"QUIT\\r\\n\");\n } catch {\n // Ignore write errors during cleanup\n }\n socket.destroy();\n }\n };\n\n const finish = (result: SmtpResult) => {\n if (!resolved) {\n resolved = true;\n cleanup();\n resolve(result);\n }\n };\n\n // Set socket timeout\n socket.setTimeout(timeout);\n\n socket.on(\"timeout\", () => {\n finish({\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.TIMEOUT,\n message: \"Connection timed out\",\n },\n });\n });\n\n socket.on(\"error\", (err) => {\n finish({\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.CONNECTION_FAILED,\n message: err.message,\n },\n });\n });\n\n socket.connect(SMTP_PORT, mxHost, async () => {\n try {\n // Wait for server greeting\n const greeting = await waitForGreeting(socket, timeout);\n if (!isSuccessResponse(greeting.code)) {\n finish({\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.BLOCKED,\n message: `Server rejected connection: ${greeting.message}`,\n },\n });\n return;\n }\n\n // Send EHLO (try EHLO first, fall back to HELO)\n let heloResponse = await sendCommand(socket, `EHLO ${heloHost}`, timeout);\n if (!isSuccessResponse(heloResponse.code)) {\n heloResponse = await sendCommand(socket, `HELO ${heloHost}`, timeout);\n if (!isSuccessResponse(heloResponse.code)) {\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.HELO_FAILED,\n message: `HELO failed: ${heloResponse.message}`,\n },\n });\n return;\n }\n }\n\n // Send MAIL FROM\n const mailFromResponse = await sendCommand(\n socket,\n `MAIL FROM:<${senderAddress}>`,\n timeout\n );\n if (!isSuccessResponse(mailFromResponse.code)) {\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.MAIL_FROM_FAILED,\n message: `MAIL FROM failed: ${mailFromResponse.message}`,\n },\n });\n return;\n }\n\n // Send RCPT TO for the actual email\n const rcptResponse = await sendCommand(socket, `RCPT TO:<${email}>`, timeout);\n\n // Check if this is a catch-all domain\n let isCatchAll = false;\n if (detectCatchAll && isSuccessResponse(rcptResponse.code)) {\n // Try a random email to detect catch-all\n const randomEmail = generateRandomEmail(domain);\n const catchAllResponse = await sendCommand(\n socket,\n `RCPT TO:<${randomEmail}>`,\n timeout\n );\n isCatchAll = isSuccessResponse(catchAllResponse.code);\n }\n\n // Interpret the response\n if (isSuccessResponse(rcptResponse.code)) {\n // 250 - Mailbox exists\n finish({\n canConnectSmtp: true,\n isDeliverable: true,\n isCatchAll,\n error: null,\n });\n } else if (rcptResponse.code === 550) {\n // 550 - Mailbox not found\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.MAILBOX_NOT_FOUND,\n message: rcptResponse.message,\n },\n });\n } else if (rcptResponse.code === 551 || rcptResponse.code === 553) {\n // 551/553 - User not local or mailbox name not allowed\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.MAILBOX_NOT_FOUND,\n message: rcptResponse.message,\n },\n });\n } else if (rcptResponse.code === 552) {\n // 552 - Mailbox full/disabled\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.MAILBOX_DISABLED,\n message: rcptResponse.message,\n },\n });\n } else if (rcptResponse.code === 450 || rcptResponse.code === 451) {\n // 450/451 - Greylisting or temporary failure\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.GREYLISTED,\n message: rcptResponse.message,\n },\n });\n } else if (rcptResponse.code >= 500) {\n // Other 5xx errors\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.RCPT_TO_FAILED,\n message: rcptResponse.message,\n },\n });\n } else {\n // Unknown response\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.UNKNOWN,\n message: `Unexpected response code ${rcptResponse.code}: ${rcptResponse.message}`,\n },\n });\n }\n } catch (err) {\n const error = err as Error;\n finish({\n canConnectSmtp: true,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.UNKNOWN,\n message: error.message,\n },\n });\n }\n });\n });\n}\n\n/**\n * Try SMTP verification against multiple MX hosts\n * Falls back to the next host if the first fails\n */\nexport async function verifySmtpWithFallback(\n email: string,\n mxHosts: string[],\n options: ValidationOptions = {}\n): Promise<SmtpResult> {\n if (mxHosts.length === 0) {\n return {\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.CONNECTION_FAILED,\n message: \"No MX hosts available\",\n },\n };\n }\n\n let lastResult: SmtpResult | null = null;\n\n for (const mxHost of mxHosts) {\n const result = await verifySmtp(email, mxHost, options);\n\n // If we got a definitive answer, return it\n if (result.isDeliverable || result.error?.type === SmtpErrorType.MAILBOX_NOT_FOUND) {\n return result;\n }\n\n // If we could connect, save the result\n if (result.canConnectSmtp) {\n lastResult = result;\n }\n\n // If connection failed, try the next host\n if (!result.canConnectSmtp) {\n lastResult = result;\n continue;\n }\n }\n\n // Return the last result, or a generic error\n return (\n lastResult || {\n canConnectSmtp: false,\n isDeliverable: false,\n isCatchAll: false,\n error: {\n type: SmtpErrorType.CONNECTION_FAILED,\n message: \"Failed to connect to any MX host\",\n },\n }\n );\n}\n","import crypto from \"crypto\";\nimport https from \"https\";\nimport type { MiscResult, ValidationOptions } from \"../types.js\";\nimport { isDisposableDomain } from \"../data/disposable.js\";\nimport { isRolePrefix } from \"../data/roles.js\";\nimport { isFreeProvider } from \"../data/free-providers.js\";\n\n/**\n * Check if an email is from a disposable domain\n */\nexport function checkDisposable(domain: string): boolean {\n return isDisposableDomain(domain.toLowerCase());\n}\n\n/**\n * Check if an email is a role-based account\n */\nexport function checkRoleAccount(username: string): boolean {\n // Remove any plus addressing\n const cleanUsername = username.split(\"+\")[0];\n return isRolePrefix(cleanUsername.toLowerCase());\n}\n\n/**\n * Check if an email is from a free provider\n */\nexport function checkFreeProvider(domain: string): boolean {\n return isFreeProvider(domain.toLowerCase());\n}\n\n/**\n * Generate MD5 hash of email for Gravatar\n */\nfunction md5(str: string): string {\n return crypto.createHash(\"md5\").update(str.trim().toLowerCase()).digest(\"hex\");\n}\n\n/**\n * Check if an email has a Gravatar\n * @param email The email to check\n * @returns Gravatar URL or null if no Gravatar exists\n */\nexport function checkGravatar(email: string): Promise<string | null> {\n return new Promise((resolve) => {\n const hash = md5(email);\n const url = `https://www.gravatar.com/avatar/${hash}?d=404`;\n\n const req = https.get(url, { timeout: 5000 }, (res) => {\n if (res.statusCode === 200) {\n resolve(`https://www.gravatar.com/avatar/${hash}`);\n } else {\n resolve(null);\n }\n res.resume(); // Consume response data to free up memory\n });\n\n req.on(\"error\", () => {\n resolve(null);\n });\n\n req.on(\"timeout\", () => {\n req.destroy();\n resolve(null);\n });\n });\n}\n\n/**\n * Perform miscellaneous checks on an email\n * @param email The email address\n * @param options Validation options\n * @returns MiscResult with check results\n */\nexport async function checkMisc(\n email: string,\n options: ValidationOptions = {}\n): Promise<MiscResult> {\n const atIndex = email.indexOf(\"@\");\n if (atIndex === -1) {\n return {\n isDisposable: false,\n isRoleAccount: false,\n isFreeProvider: false,\n gravatarUrl: null,\n };\n }\n\n const username = email.slice(0, atIndex);\n const domain = email.slice(atIndex + 1);\n\n const isDisposable =\n options.checkDisposable !== false ? checkDisposable(domain) : false;\n const isRoleAccount =\n options.checkRoleAccount !== false ? checkRoleAccount(username) : false;\n const isFree =\n options.checkFreeProvider !== false ? checkFreeProvider(domain) : false;\n\n let gravatarUrl: string | null = null;\n if (options.checkGravatar === true) {\n gravatarUrl = await checkGravatar(email);\n }\n\n return {\n isDisposable,\n isRoleAccount,\n isFreeProvider: isFree,\n gravatarUrl,\n };\n}\n","/**\n * List of known disposable email domains\n * This list includes temporary email services that should be flagged\n */\nexport const disposableDomains: Set<string> = new Set([\n // Popular disposable email services\n \"10minutemail.com\",\n \"10minutemail.net\",\n \"20minutemail.com\",\n \"33mail.com\",\n \"guerrillamail.com\",\n \"guerrillamail.org\",\n \"guerrillamail.net\",\n \"guerrillamail.biz\",\n \"guerrillamail.de\",\n \"guerrillamailblock.com\",\n \"sharklasers.com\",\n \"grr.la\",\n \"pokemail.net\",\n \"spam4.me\",\n \"mailinator.com\",\n \"mailinator.net\",\n \"mailinator.org\",\n \"mailinator2.com\",\n \"mailinater.com\",\n \"tempmail.com\",\n \"tempmail.net\",\n \"temp-mail.org\",\n \"temp-mail.io\",\n \"tempail.com\",\n \"tempmailaddress.com\",\n \"throwaway.email\",\n \"throwawaymail.com\",\n \"trashmail.com\",\n \"trashmail.net\",\n \"trashmail.org\",\n \"trashmail.me\",\n \"trashemail.de\",\n \"fakeinbox.com\",\n \"fakemailgenerator.com\",\n \"getnada.com\",\n \"nada.email\",\n \"getairmail.com\",\n \"airmail.cc\",\n \"dispostable.com\",\n \"disposableemailaddresses.com\",\n \"emailondeck.com\",\n \"yopmail.com\",\n \"yopmail.fr\",\n \"yopmail.net\",\n \"cool.fr.nf\",\n \"jetable.fr.nf\",\n \"nospam.ze.tc\",\n \"nomail.xl.cx\",\n \"mega.zik.dj\",\n \"speed.1s.fr\",\n \"courriel.fr.nf\",\n \"moncourrier.fr.nf\",\n \"monemail.fr.nf\",\n \"monmail.fr.nf\",\n \"mohmal.com\",\n \"mailnesia.com\",\n \"maildrop.cc\",\n \"mailsac.com\",\n \"mintemail.com\",\n \"mytemp.email\",\n \"mytrashmail.com\",\n \"nowmymail.com\",\n \"spambox.us\",\n \"spamfree24.org\",\n \"spamgourmet.com\",\n \"spamspot.com\",\n \"tempinbox.com\",\n \"tempomail.fr\",\n \"temporaryemail.net\",\n \"temporaryforwarding.com\",\n \"temporaryinbox.com\",\n \"thankyou2010.com\",\n \"thisisnotmyrealemail.com\",\n \"throam.com\",\n \"tmail.ws\",\n \"tmpmail.net\",\n \"tmpmail.org\",\n \"wegwerfmail.de\",\n \"wegwerfmail.net\",\n \"wegwerfmail.org\",\n \"wh4f.org\",\n \"willhackforfood.biz\",\n \"willselfdestruct.com\",\n \"emailfake.com\",\n \"emkei.cz\",\n \"anonymbox.com\",\n \"discard.email\",\n \"discardmail.com\",\n \"discardmail.de\",\n \"spambog.com\",\n \"spambog.de\",\n \"spambog.ru\",\n \"mailcatch.com\",\n \"mail-temp.com\",\n \"mailtemp.info\",\n \"mailzilla.com\",\n \"mailzilla.org\",\n \"binkmail.com\",\n \"bobmail.info\",\n \"burnthespam.info\",\n \"buyusedlibrarybooks.org\",\n \"byom.de\",\n \"deadaddress.com\",\n \"despam.it\",\n \"devnullmail.com\",\n \"dfgh.net\",\n \"e4ward.com\",\n \"emailias.com\",\n \"emailigo.de\",\n \"emailsensei.com\",\n \"emailtemporario.com.br\",\n \"emailwarden.com\",\n \"explodemail.com\",\n \"fastacura.com\",\n \"filzmail.com\",\n \"fizmail.com\",\n \"frapmail.com\",\n \"gishpuppy.com\",\n \"great-host.in\",\n \"greensloth.com\",\n \"haltospam.com\",\n \"hidzz.com\",\n \"hmamail.com\",\n \"imails.info\",\n \"incognitomail.com\",\n \"incognitomail.net\",\n \"incognitomail.org\",\n \"infocom.zp.ua\",\n \"instantemailaddress.com\",\n \"ipoo.org\",\n \"irish2me.com\",\n \"jetable.com\",\n \"kasmail.com\",\n \"klassmaster.com\",\n \"klzlv.com\",\n \"koszmail.pl\",\n \"kulturbetrieb.info\",\n \"kurzepost.de\",\n \"lawlita.com\",\n \"letthemeatspam.com\",\n \"lhsdv.com\",\n \"lifebyfood.com\",\n \"link2mail.net\",\n \"litedrop.com\",\n \"lol.ovpn.to\",\n \"lookugly.com\",\n \"lortemail.dk\",\n \"lovemeleaveme.com\",\n \"lr78.com\",\n \"maboard.com\",\n \"mail2rss.org\",\n \"mail333.com\",\n \"mailbidon.com\",\n \"mailblocks.com\",\n \"maildu.de\",\n \"maileater.com\",\n \"mailexpire.com\",\n \"mailfa.tk\",\n \"mailfork.com\",\n \"mailfreeonline.com\",\n \"mailguard.me\",\n \"mailimate.com\",\n \"mailin8r.com\",\n \"mailinblack.com\",\n \"mailincubator.com\",\n \"mailme.ir\",\n \"mailme.lv\",\n \"mailmetrash.com\",\n \"mailmoat.com\",\n \"mailnull.com\",\n \"mailorg.org\",\n \"mailscrap.com\",\n \"mailshell.com\",\n \"mailsiphon.com\",\n \"mailslite.com\",\n \"mailtemp.net\",\n \"mailtothis.com\",\n \"mailzi.ru\",\n \"makemetheking.com\",\n \"mbx.cc\",\n \"mega.zik.dj\",\n \"meltmail.com\",\n \"messagebeamer.de\",\n \"mezimages.net\",\n \"mierdamail.com\",\n \"migmail.pl\",\n \"migumail.com\",\n \"mintemail.com\",\n \"moburl.com\",\n \"moncourrier.fr.nf\",\n \"monemail.fr.nf\",\n \"monmail.fr.nf\",\n \"monumentmail.com\",\n \"ms51.hinet.net\",\n \"msb.minsmail.com\",\n \"mt2009.com\",\n \"mx0.wwwnew.eu\",\n \"mycleaninbox.net\",\n \"mypartyclip.de\",\n \"myphantomemail.com\",\n \"mysamp.de\",\n \"myspaceinc.com\",\n \"myspaceinc.net\",\n \"myspacepimpedup.com\",\n \"mytempemail.com\",\n \"neomailbox.com\",\n \"nepwk.com\",\n \"nervmich.net\",\n \"nervtmansen.de\",\n \"netmails.com\",\n \"netmails.net\",\n \"netzidiot.de\",\n \"neverbox.com\",\n \"no-spam.ws\",\n \"nobulk.com\",\n \"noclickemail.com\",\n \"nogmailspam.info\",\n \"nomail.xl.cx\",\n \"nomail2me.com\",\n \"nomorespamemails.com\",\n \"nospam.ze.tc\",\n \"nospam4.us\",\n \"nospamfor.us\",\n \"nospammail.net\",\n \"notmailinator.com\",\n \"nowhere.org\",\n \"nowmymail.com\",\n \"nurfuerspam.de\",\n \"nus.edu.sg\",\n \"objectmail.com\",\n \"obobbo.com\",\n \"oneoffemail.com\",\n \"onewaymail.com\",\n \"onlatedotcom.info\",\n \"online.ms\",\n \"oopi.org\",\n \"opayq.com\",\n \"ordinaryamerican.net\",\n \"otherinbox.com\",\n \"ourklips.com\",\n \"outlawspam.com\",\n \"ovpn.to\",\n \"owlpic.com\",\n \"pancakemail.com\",\n \"pjjkp.com\",\n \"plexolan.de\",\n \"poczta.onet.pl\",\n \"politikerclub.de\",\n \"poofy.org\",\n \"pookmail.com\",\n \"privacy.net\",\n \"privy-mail.com\",\n \"privymail.de\",\n \"proxymail.eu\",\n \"prtnx.com\",\n \"punkass.com\",\n \"putthisinyourspamdatabase.com\",\n \"qq.com\",\n \"quickinbox.com\",\n \"quickmail.nl\",\n \"rcpt.at\",\n \"reallymymail.com\",\n \"realtyalerts.ca\",\n \"recode.me\",\n \"recursor.net\",\n \"recyclemail.dk\",\n \"regbypass.com\",\n \"regbypass.comsafe-mail.net\",\n \"rejectmail.com\",\n \"remail.cf\",\n \"rhyta.com\",\n \"rklips.com\",\n \"rmqkr.net\",\n \"rppkn.com\",\n \"rtrtr.com\",\n \"s0ny.net\",\n \"safe-mail.net\",\n \"safersignup.de\",\n \"safetymail.info\",\n \"safetypost.de\",\n \"sandelf.de\",\n \"saynotospams.com\",\n \"schafmail.de\",\n \"selfdestructingmail.com\",\n \"sendspamhere.com\",\n \"shieldemail.com\",\n \"shiftmail.com\",\n \"shitmail.me\",\n \"shortmail.net\",\n \"shut.name\",\n \"shut.ws\",\n \"sibmail.com\",\n \"sinnlos-mail.de\",\n \"siteposter.net\",\n \"skeefmail.com\",\n \"slaskpost.se\",\n \"slopsbox.com\",\n \"slowfoodfoothills.xyz\",\n \"smashmail.de\",\n \"smellfear.com\",\n \"snakemail.com\",\n \"sneakemail.com\",\n \"sneakmail.de\",\n \"snkmail.com\",\n \"sofimail.com\",\n \"sofort-mail.de\",\n \"softpls.asia\",\n \"sogetthis.com\",\n \"sohu.com\",\n \"soisz.com\",\n \"solvemail.info\",\n \"soodonims.com\",\n \"spam.la\",\n \"spam.su\",\n \"spamavert.com\",\n \"spambob.com\",\n \"spambob.net\",\n \"spambob.org\",\n \"spambog.com\",\n \"spambog.de\",\n \"spambog.ru\",\n \"spambox.info\",\n \"spambox.irishspringrealty.com\",\n \"spambox.us\",\n \"spamcannon.com\",\n \"spamcannon.net\",\n \"spamcero.com\",\n \"spamcon.org\",\n \"spamcorptastic.com\",\n \"spamcowboy.com\",\n \"spamcowboy.net\",\n \"spamcowboy.org\",\n \"spamday.com\",\n \"spamex.com\",\n \"spamfree.eu\",\n \"spamfree24.com\",\n \"spamfree24.de\",\n \"spamfree24.eu\",\n \"spamfree24.info\",\n \"spamfree24.net\",\n \"spamfree24.org\",\n \"spamgoes.in\",\n \"spamherelots.com\",\n \"spamhereplease.com\",\n \"spamhole.com\",\n \"spamify.com\",\n \"spaminator.de\",\n \"spamkill.info\",\n \"spaml.com\",\n \"spaml.de\",\n \"spammotel.com\",\n \"spamobox.com\",\n \"spamoff.de\",\n \"spamsalad.in\",\n \"spamslicer.com\",\n \"spamspot.com\",\n \"spamstack.net\",\n \"spamthis.co.uk\",\n \"spamtroll.net\",\n \"speed.1s.fr\",\n \"spoofmail.de\",\n \"squizzy.de\",\n \"ssoia.com\",\n \"startkeys.com\",\n \"stinkefinger.net\",\n \"stop-my-spam.cf\",\n \"stop-my-spam.com\",\n \"stop-my-spam.ga\",\n \"stop-my-spam.ml\",\n \"stop-my-spam.tk\",\n \"streetwisemail.com\",\n \"stuffmail.de\",\n \"supergreatmail.com\",\n \"supermailer.jp\",\n \"superrito.com\",\n \"superstachel.de\",\n \"suremail.info\",\n \"svk.jp\",\n \"sweetxxx.de\",\n \"tagyourself.com\",\n \"talkinator.com\",\n \"tapchicuoihoi.com\",\n \"techemail.com\",\n \"techgroup.me\",\n \"teewars.org\",\n \"teleosaurs.xyz\",\n \"teleworm.com\",\n \"teleworm.us\",\n \"temp.emeraldwebmail.com\",\n \"tempail.com\",\n \"tempalias.com\",\n \"tempe-mail.com\",\n \"tempemail.biz\",\n \"tempemail.co.za\",\n \"tempemail.com\",\n \"tempemail.net\",\n \"tempinbox.co.uk\",\n \"tempinbox.com\",\n \"tempmail.co\",\n \"tempmail.de\",\n \"tempmail.eu\",\n \"tempmail.it\",\n \"tempmail.net\",\n \"tempmail.us\",\n \"tempmail2.com\",\n \"tempmaildemo.com\",\n \"tempmailer.com\",\n \"tempmailer.de\",\n \"tempomail.fr\",\n \"temporarioemail.com.br\",\n \"temporaryemail.net\",\n \"temporaryemail.us\",\n \"temporaryforwarding.com\",\n \"temporaryinbox.com\",\n \"temporarymailaddress.com\",\n \"tempthe.net\",\n \"thankspam.info\",\n \"thankyou2010.com\",\n \"thecloudindex.com\",\n \"thelimestones.com\",\n \"thisisnotmyrealemail.com\",\n \"throam.com\",\n \"throwam.com\",\n \"throwawayemailaddress.com\",\n \"throwawaymail.com\",\n \"tilien.com\",\n \"tittbit.in\",\n \"tmailinator.com\",\n \"tmail.ws\",\n \"toiea.com\",\n \"tokenmail.de\",\n \"toomail.biz\",\n \"topranklist.de\",\n \"tradermail.info\",\n \"trash-amil.com\",\n \"trash-mail.at\",\n \"trash-mail.com\",\n \"trash-mail.de\",\n \"trash2009.com\",\n \"trash2010.com\",\n \"trash2011.com\",\n \"trashcanmail.com\",\n \"trashdevil.com\",\n \"trashdevil.de\",\n \"trashemail.de\",\n \"trashmail.at\",\n \"trashmail.com\",\n \"trashmail.de\",\n \"trashmail.me\",\n \"trashmail.net\",\n \"trashmail.org\",\n \"trashmail.ws\",\n \"trashmailer.com\",\n \"trashymail.com\",\n \"trashymail.net\",\n \"trbvm.com\",\n \"trickmail.net\",\n \"trillianpro.com\",\n \"tryalert.com\",\n \"turual.com\",\n \"twinmail.de\",\n \"tyldd.com\",\n \"uggsrock.com\",\n \"umail.net\",\n \"upliftnow.com\",\n \"uplipht.com\",\n \"uroid.com\",\n \"us.af\",\n \"valemail.net\",\n \"venompen.com\",\n \"veryrealemail.com\",\n \"viditag.com\",\n \"viralplays.com\",\n \"vpn.st\",\n \"vsimcard.com\",\n \"vubby.com\",\n \"wasteland.rfc822.org\",\n \"webemail.me\",\n \"webm4il.info\",\n \"webuser.in\",\n \"wee.my\",\n \"weg-werf-email.de\",\n \"wegwerf-emails.de\",\n \"wegwerfadresse.de\",\n \"wegwerfemail.com\",\n \"wegwerfemail.de\",\n \"wegwerfmail.de\",\n \"wegwerfmail.info\",\n \"wegwerfmail.net\",\n \"wegwerfmail.org\",\n \"wetrainbayarea.com\",\n \"wetrainbayarea.org\",\n \"wh4f.org\",\n \"whatiaas.com\",\n \"whatpaas.com\",\n \"whopy.com\",\n \"whtjddn.33mail.com\",\n \"whyspam.me\",\n \"willhackforfood.biz\",\n \"willselfdestruct.com\",\n \"winemaven.info\",\n \"wolfsmail.tk\",\n \"wollan.info\",\n \"worldspace.link\",\n \"wpdork.com\",\n \"wronghead.com\",\n \"wuzup.net\",\n \"wuzupmail.net\",\n \"wwwnew.eu\",\n \"xagloo.co\",\n \"xagloo.com\",\n \"xemaps.com\",\n \"xents.com\",\n \"xmaily.com\",\n \"xoxy.net\",\n \"yapped.net\",\n \"yep.it\",\n \"yogamaven.com\",\n \"yomail.info\",\n \"yopmail.com\",\n \"yopmail.fr\",\n \"yopmail.gq\",\n \"yopmail.net\",\n \"you-spam.com\",\n \"yourdomain.com\",\n \"ypmail.webarnak.fr.eu.org\",\n \"yuurok.com\",\n \"za.com\",\n \"zehnminuten.de\",\n \"zehnminutenmail.de\",\n \"zippymail.info\",\n \"zoaxe.com\",\n \"zoemail.com\",\n \"zoemail.net\",\n \"zoemail.org\",\n \"zomg.info\",\n \"zxcv.com\",\n \"zxcvbnm.com\",\n \"zzz.com\",\n]);\n\n/**\n * Check if a domain is a known disposable email domain\n */\nexport function isDisposableDomain(domain: string): boolean {\n return disposableDomains.has(domain.toLowerCase());\n}\n","/**\n * List of known role-based email prefixes\n * These are email addresses that typically go to a group or role rather than an individual\n */\nexport const rolePrefixes: Set<string> = new Set([\n // Administrative\n \"admin\",\n \"administrator\",\n \"postmaster\",\n \"hostmaster\",\n \"webmaster\",\n \"root\",\n \"sysadmin\",\n \"it\",\n \"tech\",\n \"technical\",\n\n // Support\n \"support\",\n \"help\",\n \"helpdesk\",\n \"customerservice\",\n \"customer-service\",\n \"customercare\",\n \"customer-care\",\n \"service\",\n \"assist\",\n \"assistance\",\n\n // Sales and Marketing\n \"sales\",\n \"marketing\",\n \"advertising\",\n \"ads\",\n \"promo\",\n \"promotions\",\n \"partners\",\n \"partnership\",\n \"partnerships\",\n \"affiliate\",\n \"affiliates\",\n \"leads\",\n \"enquiry\",\n \"enquiries\",\n \"inquiry\",\n \"inquiries\",\n\n // General Contact\n \"info\",\n \"information\",\n \"contact\",\n \"contactus\",\n \"contact-us\",\n \"hello\",\n \"hi\",\n \"hey\",\n \"mail\",\n \"email\",\n \"office\",\n \"general\",\n \"reception\",\n\n // Human Resources\n \"hr\",\n \"humanresources\",\n \"human-resources\",\n \"jobs\",\n \"careers\",\n \"career\",\n \"recruitment\",\n \"recruiting\",\n \"talent\",\n \"hiring\",\n \"resume\",\n \"resumes\",\n \"cv\",\n \"employment\",\n\n // Finance and Legal\n \"billing\",\n \"finance\",\n \"accounting\",\n \"accounts\",\n \"payroll\",\n \"invoices\",\n \"invoice\",\n \"payments\",\n \"payment\",\n \"legal\",\n \"compliance\",\n \"privacy\",\n \"gdpr\",\n\n // Media and PR\n \"press\",\n \"media\",\n \"pr\",\n \"publicrelations\",\n \"public-relations\",\n \"news\",\n \"newsroom\",\n \"communications\",\n \"comms\",\n\n // Security\n \"security\",\n \"abuse\",\n \"spam\",\n \"phishing\",\n \"fraud\",\n \"noc\",\n \"cert\",\n\n // Operations\n \"operations\",\n \"ops\",\n \"devops\",\n \"engineering\",\n \"dev\",\n \"development\",\n \"product\",\n \"feedback\",\n\n // Team/Group addresses\n \"team\",\n \"staff\",\n \"all\",\n \"everyone\",\n \"group\",\n \"department\",\n \"board\",\n \"management\",\n \"exec\",\n \"executive\",\n \"executives\",\n\n // E-commerce\n \"orders\",\n \"order\",\n \"shipping\",\n \"returns\",\n \"refunds\",\n \"shop\",\n \"store\",\n \"buy\",\n \"purchase\",\n \"checkout\",\n\n // Automated/System\n \"noreply\",\n \"no-reply\",\n \"donotreply\",\n \"do-not-reply\",\n \"mailer-daemon\",\n \"mailerdaemon\",\n \"bounce\",\n \"bounces\",\n \"auto\",\n \"autoresponder\",\n \"notifications\",\n \"notification\",\n \"alerts\",\n \"alert\",\n \"updates\",\n \"newsletter\",\n \"newsletters\",\n \"subscribe\",\n \"unsubscribe\",\n\n // Miscellaneous\n \"ftp\",\n \"www\",\n \"web\",\n \"api\",\n \"test\",\n \"testing\",\n \"demo\",\n \"sample\",\n \"example\",\n]);\n\n/**\n * Check if an email prefix is a role-based account\n */\nexport function isRolePrefix(prefix: string): boolean {\n return rolePrefixes.has(prefix.toLowerCase());\n}\n","/**\n * List of known free email providers\n * These are legitimate email services that offer free accounts\n */\nexport const freeProviders: Set<string> = new Set([\n // Google\n \"gmail.com\",\n \"googlemail.com\",\n\n // Microsoft\n \"outlook.com\",\n \"outlook.co.uk\",\n \"outlook.com.br\",\n \"outlook.com.au\",\n \"outlook.de\",\n \"outlook.fr\",\n \"outlook.it\",\n \"outlook.es\",\n \"outlook.jp\",\n \"hotmail.com\",\n \"hotmail.co.uk\",\n \"hotmail.com.br\",\n \"hotmail.com.au\",\n \"hotmail.de\",\n \"hotmail.fr\",\n \"hotmail.it\",\n \"hotmail.es\",\n \"hotmail.co.jp\",\n \"live.com\",\n \"live.co.uk\",\n \"live.com.au\",\n \"live.de\",\n \"live.fr\",\n \"live.it\",\n \"live.nl\",\n \"live.se\",\n \"msn.com\",\n\n // Yahoo\n \"yahoo.com\",\n \"yahoo.co.uk\",\n \"yahoo.com.br\",\n \"yahoo.com.au\",\n \"yahoo.de\",\n \"yahoo.fr\",\n \"yahoo.it\",\n \"yahoo.es\",\n \"yahoo.co.jp\",\n \"yahoo.co.in\",\n \"yahoo.ca\",\n \"yahoo.com.mx\",\n \"yahoo.com.ar\",\n \"yahoo.com.sg\",\n \"yahoo.co.id\",\n \"yahoo.com.ph\",\n \"yahoo.com.tw\",\n \"yahoo.com.hk\",\n \"yahoo.ie\",\n \"yahoo.co.nz\",\n \"yahoo.com.vn\",\n \"ymail.com\",\n \"rocketmail.com\",\n\n // Apple\n \"icloud.com\",\n \"me.com\",\n \"mac.com\",\n\n // AOL\n \"aol.com\",\n \"aol.co.uk\",\n \"aol.de\",\n \"aol.fr\",\n \"aim.com\",\n\n // Proton\n \"protonmail.com\",\n \"protonmail.ch\",\n \"proton.me\",\n \"pm.me\",\n\n // Zoho\n \"zoho.com\",\n \"zohomail.com\",\n \"zohomail.in\",\n \"zohomail.eu\",\n\n // Mail.com\n \"mail.com\",\n \"email.com\",\n \"usa.com\",\n \"myself.com\",\n \"consultant.com\",\n \"post.com\",\n \"europe.com\",\n \"asia.com\",\n \"iname.com\",\n \"writeme.com\",\n \"dr.com\",\n \"cheerful.com\",\n \"accountant.com\",\n \"techie.com\",\n \"engineer.com\",\n \"activist.com\",\n \"contractor.com\",\n \"artlover.com\",\n\n // GMX\n \"gmx.com\",\n \"gmx.net\",\n \"gmx.de\",\n \"gmx.at\",\n \"gmx.ch\",\n \"gmx.fr\",\n \"gmx.co.uk\",\n \"gmx.us\",\n\n // Tutanota/Tuta\n \"tutanota.com\",\n \"tutanota.de\",\n \"tutamail.com\",\n \"tuta.io\",\n \"keemail.me\",\n\n // Fastmail\n \"fastmail.com\",\n \"fastmail.fm\",\n\n // Mailfence\n \"mailfence.com\",\n\n // Hushmail\n \"hushmail.com\",\n \"hush.com\",\n \"hush.ai\",\n \"mac.hush.com\",\n\n // Runbox\n \"runbox.com\",\n\n // Posteo\n \"posteo.de\",\n \"posteo.net\",\n\n // Yandex\n \"yandex.com\",\n \"yandex.ru\",\n \"yandex.ua\",\n \"yandex.by\",\n \"yandex.kz\",\n \"ya.ru\",\n\n // Mail.ru\n \"mail.ru\",\n \"inbox.ru\",\n \"list.ru\",\n \"bk.ru\",\n\n // Chinese providers\n \"qq.com\",\n \"163.com\",\n \"126.com\",\n \"sina.com\",\n \"sina.cn\",\n \"sohu.com\",\n \"aliyun.com\",\n \"foxmail.com\",\n\n // Indian providers\n \"rediffmail.com\",\n \"rediff.com\",\n\n // European providers\n \"web.de\",\n \"t-online.de\",\n \"freenet.de\",\n \"arcor.de\",\n \"orange.fr\",\n \"laposte.net\",\n \"free.fr\",\n \"sfr.fr\",\n \"wanadoo.fr\",\n \"libero.it\",\n \"virgilio.it\",\n \"tin.it\",\n \"alice.it\",\n \"tiscali.it\",\n \"tiscali.co.uk\",\n \"terra.com.br\",\n \"uol.com.br\",\n \"bol.com.br\",\n \"ig.com.br\",\n \"wp.pl\",\n \"onet.pl\",\n \"interia.pl\",\n \"o2.pl\",\n \"seznam.cz\",\n \"centrum.cz\",\n \"azet.sk\",\n\n // Misc\n \"inbox.com\",\n \"lycos.com\",\n \"naver.com\",\n \"daum.net\",\n \"hanmail.net\",\n \"comcast.net\",\n \"verizon.net\",\n \"att.net\",\n \"sbcglobal.net\",\n \"bellsouth.net\",\n \"charter.net\",\n \"cox.net\",\n \"earthlink.net\",\n \"juno.com\",\n \"netzero.net\",\n \"optonline.net\",\n \"btinternet.com\",\n \"talktalk.net\",\n \"virginmedia.com\",\n \"sky.com\",\n \"ntlworld.com\",\n \"shaw.ca\",\n \"rogers.com\",\n \"sympatico.ca\",\n \"telus.net\",\n \"bigpond.com\",\n \"bigpond.net.au\",\n \"optusnet.com.au\",\n \"ozemail.com.au\",\n]);\n\n/**\n * Check if a domain is a known free email provider\n */\nexport function isFreeProvider(domain: string): boolean {\n return freeProviders.has(domain.toLowerCase());\n}\n"],"mappings":"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CGX,IAAM,oBAAiC,oBAAI,IAAI;AAAA;AAAA,EAEpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAKM,SAAS,mBAAmB,QAAyB;AAC1D,SAAO,kBAAkB,IAAI,OAAO,YAAY,CAAC;AACnD;;;ACpiBO,IAAM,eAA4B,oBAAI,IAAI;AAAA;AAAA,EAE/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAKM,SAAS,aAAa,QAAyB;AACpD,SAAO,aAAa,IAAI,OAAO,YAAY,CAAC;AAC9C;;;ACtLO,IAAM,gBAA6B,oBAAI,IAAI;AAAA;AAAA,EAEhD;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EAC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","names":["dns","result","os","net","crypto","https","miscResult"]}
|