import { Zynor } from "../resolver.js"; import type { ZynorConfig, AbortOptions, MxRecord } from "../types.js"; import { EmailProviderName } from "./options.js"; /** * Logger signature for debug output. Receives one preformatted line per event. */ export type DebugLogger = (line: string) => void; /** * Verbosity level for debug logging. * - `info` — top-level checkpoints only: validate() enter/exit, MX result, * shallow/deep/Invalid outcome, deep-validation enter/exit, * validateBulk phase boundaries. Best for spotting *where* a hang * occurs without drowning in noise. * - `debug` — adds sub-operations: cache hits/misses, MX→record matches, * domain_check probes, dnsLookup per-IP iteration, IP-cascade * HTTP calls, per-EmailProviders match. * - `trace` — adds every event: inflight hit/cleared, per-mx loop iterations, * per-worker bulk progress, syntax/rejected/disposable early * returns. Use only when `debug` doesn't pinpoint the issue. */ export type DebugLevel = 'info' | 'debug' | 'trace'; export interface ValidationConfig { /** * Structured debug logging for the validation flow. Off by default. * * - `false` / omitted — silent (no overhead) * - `true` — `info` level, logged to stderr via `console.error` * - `'info' | 'debug' | 'trace'` — that level on stderr * - `(line: string) => void` — `trace` level, each line passed to fn * - `{ level, log }` — both explicit * * Each line is `[zynor HH:MM:SS.mmm ] : `. * * @default false */ debug?: boolean | DebugLevel | DebugLogger | { level?: DebugLevel; log?: DebugLogger; }; /** * Domain/IP validation-cache retention policy. * * In server runtimes, persistence defaults to the private Zynor temporary * directory for compatibility. Set `persistence: false` to prohibit all * cache filesystem access. Web runtimes always use their bounded isolate- * memory adapter. */ cache?: { /** Enable server-runtime disk persistence. @default true */ persistence?: boolean; /** Absolute directory containing the versioned cache namespaces. */ directory?: string; /** Maximum entries per internal cache namespace. */ maxEntries?: number; /** Maximum UTF-8 bytes per persisted cache file (minimum 1024). @default 67108864 */ maxFileBytes?: number; }; /** * @description This will enable deep validation of the email. slower than normal email validator as it triggers multiple dns requests, or travel to the ip address to get the domain name. * This is per request option, passing true to the getProvider without turning this ON, it wont work and vice versa. * @default false */ enableDeepValidation?: boolean; /** * @description This will enable the ipResolver for the email validator on deep validation. * @default undefined */ ipResolver?: { /** * @description Get your free api keys from https://findip.net to use find-api as a fallback for ipApi if enabled * @default undefined */ findip?: { enabled: boolean; apiKey: string[]; }; /** * @description This is 100% but might throagth that's why we have a fallback to findip.net * if you want to use this feature, change to true enable it * @default false */ ipApi?: boolean; /** * @description This is 100% but might throagth that's why we have a fallback to findip.net * if you want to use this feature, change to true enable it * @default false */ ipWhoIs?: boolean; }; deepValidationOptions?: { /** Max total time (ms) for the entire deep validation phase. @default 3000 */ maxTimeout?: number; http?: { timeout?: number; maxRetry?: number; }; }; } /** Per-call options shared by single-email validation. */ export type EmailValidationOptions = AbortOptions & { deep?: boolean; logo?: boolean; /** Include the normalized MX RRset on successful response data. */ includeMx?: boolean; }; /** Options for ordered bulk email validation. */ export type EmailBulkValidationOptions = EmailValidationOptions & { concurrency?: number; }; /** Options for streaming email validation. */ export type EmailEachOptions = EmailBulkValidationOptions & { perPage?: number; }; /** * Minimal domain-level cache entry. * Cheap fields (isFree, role, isDisposable) are recomputed on cache hit. */ export interface ValidateCacheEntry { provider?: string; status: 'valid' | 'Invalid' | 'Syntax' | 'Error' | 'Rejected' | 'Disposable'; message?: string; webmail?: string; /** Validation method — only set for Unknown/Others providers. */ method?: 'shallow' | 'deep'; } export declare class EmailValidator { private roles; private records; private yahooList; private domain; private static instance; protected dns: Zynor; private validateCache; private ipCache; private readonly mxLookupContexts; private inflight; private httpQueue; private _logFn; /** 0=silent, 1=info, 2=debug, 3=trace */ private _logLevel; private validationConfig; constructor(config?: { options?: ValidationConfig; dns?: Omit; }); protected positiveIntegerOption(name: string, value: number | undefined, fallback: number): number; protected validateTimeoutOption(timeout: number | undefined): void; private requestedMxRecords; /** * Return the domain only when validation will actually need an MX lookup. * Native page warming uses this to avoid spending FFI/DNS work on syntax, * policy, disposable, known-provider, and reusable cache-hit outcomes. */ protected mxLookupCandidate(email: string, deep: boolean, includeMx?: boolean): string | null; /** * Creates or returns an existing instance of the EmailValidator (Singleton pattern) * @param config - Configuration object for the EmailValidator * @param config.options - Optional validation configuration settings * @param config.options.enableDeepValidation - Enable deep validation with additional DNS lookups * @param config.options.ipResolver - Configure IP resolution settings * @param config.options.ipResolver.findip - Settings for findip.net API * @param config.options.ipResolver.ipApi - Enable/disable ipApi service * @param config.options.ipResolver.ipWhoIs - Enable/disable ipWhoIs service * @param config.dns - Optional DNS configuration settings * @returns The singleton instance of EmailValidator * @example * // Create with default settings * const validator = EmailValidator.create(); * * // Create with custom configuration * const validator = EmailValidator.create({ * options: { * enableDeepValidation: true, * ipResolver: { * findip: { * enabled: true, * apiKey: ['your-api-key'] * } * } * } * }); */ static create(config?: { options?: ValidationConfig; dns?: ZynorConfig; }): EmailValidator; private getMxRecords; /** * Validates an email address and determines its provider/service * @param email - The email address to validate and analyze * @returns Promise resolving to EmailResponse containing validation status and provider details * @throws Error if email validation fails * @example * const validator = EmailValidator.create(); * const result = await validator.validate("user@gmail.com"); */ validate(email: string): Promise; /** * Validates an email address with deep validation and determines its provider/service * @param email - The email address to validate and analyze * @param deep - Set to true to enable deep validation with additional DNS lookups * @returns Promise resolving to EmailResponse containing validation status and provider details * @throws Error if email validation fails * @remarks Deep validation performs additional DNS lookups and domain checks which may be slower * @example * const validator = EmailValidator.create(); * const result = await validator.getProvider("user@company.com", true); */ validate(email: string, deep: true): Promise; /** * Validates an email address with abort/timeout support and optional deep validation * @param email - The email address to validate and analyze * @param options - Options including signal, timeout, and optional deep flag * @param options.includeMx - Include normalized MX records in successful response data * @returns Promise resolving to EmailResponse containing validation status and provider details * @example * const validator = EmailValidator.create(); * const result = await validator.validate("user@company.com", { timeout: 5000 }); * const result2 = await validator.validate("user@company.com", { timeout: 5000, deep: true }); */ validate(email: string, options: EmailValidationOptions & { includeMx: true; }): Promise; validate(email: string, options: EmailValidationOptions): Promise; /** * Emit a log line if its level is at or below the configured threshold. * Format: `[zynor HH:MM:SS.mmm ] : `. Zero formatting * cost when level is filtered out. * * Use the typed wrappers (`_info`/`_debug`/`_trace`) — they make every * call site self-document its expected verbosity. */ private _emit; /** Top-level checkpoint (validate enter/exit, MX result, terminal outcome). */ private _info; /** Sub-operation (cache hit/miss, network call start/end, sub-loop boundary). */ private _debug; /** Fine-grained event (singleflight cleanup, per-iteration loop, early returns). */ private _trace; /** * Belt-and-suspenders timeout for DNS calls. Races the underlying * operation against a `setTimeout`-based watchdog so a hung c-ares * query (or a broken AbortSignal propagation) cannot pin the inflight * Map indefinitely. The leaked DNS promise continues running in the * background — c-ares eventually abandons it on its own — but the * wrapper rejects on time and the inflight key is always cleared. * * Logged at INFO so the watchdog firing is visible at default * `debug: true`; the `WATCHDOG fired` line tells you which domain is * misbehaving. */ private _withWatchdog; private isAbortOrTimeout; private throwIfCallerAborted; private normalizeAbortOptions; private parseHttpJson; private normalizeMxExchange; /** * Match an MX hostname only across complete DNS labels. Most historical * patterns are suffixes (with or without one leading dot). A pattern * wrapped in dots, such as `.yahoo.`, deliberately means that contiguous * label sequence anywhere in the hostname. Dot-only placeholder records * carry no labels and can never match. */ private matchesMxPattern; /** * Match one MX table row against an exchange. Rows tagged * `match: "exact"` require the whole hostname to equal the pattern * (label count equality on top of the end-anchored label match), so * `foo.mxa.mailgun.org` can never satisfy the `mxa.mailgun.org` * ingress row. All other rows keep the historical suffix/anywhere * semantics of {@link matchesMxPattern}. */ private matchesMxRecord; /** * Aggregate every validator-owned HTTP request behind one bounded queue. * Passing the caller signal to PQueue removes an aborted task while it is * still waiting; httpGet observes the same signal after it starts. */ private requestHttp; private normalizeProbeDomain; /** * Build a Valid response with `websiteTitle` and optional `loginUrl` * populated from the provider maps in ./provider-webmail. * * `webmail` (record-level override) and `loginUrl` (provider-level default) * coexist: both may be set, neither, or one. All optional fields use * conditional spread to satisfy `exactOptionalPropertyTypes`. */ private _buildValidResponse; private cloneMxRecords; /** * Reconstruct full EmailResponse from a cache entry + cheap recomputed fields. */ private _buildResponse; private validationErrorResponse; private _validateCore; /** * Validates multiple email addresses in parallel. * Concurrency is derived from enabled DNS provider limits unless explicitly provided. * Results are returned in the same order as the input array. * Each validation is independent — one failure does not abort others. * * @param emails - Array of email addresses to validate * @param options - Optional bulk validation options * @param options.concurrency - Max parallel validations (defaults to DNS totalConcurrency) * @param options.deep - Enable deep validation for all emails * @param options.logo - Fetch the provider logo for successful results * @param options.includeMx - Include normalized MX records in successful results * @param options.signal - AbortSignal to cancel the entire batch * @param options.timeout - Timeout in ms forwarded to each validation * @returns A promise resolving to an array of EmailResponse in the same order as input * * @example * ```typescript * const validator = EmailValidator.create(); * const results = await validator.validateBulk( * ['user@gmail.com', 'invalid@@', 'test@company.com'], * { deep: true } * ); * // results[0].success === true, results[1].success === false, ... * ``` */ validateBulk(emails: string[], options: EmailBulkValidationOptions & { includeMx: true; }): Promise; validateBulk(emails: string[], options?: EmailBulkValidationOptions): Promise; /** * Streams validation results as they complete, in completion order. * * Unlike {@link validateBulk}, which waits for every input before returning, * `each` invokes `onBatch` as soon as enough results have accumulated * (`perPage`, default 10) and continues until every input has been * processed. Designed for very large inputs (millions) where time-to-first * result matters and holding the entire result array in memory is wasteful. * * Validation workers and DNS providers enforce separate boundaries. Every * internal direct DNS lookup enters the selected provider's configured * concurrency and rate queue after load-aware provider selection. * * Backpressure: `onBatch` is awaited serially. If the callback is slow and * the in-memory buffer reaches `10 * perPage`, workers pause picking * new emails until the buffer drains below the cap. This keeps memory * bounded for truly large inputs. * * Errors: * - Per-email errors become error-shaped {@link EmailResponse} entries in * the stream — they never abort the batch. * - An error thrown by `onBatch` aborts production: workers stop picking * new emails, in-flight work is awaited, and the returned promise * rejects with the first such error. * * Abort: when the supplied `signal` fires, workers stop picking new * emails, in-flight validations finish, the buffer is flushed via * `onBatch`, and the returned promise resolves cleanly. * * @param emails - The list of email addresses to validate * @param options - Streaming options * @param options.concurrency - Max parallel validations (default 500) * @param options.perPage - Min results buffered before invoking onBatch (default 10) * @param options.deep - Enable deep validation per email * @param options.logo - Fetch provider logo per email * @param options.includeMx - Include normalized MX records per successful email * @param options.signal - AbortSignal to cancel the batch * @param options.timeout - Per-validation timeout in ms * @param onBatch - Invoked with each completed batch; may return a Promise * @returns Resolves once every input has been processed and flushed * * @example * ```typescript * await validator.each( * emails, // could be millions * { concurrency: 500, perPage: 50, deep: true }, * async (batch) => { * await db.insertMany(batch); * }, * ); * ``` */ each(emails: string[], options: EmailEachOptions & { includeMx: true; }, onBatch: (batch: EmailResponseWithMx[]) => void | Promise): Promise; each(emails: string[], options: EmailEachOptions | undefined, onBatch: (batch: EmailResponse[]) => void | Promise): Promise; private is_wale4r_zimbra; private is_zimbra; private is_webmail; private is_owa; private is_cPanel; private toToken; private parseJSCpanel; private is_Roundcube; private probeUrl; protected domain_check(email?: string, direct?: boolean, _pattern?: number, abortOptions?: AbortOptions): Promise<{ status: boolean; type: string; webmail?: string; }>; private resolveA; private getIpCache; private dnsLookup; private returnDNS; protected ipApi(ip: string, abortOptions?: AbortOptions): Promise<[string, string] | null>; protected ipWhoIs(ip: string, abortOptions?: AbortOptions): Promise<[string, string] | null>; protected findIp(ip: string, abortOptions?: AbortOptions): Promise<[string, string] | null>; /** * Checks if the given string is a valid email address according to advanced validation rules. * * This function performs a multi-step validation of an email address. It first checks the general format, * then splits the address into local and domain parts, and applies several constraints: * - Local part must be at least 2 characters, domain part at least 5 characters. * - Local part cannot exceed certain length and may not contain too many hyphens or dots. * - Domain part may not contain too many labels or hyphens. * - Validates extension via this.domain.isDomainExtension. * - Total email length cannot be excessive. * * Validation rules: * - Maximum 35 characters for the local part * - Maximum 3 hyphens in the local part * - Maximum 3 dots in the local part * - Maximum 3 labels in the domain part (i.e. at most 2 dots), so * `host.plus.com` is accepted while `mailbox.node.plus.com` is not * - Maximum 2 hyphens in the domain part * - Maximum 55 total characters in the email address * - Local part >= 2 chars; domain part >= 5 chars * * @param {string} email - The email address to validate. * @returns {boolean} True if the email passes all format and structural constraints, false otherwise. * * @example * validator.isEmail("john.doe@example.com"); // true * validator.isEmail("x@y.com"); // false (domain part < 5 chars) * validator.isEmail("toolong--name----more@long-domain-hyphen---.com"); // false */ isEmail(email: string): boolean; /** * Checks if the given email or domain name belongs to a free (public/free-to-register) email provider. * * - If an email address is provided, this method extracts the domain part. * - If a domain is provided directly, it is checked as-is. * - Returns `true` if the domain is recognized as a free provider (such as Gmail, Yahoo, Outlook, etc.), otherwise `false`. * * @param {string} email_or_domain - The email address (e.g. "user@gmail.com") or domain name (e.g. "gmail.com") to check. * @returns {boolean} `true` if the domain is a known free email provider, `false` otherwise. * * @example * validator.isFreeDomain('person@yahoo.com'); // returns true * validator.isFreeDomain('gmail.com'); // returns true * validator.isFreeDomain('user@private-company.org'); // returns false * validator.isFreeDomain('private-company.org'); // returns false */ isFreeDomain(email_or_domain: string): boolean; /** * Checks if the given email address is disposable. * * This method determines whether the provided email address is from a known disposable email provider. * Disposable email addresses are typically used for temporary or throwaway purposes, and are often associated * with domains that provide temporary inboxes. * * - Returns `true` if the email is found to be disposable using the internal provider list. * - Returns `false` for any non-disposable addresses, invalid addresses, or if the email is not recognized. * * @param {string} email - The email address to check for disposability (e.g., "user@mailinator.com"). * @returns {boolean} `true` if the email is disposable, otherwise `false`. * * @example * validator.isDisposable('test@mailinator.com'); // returns true * validator.isDisposable('john.doe@gmail.com'); // returns false * */ isDisposable(email: string): boolean; /** * Detects the mail server / webmail provider for a domain by probing common webmail URLs. * This is the deep validation `domain_check` logic exposed as a standalone public method. * * @param domain - The domain name to check (e.g. "example.com") * @param abortOptions - Optional signal/timeout to cancel the operation * @returns An object with `status`, `type` (provider name), and optional `webmail` URL * * @example * const result = await validator.detectMailProvider('company.com'); * // { status: true, type: 'Zimbra', webmail: 'https://mail.company.com' } * * @example * const result = await validator.detectMailProvider('unknown.io', { timeout: 2000 }); * // { status: false, type: '' } */ detectMailProvider(domain: string, abortOptions?: AbortOptions): Promise<{ status: boolean; type: string; webmail?: string; }>; /** * Detects the hosting provider for a domain by resolving its A records and looking up IP info. * Identifies providers like AWS, Microsoft, DigitalOcean, Oracle, IBM, Alibaba, and Aruba. * * Works independently of `enableDeepValidation`. Only requires `ipResolver` config: * - `ipResolver.ipApi: true` for ip-api.com lookups * - `ipResolver.findip: { enabled: true, apiKey: [...] }` for findip.net fallback * * @param domain - The domain name to check (e.g. "mail.example.com") * @param abortOptions - Optional signal/timeout to cancel the operation * @returns An object with `status` and `type` (hosting provider name) * * @example * const validator = EmailValidator.create({ * options: { ipResolver: { ipApi: true } } * }); * const result = await validator.detectHostingProvider('mail.company.com'); * // { status: true, type: 'AWS Partner' } */ detectHostingProvider(domain: string, abortOptions?: AbortOptions): Promise<{ status: boolean; type: string; webmail?: string; }>; private is_email; private isDomainOrUrl; /** * Checks if the input string is a valid JSON array of strings, where each string is a valid email address. * * - Attempts to parse the input string as JSON. * - Ensures the parsed value is an array of non-empty strings. * - Each element is also checked (using this.isEmail) to confirm it is a valid email address. * - If all conditions are met and the array has at least one valid email, returns the array. * - Otherwise, returns null. * * @param {string} input - The input string to validate. * @returns {string[] | null} The parsed array of valid email addresses if all conditions are met, otherwise null. * * @example * validator.isJson('["hello@site.com", "test@a.io"]'); // returns ["hello@site.com", "test@a.io"] * validator.isJson('["foo", 1, null]'); // returns null * validator.isJson('not json'); // returns null * validator.isJson('[]'); // returns null */ isJson(input: string): string[] | null; /** * Extracts and returns an array of valid email addresses from various input formats. * * This method processes input strings that may contain: * - Plain email addresses * - Comma-separated email addresses * - URL-encoded strings (automatically decoded) * - JSON arrays containing email addresses * * The function will: * 1. URL-decode each input string * 2. Split comma-separated values * 3. Validate each token as an email address * 4. Parse JSON arrays and extract valid emails from them * 5. Return a flat array of all valid email addresses found * * Note: Domain/URL detection is currently disabled (commented out in the implementation). * Only valid email addresses are included in the result. * * @param {string[]} input - An array of strings that may contain email addresses in various formats. * Each string can be: * - A single email address * - Comma-separated email addresses * - URL-encoded email addresses * - A JSON array string containing email addresses * - Any combination of the above * * @returns {string[]} An array of valid email addresses extracted from the input. * Duplicate emails may be present if they appear multiple times in the input. * Returns an empty array if no valid emails are found. * * @example * // Single email * validator.extractEmailsFromArray(["user@example.com"]); * // Returns: ["user@example.com"] * * @example * // Comma-separated emails * validator.extractEmailsFromArray(["user1@example.com,user2@example.com"]); * // Returns: ["user1@example.com", "user2@example.com"] * * @example * // URL-encoded and comma-separated * validator.extractEmailsFromArray(["user%40example.com,test%40domain.com"]); * // Returns: ["user@example.com", "test@domain.com"] * * @example * // JSON array of emails * validator.extractEmailsFromArray(['["email1@test.com", "email2@test.com"]']); * // Returns: ["email1@test.com", "email2@test.com"] * * @example * // Mixed formats * validator.extractEmailsFromArray([ * "user@example.com", * "test@domain.com,admin@site.com", * '["json@email.com"]' * ]); * // Returns: ["user@example.com", "test@domain.com", "admin@site.com", "json@email.com"] * * @example * // Invalid emails are filtered out * validator.extractEmailsFromArray(["valid@example.com", "invalid-email", "another@valid.com"]); * // Returns: ["valid@example.com", "another@valid.com"] */ extractEmailsFromArray(input: string[]): string[]; /** * Retrieves the webmail URL for a given email provider or domain/email address. * * This method returns the webmail login URL for known email providers (e.g., Gmail, Yahoo, Outlook). * It supports multiple calling patterns: * - By provider name only (returns the standard webmail URL for that provider) * - By provider name with domain/email (for providers that may have custom domains) * - By domain/email address directly (automatically detects if the string is a domain or email) * * The method first checks if the provider has a known webmail URL in the internal provider list. * If not found and a domain/email is provided, it attempts to resolve the webmail URL from the domain. * * Supported providers include major global providers (Gmail, Yahoo, Outlook, etc.), regional providers, * business/enterprise providers, and many others. See the provider list for complete coverage. * * @overload * @param {EmailProviderName} provider - The name of the email provider (e.g., "Gmail", "Yahoo", "Outlook"). * @returns {string | null} The webmail URL for the provider, or `null` if not found. * * @overload * @param {EmailProviderName} provider - The name of the email provider. * @param {string} domainOrEmail - A domain name (e.g., "example.com") or email address (e.g., "user@example.com"). * Used as a fallback if the provider name doesn't have a direct URL mapping. * @returns {string | null} The webmail URL for the provider/domain, or `null` if not found. * * @overload * @param {string} domainOrEmail - A domain name (e.g., "gmail.com") or email address (e.g., "user@gmail.com"). * The method automatically detects if this is a domain or email by checking for "@" or ".". * @returns {string | null} The webmail URL for the domain, or `null` if not found. * * @example * // Get webmail URL by provider name * validator.getProviderWebmailUrl("Gmail"); * // Returns: "https://mail.google.com" * * @example * // Get webmail URL by provider name with domain * validator.getProviderWebmailUrl("Yahoo", "yahoo.com"); * // Returns: "https://mail.yahoo.com" * * @example * // Get webmail URL by email address (auto-detects domain) * validator.getProviderWebmailUrl("user@gmail.com"); * // Returns: "https://mail.google.com" * * @example * // Get webmail URL by domain name * validator.getProviderWebmailUrl("outlook.com"); * // Returns: "https://outlook.live.com" * * @example * // Unknown provider returns null * validator.getProviderWebmailUrl("UnknownProvider"); * // Returns: null * * @example * // Provider with domain fallback * validator.getProviderWebmailUrl("CustomProvider", "customdomain.com"); * // May return a URL if the domain is recognized as a free provider */ getProviderWebmailUrl(provider: EmailProviderName): string | null; getProviderWebmailUrl(provider: EmailProviderName, domainOrEmail: string): string | null; getProviderWebmailUrl(domainOrEmail: string): string | null; /** * Extract and validate email addresses from mixed HTML or plain-text content. * * The method: * 1. Sanitizes the input by stripping HTML tags and removing non-essential punctuation. * 2. Applies a robust regular-expression pattern to locate candidate email strings. * 3. Validates each candidate against the full RFC-style rules implemented in {@link isEmail}. * 4. De-duplicates the final list while preserving the original order of first appearance. * * @param content - Arbitrary HTML or plain-text that may contain zero or more email addresses. * @returns An array of unique, syntactically valid email addresses discovered in the supplied content. * Returns an empty array when no valid emails are found. * * @example * // Plain text * validator.extractEmails('Contact us at support@example.com or sales@example.com'); * // → ['support@example.com', 'sales@example.com'] * * @example * // HTML fragment * validator.extractEmails('Info admin@site.org'); * // → ['info@site.org', 'admin@site.org'] * * @example * // Duplicates are removed * validator.extractEmails('user@demo.io, User@demo.io, USER@DEMO.IO'); * // → ['user@demo.io'] */ extractEmails(content: string): string[]; } type ValidData = { provider: EmailProviderName; isFree: boolean; email: string; role: boolean; websiteTitle: string; webmail?: string; loginUrl?: string; logo?: string; }; interface Valid { success: true; data: ValidData; } interface ValidWithMx { success: true; data: ValidData & { mx: MxRecord[]; }; } interface Invalid { success: false; type: 'Invalid'; email: string; role: boolean; } interface EmailDisposable { success: false; type: 'Disposable'; email: string; role: boolean; } interface Rejected { success: false; type: 'Rejected'; email: string; role: boolean; } interface Syntax { success: false; type: 'Syntax'; email: string; role: boolean; } interface EmailError { success: false; type: 'Error'; email: string; message: string; role: boolean; } export type EmailResponse = Valid | Invalid | Rejected | Syntax | EmailError | EmailDisposable; /** Validation response whose successful branch includes the requested MX RRset. */ export type EmailResponseWithMx = ValidWithMx | Invalid | Rejected | Syntax | EmailError | EmailDisposable; export {};