@emailcheck/email-validator-js 4.0.1 → 5.0.0-beta.2

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/README.md CHANGED
@@ -113,7 +113,8 @@ const result = await verifyEmail({
113
113
  emailAddress: 'user@mydomain.com',
114
114
  verifyMx: true,
115
115
  verifySmtp: true,
116
- timeout: 3000
116
+ smtpPerAttemptTimeoutMs: 3000, // bounds a single MX × port attempt
117
+ smtpTotalDeadlineMs: 8000, // bounds the entire SMTP probe (NEW in v5)
117
118
  });
118
119
 
119
120
  console.log(result.validFormat); // true
@@ -249,25 +250,31 @@ If you're using an IDE with refactoring support (like VS Code), you can use find
249
250
  Comprehensive email verification with detailed results and error codes.
250
251
 
251
252
  **Parameters:**
252
- - `emailAddress` (string, required): Email address to verify
253
- - `timeout` (number): Timeout in milliseconds (default: 4000)
254
- - `verifyMx` (boolean): Check MX records (default: true)
255
- - `verifySmtp` (boolean): Verify SMTP connection (default: false)
256
- - `smtpPort` (number): Custom SMTP port
257
- - `debug` (boolean): Enable debug logging (default: false)
258
- - `checkDisposable` (boolean): Check for disposable emails (default: true)
259
- - `checkFree` (boolean): Check for free email providers (default: true)
260
- - `retryAttempts` (number): Retry attempts for failures (default: 1)
261
- - `detectName` (boolean): Detect names from email address (default: false)
262
- - `nameDetectionMethod` (function): Custom name detection method
263
- - `suggestDomain` (boolean): Enable domain typo suggestions (default: true)
264
- - `domainSuggestionMethod` (function): Custom domain suggestion method
265
- - `commonDomains` (string[]): Custom list of domains for suggestions
266
- - `checkDomainAge` (boolean): Check domain age (default: false)
267
- - `checkDomainRegistration` (boolean): Check domain registration status (default: false)
268
- - `whoisTimeout` (number): WHOIS lookup timeout (default: 5000)
269
- - `debug` (boolean): Enable debug logging including WHOIS lookups (default: false)
270
- - `cache` (ICache): Optional custom cache instance
253
+ - `emailAddress` (string, required) Email address to verify.
254
+ - `verifyMx` (boolean) Resolve MX records (default: `true`).
255
+ - `verifySmtp` (boolean) Run live SMTP probe (default: `false`).
256
+ - `checkDisposable` (boolean) Disposable-provider list check (default: `true`).
257
+ - `checkFree` (boolean) Free-provider list check (default: `true`).
258
+ - `detectName` (boolean) Extract first/last name from local-part (default: `false`).
259
+ - `suggestDomain` (boolean) Suggest a corrected domain on typos (default: `true`).
260
+ - `checkDomainAge` (boolean) WHOIS creation-date lookup (default: `false`).
261
+ - `checkDomainRegistration` (boolean) WHOIS registration / expiry / lock lookup (default: `false`).
262
+ - `skipMxForDisposable` (boolean) Skip MX/SMTP for disposable addresses (default: `false`).
263
+ - `skipDomainWhoisForDisposable` (boolean) Skip WHOIS for disposable addresses (default: `false`).
264
+ - `smtpPort` (number) Force a specific port for the SMTP probe (overrides the `[25, 587, 465]` walk).
265
+ - **SMTP time-budget controls** (NEW in v5):
266
+ - `smtpPerAttemptTimeoutMs` (number) Per-MX × port budget in ms (default: `4000`).
267
+ - `smtpTotalDeadlineMs` (number) Hard cap on total wall-clock for the SMTP probe. Use this from a request handler with a tight latency budget. Default: unbounded.
268
+ - `smtpMaxConsecutiveFailures` (number) Bail after N connection-class failures in a row (`connection_error` / `connection_timeout` / `connection_closed`). Default: unbounded.
269
+ - `smtpMaxMxHosts` (number) Cap the MX walk to the first N hostnames. Default: unbounded.
270
+ - `smtpRetry` (`{ attempts, delayMs?, backoff? }`) Retry connection-class failures on the same MX × port. Default: no retries.
271
+ - `whoisTimeoutMs` (number) Per-WHOIS-query timeout (default: `5000`).
272
+ - `debug` (boolean) — Per-line `console.debug` trace (default: `false`).
273
+ - `captureTranscript` (boolean) — Populate `result.transcript` with a per-step structured trace (default: `false`).
274
+ - `nameDetectionMethod` (function) — Override the default name-detection heuristic.
275
+ - `domainSuggestionMethod` (function) — Override the default typo-suggestion heuristic.
276
+ - `commonDomains` (string[]) — Custom canonical-domain list for the typo suggester.
277
+ - `cache` (Cache) — Optional shared cache (MX, WHOIS, disposable / free, SMTP, domain results all stored).
271
278
 
272
279
  **Returns:**
273
280
  ```typescript
@@ -736,7 +743,7 @@ const result = await verifyEmail({
736
743
  emailAddress: 'foo@email.com',
737
744
  verifyMx: true,
738
745
  verifySmtp: true,
739
- timeout: 3000
746
+ smtpPerAttemptTimeoutMs: 3000,
740
747
  });
741
748
  console.log(result.validFormat); // true
742
749
  console.log(result.validMx); // true
@@ -790,16 +797,20 @@ const { smtpResult, port, cached, portCached } = await verifyMailboxSMTP({
790
797
  domain: 'example.com',
791
798
  mxRecords: ['mx.example.com'],
792
799
  options: {
793
- ports: [25, 587, 465], // Plain → STARTTLS-able → implicit-TLS
794
- timeout: 5000,
795
- cache: getDefaultCache(), // Per-isolate verdict + port cache
800
+ ports: [25, 587, 465], // Plain → STARTTLS-able → implicit-TLS
801
+ perAttemptTimeoutMs: 5000, // Per-MX × port budget (renamed from `timeout` in v5)
802
+ totalDeadlineMs: 12_000, // Hard cap on total wall-clock (NEW in v5)
803
+ maxConsecutiveFailures: 3, // Bail after N connection-class failures (NEW in v5)
804
+ cache: getDefaultCache(), // Per-isolate verdict + port cache
796
805
  debug: false,
797
- tls: {
806
+ tlsConfig: { // Renamed from `tls` in v5
798
807
  rejectUnauthorized: false,
799
808
  minVersion: 'TLSv1.2',
800
809
  },
801
- hostname: 'your-domain.com', // EHLO/HELO identity
802
- captureTranscript: false, // see "SMTP Transcript Capture" below
810
+ heloHostname: 'your-domain.com', // EHLO/HELO identity (renamed from `hostname` in v5)
811
+ startTls: 'auto', // STARTTLS upgrade on plaintext ports (NEW in v5)
812
+ pipelining: 'auto', // Use SMTP PIPELINING when advertised
813
+ captureTranscript: false, // See "SMTP Transcript Capture" below
803
814
  },
804
815
  });
805
816
 
@@ -807,6 +818,93 @@ console.log(`SMTP result: ${smtpResult.isDeliverable} via port ${port}`);
807
818
  console.log(`canConnectSmtp=${smtpResult.canConnectSmtp}, error=${smtpResult.error ?? 'none'}`);
808
819
  ```
809
820
 
821
+ ### Configuration presets (NEW in v5)
822
+
823
+ Don't want to think about timeouts and retries? Pick a preset that matches your deployment shape:
824
+
825
+ ```typescript
826
+ import { verifyEmail, VERIFY_EMAIL_PRESETS } from '@emailcheck/email-validator-js';
827
+
828
+ // Lambda / Vercel / Cloudflare-Workers handler
829
+ await verifyEmail({
830
+ emailAddress: 'alice@example.com',
831
+ verifySmtp: true,
832
+ ...VERIFY_EMAIL_PRESETS.serverless,
833
+ });
834
+
835
+ // Long-running worker / dyno
836
+ await verifyEmail({ ..., ...VERIFY_EMAIL_PRESETS.dedicated });
837
+
838
+ // Bulk processing
839
+ await verifyEmail({ ..., ...VERIFY_EMAIL_PRESETS.batch });
840
+
841
+ // Form-autocomplete UX (sub-3s)
842
+ await verifyEmail({ ..., ...VERIFY_EMAIL_PRESETS.fast });
843
+ ```
844
+
845
+ | Preset | Per-attempt | Total deadline | Max consecutive failures | Max MX | Retry |
846
+ | --- | --- | --- | --- | --- | --- |
847
+ | `serverless` | 2500 ms | **5 s** | 3 | 2 | none — fail fast |
848
+ | `dedicated` | 5000 ms | 30 s | unbounded | unbounded | 1 retry, 500 ms exp backoff |
849
+ | `batch` | 10 000 ms | 60 s | unbounded | unbounded | 2 retries, 1 s exp backoff |
850
+ | `fast` | 1500 ms | **3 s** | 2 | **1** | none — fail fast |
851
+
852
+ `SMTP_PRESETS` is a parallel set with the unprefixed field names for `verifyMailboxSMTP({ options })` callers — same values, same shape.
853
+
854
+ You can spread + override:
855
+
856
+ ```typescript
857
+ await verifyEmail({
858
+ emailAddress: 'alice@example.com',
859
+ ...VERIFY_EMAIL_PRESETS.serverless,
860
+ smtpTotalDeadlineMs: 3000, // tighter than the preset's 5s
861
+ });
862
+ ```
863
+
864
+ ### Time-budget controls (NEW in v5)
865
+
866
+ The probe walks `mxRecords × ports` (worst-case 4 × 3 = 12 attempts at 3s each = 36s). Four orthogonal knobs let you bound that:
867
+
868
+ ```typescript
869
+ import { verifyEmail, verifyMailboxSMTP } from '@emailcheck/email-validator-js';
870
+
871
+ await verifyEmail({
872
+ emailAddress: 'maria.hernandez+news@yahoo.com',
873
+ verifySmtp: true,
874
+ smtpPerAttemptTimeoutMs: 3000, // Bound a single MX × port attempt
875
+ smtpTotalDeadlineMs: 5000, // Hard cap on total wall-clock
876
+ smtpMaxConsecutiveFailures: 3, // Bail after 3 connection failures in a row
877
+ smtpMaxMxHosts: 2, // Try only the first 2 MXes
878
+ smtpRetry: { // Retry connection-class failures
879
+ attempts: 1,
880
+ delayMs: 200,
881
+ backoff: 'exponential', // or 'fixed'
882
+ },
883
+ });
884
+
885
+ // On verifyMailboxSMTP directly, the same knobs are unprefixed:
886
+ await verifyMailboxSMTP({
887
+ local: 'alice', domain: 'example.com', mxRecords: [...],
888
+ options: {
889
+ perAttemptTimeoutMs: 3000,
890
+ totalDeadlineMs: 5000,
891
+ maxConsecutiveFailures: 3,
892
+ maxMxHosts: 2,
893
+ retry: { attempts: 1, delayMs: 200, backoff: 'exponential' },
894
+ },
895
+ });
896
+ ```
897
+
898
+ | Knob | Default | When to use |
899
+ | --- | --- | --- |
900
+ | `(smtp)PerAttemptTimeoutMs` | `4000` (verifyEmail) / `3000` (verifyMailboxSMTP) | Per-MX × port budget. Bound a single attempt. |
901
+ | `(smtp)TotalDeadlineMs` | unbounded | Hard wall-clock cap. Use from a request handler with a tight latency budget. |
902
+ | `(smtp)MaxConsecutiveFailures` | unbounded | Cut off probes when the network path is dead. Counter resets on any non-connection-class outcome. |
903
+ | `(smtp)MaxMxHosts` | unbounded | Cap the MX walk regardless of how many DNS returned. |
904
+ | `(smtp)Retry` | no retries | Retry connection-class failures on the same MX × port. Definitive answers (250 / 550 / 552) are never retried. |
905
+
906
+ `PerAttemptTimeout` and `TotalDeadline` are **orthogonal** — use both when you have both a per-attempt SLO and a hard caller-side budget.
907
+
810
908
  ### Custom SMTP step sequence
811
909
 
812
910
  Override the default `greeting → EHLO → MAIL FROM → RCPT TO` walk for advanced cases:
@@ -839,11 +937,11 @@ const { smtpResult } = await verifyMailboxSMTP({
839
937
  local: 'user',
840
938
  domain: 'example.com',
841
939
  mxRecords: ['mx.example.com'],
842
- options: { ports: [25, 587], timeout: 5000, captureTranscript: true },
940
+ options: { ports: [25, 587], perAttemptTimeoutMs: 5000, captureTranscript: true },
843
941
  });
844
942
 
845
- // Both arrays aggregate across every port attempted, prefixed with the port:
846
- // "25|s| 220 mx.example.com ESMTP"
943
+ // Both arrays aggregate across every MX × port attempted, prefixed:
944
+ // "mx.example.com:25|s| 220 mx.example.com ESMTP"
847
945
  // "25|c| EHLO localhost"
848
946
  console.log(smtpResult.transcript);
849
947
  console.log(smtpResult.commands);
package/dist/cli/index.js CHANGED
@@ -1052,15 +1052,21 @@ async function verifyMailboxSMTP(params) {
1052
1052
  const { local, domain, options = {} } = params;
1053
1053
  const mxRecords = params.mxRecords ?? [];
1054
1054
  const ports = (options.ports ?? DEFAULT_PORTS).filter((port) => Number.isInteger(port) && port > 0 && port < 65536);
1055
- const timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
1056
- const tlsConfig = options.tls ?? true;
1057
- const hostname = options.hostname ?? "localhost";
1055
+ const perAttemptTimeoutMs = options.perAttemptTimeoutMs ?? DEFAULT_TIMEOUT_MS;
1056
+ const tlsConfig = options.tlsConfig ?? true;
1057
+ const heloHostname = options.heloHostname ?? "localhost";
1058
1058
  const debug = options.debug ?? false;
1059
1059
  const captureTranscript = options.captureTranscript ?? false;
1060
1060
  const sequence = options.sequence;
1061
1061
  const cache = options.cache;
1062
1062
  const log = debug ? (...args) => console.log("[SMTP]", ...args) : () => {
1063
1063
  };
1064
+ const totalDeadlineMs = options.totalDeadlineMs;
1065
+ const maxConsecutiveFailures = options.maxConsecutiveFailures;
1066
+ const maxMxHosts = options.maxMxHosts;
1067
+ const retryAttempts = options.retry?.attempts ?? 0;
1068
+ const retryDelayMs = options.retry?.delayMs ?? 200;
1069
+ const retryBackoff = options.retry?.backoff ?? "exponential";
1064
1070
  const startedAtMs = Date.now();
1065
1071
  const primaryMx = mxRecords[0];
1066
1072
  if (!primaryMx) {
@@ -1074,9 +1080,9 @@ async function verifyMailboxSMTP(params) {
1074
1080
  const probeOptions = {
1075
1081
  local,
1076
1082
  domain,
1077
- timeout,
1083
+ perAttemptTimeoutMs,
1078
1084
  tlsConfig,
1079
- hostname,
1085
+ heloHostname,
1080
1086
  sequence,
1081
1087
  log,
1082
1088
  catchAllProbeLocal: options.catchAllProbeLocal,
@@ -1097,17 +1103,41 @@ async function verifyMailboxSMTP(params) {
1097
1103
  const mxHostsTried = [];
1098
1104
  let mxAttempts = 0;
1099
1105
  let portAttempts = 0;
1106
+ let consecutiveFailures = 0;
1100
1107
  let lastReason = "all_attempts_failed";
1101
1108
  let lastEnhancedStatus;
1102
1109
  let lastResponseCode;
1103
- for (const mxHost of mxRecords) {
1110
+ let stoppedEarly = null;
1111
+ const isConnectionFailure = (reason) => reason === "connection_error" || reason === "connection_timeout" || reason === "connection_closed" || reason === "socket_timeout";
1112
+ const retryDelayFor = (attemptIndex) => retryBackoff === "exponential" ? retryDelayMs * 2 ** (attemptIndex - 1) : retryDelayMs;
1113
+ const probeWithRetry = async (mxHost, port) => {
1114
+ let lastProbe = await runProbe({ ...probeOptions, mxHost, port });
1115
+ for (let i = 1; i <= retryAttempts; i++) {
1116
+ if (lastProbe.result !== null || !isConnectionFailure(lastProbe.reason)) break;
1117
+ const delay = retryDelayFor(i);
1118
+ log(`retry ${i}/${retryAttempts} on ${mxHost}:${port} after ${delay}ms (last: ${lastProbe.reason})`);
1119
+ await new Promise((r) => setTimeout(r, delay));
1120
+ portAttempts++;
1121
+ lastProbe = await runProbe({ ...probeOptions, mxHost, port });
1122
+ }
1123
+ return lastProbe;
1124
+ };
1125
+ outer: for (const mxHost of mxRecords) {
1126
+ if (maxMxHosts !== void 0 && mxAttempts >= maxMxHosts) {
1127
+ stoppedEarly = "max_mx_hosts";
1128
+ break;
1129
+ }
1104
1130
  mxHostsTried.push(mxHost);
1105
1131
  mxAttempts++;
1106
1132
  const portsForThisMx = mxHost === primaryMx && cachedPort ? [cachedPort, ...ports.filter((p) => p !== cachedPort)] : ports;
1107
1133
  for (const port of portsForThisMx) {
1134
+ if (totalDeadlineMs !== void 0 && Date.now() - startedAtMs >= totalDeadlineMs) {
1135
+ stoppedEarly = "deadline";
1136
+ break outer;
1137
+ }
1108
1138
  portAttempts++;
1109
1139
  log(`Testing ${mxHost}:${port}`);
1110
- const probe = await runProbe({ ...probeOptions, mxHost, port });
1140
+ const probe = await probeWithRetry(mxHost, port);
1111
1141
  collectTranscript(transcript, commands, probe, mxHost, port);
1112
1142
  lastReason = probe.reason;
1113
1143
  if (probe.enhancedStatus !== void 0) lastEnhancedStatus = probe.enhancedStatus;
@@ -1123,8 +1153,14 @@ async function verifyMailboxSMTP(params) {
1123
1153
  if (mxHost === primaryMx) await safeCacheSet(portCache, primaryMx, port);
1124
1154
  return { smtpResult: smtpResult2, cached: false, port, portCached: cachedPort === port };
1125
1155
  }
1156
+ consecutiveFailures = isConnectionFailure(probe.reason) ? consecutiveFailures + 1 : 0;
1157
+ if (maxConsecutiveFailures !== void 0 && consecutiveFailures >= maxConsecutiveFailures) {
1158
+ stoppedEarly = "consecutive_failures";
1159
+ break outer;
1160
+ }
1126
1161
  }
1127
1162
  }
1163
+ if (stoppedEarly) log(`Stopped early: ${stoppedEarly}`);
1128
1164
  log(`All MX\xD7port attempts failed (mx=${mxAttempts}, port=${portAttempts})`);
1129
1165
  const metrics = makeMetrics(mxHostsTried, mxAttempts, portAttempts, void 0, startedAtMs);
1130
1166
  const smtpResult = {
@@ -1275,16 +1311,16 @@ class SMTPProbeConnection {
1275
1311
  } else {
1276
1312
  this.socket = net__namespace.connect({ host: this.p.mxHost, port: this.p.port }, onConnect);
1277
1313
  }
1278
- this.socket.setTimeout(this.p.timeout, () => this.finish(null, "socket_timeout"));
1314
+ this.socket.setTimeout(this.p.perAttemptTimeoutMs, () => this.finish(null, "socket_timeout"));
1279
1315
  this.socket.on("error", () => this.finish(null, "connection_error"));
1280
1316
  this.socket.on("close", () => this.finish(null, "connection_closed"));
1281
1317
  }
1282
1318
  armConnectionTimer() {
1283
- this.connectionTimer = setTimeout(() => this.finish(null, "connection_timeout"), this.p.timeout);
1319
+ this.connectionTimer = setTimeout(() => this.finish(null, "connection_timeout"), this.p.perAttemptTimeoutMs);
1284
1320
  }
1285
1321
  resetStepTimer() {
1286
1322
  if (this.stepTimer) clearTimeout(this.stepTimer);
1287
- this.stepTimer = setTimeout(() => this.finish(null, "step_timeout"), this.p.timeout);
1323
+ this.stepTimer = setTimeout(() => this.finish(null, "step_timeout"), this.p.perAttemptTimeoutMs);
1288
1324
  }
1289
1325
  send(cmd) {
1290
1326
  if (this.resolved) return;
@@ -1309,10 +1345,10 @@ class SMTPProbeConnection {
1309
1345
  return;
1310
1346
  // server-driven; nothing to send
1311
1347
  case SMTPStep.ehlo:
1312
- this.send(`EHLO ${this.p.hostname}`);
1348
+ this.send(`EHLO ${this.p.heloHostname}`);
1313
1349
  return;
1314
1350
  case SMTPStep.helo:
1315
- this.send(`HELO ${this.p.hostname}`);
1351
+ this.send(`HELO ${this.p.heloHostname}`);
1316
1352
  return;
1317
1353
  case SMTPStep.startTls:
1318
1354
  this.executeStartTls();
@@ -1384,7 +1420,7 @@ class SMTPProbeConnection {
1384
1420
  this.supportsStartTls = false;
1385
1421
  this.supportsPipelining = false;
1386
1422
  this.postUpgradeReEhlo = true;
1387
- this.send(`EHLO ${this.p.hostname}`);
1423
+ this.send(`EHLO ${this.p.heloHostname}`);
1388
1424
  });
1389
1425
  this.socket = tlsSocket;
1390
1426
  this.socket.on("data", this.onData);
@@ -1392,7 +1428,7 @@ class SMTPProbeConnection {
1392
1428
  this.finish(null, this.tlsUpgrading ? "tls_handshake_failed" : "connection_error");
1393
1429
  });
1394
1430
  this.socket.on("close", () => this.finish(null, "connection_closed"));
1395
- this.socket.setTimeout(this.p.timeout, () => this.finish(null, "socket_timeout"));
1431
+ this.socket.setTimeout(this.p.perAttemptTimeoutMs, () => this.finish(null, "socket_timeout"));
1396
1432
  }
1397
1433
  /**
1398
1434
  * Send the dual-probe envelope (real RCPT + probe RCPT + RSET). Pipelined
@@ -2328,13 +2364,13 @@ async function runWhoisChecks(domain, params, result, skipWhois, log, collector)
2328
2364
  log(`[verifyEmail] WHOIS checks skipped for disposable: ${domain}`);
2329
2365
  return;
2330
2366
  }
2331
- const whoisTimeout = params.whoisTimeout ?? 5e3;
2367
+ const whoisTimeoutMs = params.whoisTimeoutMs ?? 5e3;
2332
2368
  const debug = params.debug ?? false;
2333
2369
  if (params.checkDomainAge) {
2334
2370
  try {
2335
2371
  result.domainAge = await collector.record(
2336
2372
  "whois-age",
2337
- () => getDomainAge(domain, whoisTimeout, debug, params.cache),
2373
+ () => getDomainAge(domain, whoisTimeoutMs, debug, params.cache),
2338
2374
  (info) => ({
2339
2375
  domain,
2340
2376
  found: info !== null,
@@ -2354,7 +2390,7 @@ async function runWhoisChecks(domain, params, result, skipWhois, log, collector)
2354
2390
  try {
2355
2391
  result.domainRegistration = await collector.record(
2356
2392
  "whois-registration",
2357
- () => getDomainRegistrationStatus(domain, whoisTimeout, debug, params.cache),
2393
+ () => getDomainRegistrationStatus(domain, whoisTimeoutMs, debug, params.cache),
2358
2394
  (info) => ({
2359
2395
  domain,
2360
2396
  found: info !== null,
@@ -2427,7 +2463,11 @@ async function runSmtp(local, domain, mxRecords, params, result, log, collector)
2427
2463
  options: {
2428
2464
  cache: params.cache,
2429
2465
  ports: resolveSmtpPorts(params.smtpPort, mxRecords[0]),
2430
- timeout: params.timeout ?? 4e3,
2466
+ perAttemptTimeoutMs: params.smtpPerAttemptTimeoutMs ?? 4e3,
2467
+ totalDeadlineMs: params.smtpTotalDeadlineMs,
2468
+ maxConsecutiveFailures: params.smtpMaxConsecutiveFailures,
2469
+ maxMxHosts: params.smtpMaxMxHosts,
2470
+ retry: params.smtpRetry,
2431
2471
  debug: params.debug ?? false,
2432
2472
  // Forward transcript capture so the SMTP step's details include
2433
2473
  // the full per-port transcript when the caller asked for it.
@@ -2613,7 +2653,7 @@ async function run(args, deps = {}) {
2613
2653
  emailAddress: args.email,
2614
2654
  verifyMx: args.verifyMx,
2615
2655
  verifySmtp: args.verifySmtp,
2616
- timeout: args.timeoutMs ?? 5e3,
2656
+ smtpPerAttemptTimeoutMs: args.timeoutMs ?? 5e3,
2617
2657
  debug: args.debug,
2618
2658
  smtpPort: args.smtpPort,
2619
2659
  checkDisposable: args.checkDisposable,
@@ -2622,7 +2662,7 @@ async function run(args, deps = {}) {
2622
2662
  suggestDomain: args.suggestDomain,
2623
2663
  checkDomainAge: args.checkDomainAge,
2624
2664
  checkDomainRegistration: args.checkDomainRegistration,
2625
- whoisTimeout: args.whoisTimeoutMs ?? 5e3,
2665
+ whoisTimeoutMs: args.whoisTimeoutMs ?? 5e3,
2626
2666
  captureTranscript: args.captureTranscript
2627
2667
  });
2628
2668
  if (args.quiet) {