@mikkelscheike/email-provider-links 5.0.0 → 5.1.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/dist/api.js CHANGED
@@ -6,15 +6,14 @@
6
6
  * Clean function names and enhanced error context.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.Config = void 0;
9
+ exports.Config = exports.emailsMatch = exports.normalizeEmail = void 0;
10
10
  exports.getEmailProvider = getEmailProvider;
11
11
  exports.getEmailProviderSync = getEmailProviderSync;
12
- exports.normalizeEmail = normalizeEmail;
13
- exports.emailsMatch = emailsMatch;
14
12
  exports.getEmailProviderFast = getEmailProviderFast;
15
13
  const concurrent_dns_1 = require("./concurrent-dns");
16
14
  const provider_loader_1 = require("./provider-loader");
17
15
  const idn_1 = require("./idn");
16
+ const alias_detection_1 = require("./alias-detection");
18
17
  let cachedProvidersRef = null;
19
18
  let cachedDomainMap = null;
20
19
  function getDomainMapFromProviders(providers) {
@@ -82,6 +81,18 @@ function validateAndParseEmailForLookup(email) {
82
81
  const domain = (0, idn_1.domainToPunycode)(domainRaw);
83
82
  return { ok: true, trimmedEmail, domain };
84
83
  }
84
+ /**
85
+ * Convert a full EmailProvider to a simplified version
86
+ */
87
+ function simplifyProvider(provider) {
88
+ if (!provider)
89
+ return null;
90
+ return {
91
+ companyProvider: provider.companyProvider,
92
+ loginUrl: provider.loginUrl,
93
+ type: provider.type
94
+ };
95
+ }
85
96
  /**
86
97
  * Get email provider information for any email address.
87
98
  *
@@ -90,16 +101,22 @@ function validateAndParseEmailForLookup(email) {
90
101
  * - Business domains (mycompany.com using Google Workspace, etc.)
91
102
  * - Unknown providers (graceful fallback)
92
103
  *
104
+ * By default, returns a simplified response with only essential fields.
105
+ * Use the `extended` option to get full provider details including domains and alias configuration.
106
+ *
93
107
  * @param email - The email address to analyze
94
- * @param timeout - Optional timeout for DNS queries in milliseconds (default: 5000ms)
95
- * @returns Promise resolving to EmailProviderResult with provider info and error context
108
+ * @param options - Optional configuration: timeout for DNS queries (default: 5000ms) and extended response flag
109
+ * @returns Promise resolving to SimplifiedEmailProviderResult (default) or EmailProviderResult (if extended)
96
110
  *
97
111
  * @example
98
112
  * ```typescript
99
- * // Consumer email
100
- * const result = await getEmailProvider('local@domain.tld');
101
- * console.log(result.provider?.companyProvider); // Provider name
102
- * console.log(result.loginUrl); // Login URL
113
+ * // Default: Simplified response (recommended for frontend)
114
+ * const result = await getEmailProvider('user@gmail.com');
115
+ * // Returns: { provider: { companyProvider, loginUrl, type }, email, loginUrl, detectionMethod }
116
+ *
117
+ * // Extended response (includes domains, alias config, etc.)
118
+ * const extended = await getEmailProvider('user@gmail.com', { extended: true });
119
+ * // Returns: { provider: { companyProvider, loginUrl, domains, alias, type, ... }, ... }
103
120
  *
104
121
  * // Business domain
105
122
  * const business = await getEmailProvider('local@business.tld');
@@ -112,21 +129,34 @@ function validateAndParseEmailForLookup(email) {
112
129
  * console.log(invalid.error?.message); // "Invalid email format"
113
130
  * ```
114
131
  */
115
- async function getEmailProvider(email, timeout) {
132
+ async function getEmailProvider(email, options) {
133
+ // Parse options - support both legacy (number) and new (object) format
134
+ const timeout = typeof options === 'number' ? options : options?.timeout;
135
+ const extended = typeof options === 'object' && options?.extended === true;
116
136
  try {
117
137
  const parsed = validateAndParseEmailForLookup(email);
118
138
  if (!parsed.ok) {
119
- return {
139
+ // Try to normalize even invalid emails (may help with some edge cases)
140
+ let normalizedEmail = parsed.email;
141
+ try {
142
+ normalizedEmail = (0, alias_detection_1.normalizeEmail)(parsed.email);
143
+ }
144
+ catch {
145
+ // If normalization fails, use original email
146
+ }
147
+ const errorResult = {
120
148
  provider: null,
121
- email: parsed.email,
122
- loginUrl: null,
149
+ email: normalizedEmail,
150
+ ...(extended ? { loginUrl: null } : {}),
123
151
  error: parsed.error
124
152
  };
153
+ return extended ? errorResult : errorResult;
125
154
  }
126
155
  const domain = parsed.domain;
127
156
  // First try synchronous domain matching
128
- const syncResult = getEmailProviderSync(email);
157
+ const syncResult = getEmailProviderSync(email, { extended });
129
158
  if (syncResult.provider) {
159
+ // Email is already normalized in getEmailProviderSync
130
160
  return {
131
161
  ...syncResult,
132
162
  detectionMethod: 'domain_match'
@@ -135,15 +165,16 @@ async function getEmailProvider(email, timeout) {
135
165
  // Fall back to DNS detection for business domains
136
166
  const loadResult = (0, provider_loader_1.loadProviders)();
137
167
  if (!loadResult.success) {
138
- return {
168
+ const errorResult = {
139
169
  provider: null,
140
170
  email,
141
- loginUrl: null,
171
+ ...(extended ? { loginUrl: null } : {}),
142
172
  error: {
143
173
  type: 'NETWORK_ERROR',
144
174
  message: 'Service temporarily unavailable'
145
175
  }
146
176
  };
177
+ return extended ? errorResult : errorResult;
147
178
  }
148
179
  const providers = loadResult.providers;
149
180
  const concurrentResult = await (0, concurrent_dns_1.detectProviderConcurrent)(domain, providers, {
@@ -151,17 +182,42 @@ async function getEmailProvider(email, timeout) {
151
182
  enableParallel: true,
152
183
  collectDebugInfo: false
153
184
  });
185
+ // Normalize email using alias detection (even if no provider found)
186
+ // This ensures consistent email format regardless of provider detection result
187
+ let normalizedEmail = email;
188
+ try {
189
+ normalizedEmail = (0, alias_detection_1.normalizeEmail)(email);
190
+ }
191
+ catch {
192
+ // If normalization fails, use original email
193
+ }
194
+ if (extended) {
195
+ const result = {
196
+ provider: concurrentResult.provider,
197
+ email: normalizedEmail,
198
+ loginUrl: concurrentResult.provider?.loginUrl || null,
199
+ detectionMethod: concurrentResult.detectionMethod || 'mx_record'
200
+ };
201
+ if (concurrentResult.proxyService) {
202
+ result.proxyService = concurrentResult.proxyService;
203
+ }
204
+ // Add error context for null results
205
+ if (!result.provider && !result.proxyService) {
206
+ result.error = {
207
+ type: 'UNKNOWN_DOMAIN',
208
+ message: `No email provider found for domain: ${domain}`
209
+ };
210
+ }
211
+ return result;
212
+ }
213
+ // Default: simplified response
154
214
  const result = {
155
- provider: concurrentResult.provider,
156
- email,
157
- loginUrl: concurrentResult.provider?.loginUrl || null,
215
+ provider: simplifyProvider(concurrentResult.provider),
216
+ email: normalizedEmail,
158
217
  detectionMethod: concurrentResult.detectionMethod || 'mx_record'
159
218
  };
160
- if (concurrentResult.proxyService) {
161
- result.proxyService = concurrentResult.proxyService;
162
- }
163
219
  // Add error context for null results
164
- if (!result.provider && !result.proxyService) {
220
+ if (!result.provider) {
165
221
  result.error = {
166
222
  type: 'UNKNOWN_DOMAIN',
167
223
  message: `No email provider found for domain: ${domain}`
@@ -171,40 +227,36 @@ async function getEmailProvider(email, timeout) {
171
227
  }
172
228
  catch (error) {
173
229
  // Enhanced error handling
230
+ const errorResult = {
231
+ provider: null,
232
+ email,
233
+ error: {}
234
+ };
235
+ if (extended) {
236
+ errorResult.loginUrl = null;
237
+ }
174
238
  if (error instanceof Error && error.message.includes('Rate limit exceeded')) {
175
239
  const retryMatch = error.message.match(/Try again in (\d+) seconds/);
176
240
  const retryAfter = retryMatch?.[1] ? parseInt(retryMatch[1], 10) : undefined;
177
- return {
178
- provider: null,
179
- email,
180
- loginUrl: null,
181
- error: {
182
- type: 'RATE_LIMITED',
183
- message: 'DNS query rate limit exceeded',
184
- ...(retryAfter !== undefined ? { retryAfter } : {})
185
- }
241
+ errorResult.error = {
242
+ type: 'RATE_LIMITED',
243
+ message: 'DNS query rate limit exceeded',
244
+ ...(retryAfter !== undefined ? { retryAfter } : {})
186
245
  };
246
+ return extended ? errorResult : errorResult;
187
247
  }
188
248
  if (error instanceof Error && error.message.includes('timeout')) {
189
- return {
190
- provider: null,
191
- email,
192
- loginUrl: null,
193
- error: {
194
- type: 'DNS_TIMEOUT',
195
- message: `DNS lookup timed out after ${timeout || 5000}ms`
196
- }
249
+ errorResult.error = {
250
+ type: 'DNS_TIMEOUT',
251
+ message: `DNS lookup timed out after ${timeout || 5000}ms`
197
252
  };
253
+ return extended ? errorResult : errorResult;
198
254
  }
199
- return {
200
- provider: null,
201
- email,
202
- loginUrl: null,
203
- error: {
204
- type: 'NETWORK_ERROR',
205
- message: error instanceof Error ? error.message : 'Unknown network error'
206
- }
255
+ errorResult.error = {
256
+ type: 'NETWORK_ERROR',
257
+ message: error instanceof Error ? error.message : 'Unknown network error'
207
258
  };
259
+ return extended ? errorResult : errorResult;
208
260
  }
209
261
  }
210
262
  /**
@@ -213,14 +265,22 @@ async function getEmailProvider(email, timeout) {
213
265
  * This function only checks predefined domains and returns immediately.
214
266
  * Use this when you can't use async functions or don't want DNS lookups.
215
267
  *
268
+ * By default, returns a simplified response with only essential fields.
269
+ * Use the `extended` option to get full provider details including domains and alias configuration.
270
+ *
216
271
  * @param email - The email address to analyze
217
- * @returns EmailProviderResult with provider info (limited to known domains)
272
+ * @param options - Optional configuration: extended response flag
273
+ * @returns SimplifiedEmailProviderResult (default) or EmailProviderResult (if extended) with provider info (limited to known domains)
218
274
  *
219
275
  * @example
220
276
  * ```typescript
221
- * // Works for known domains
277
+ * // Default: Simplified response (recommended for frontend)
222
278
  * const gmail = getEmailProviderSync('user@gmail.com');
223
- * console.log(gmail.provider?.companyProvider); // "Gmail"
279
+ * // Returns: { provider: { companyProvider, loginUrl, type }, email, loginUrl }
280
+ *
281
+ * // Extended response (includes domains, alias config, etc.)
282
+ * const extended = getEmailProviderSync('user@gmail.com', { extended: true });
283
+ * // Returns: { provider: { companyProvider, loginUrl, domains, alias, type, ... }, ... }
224
284
  *
225
285
  * // Unknown domains return null
226
286
  * const unknown = getEmailProviderSync('user@mycompany.com');
@@ -228,16 +288,28 @@ async function getEmailProvider(email, timeout) {
228
288
  * console.log(unknown.error?.type); // "UNKNOWN_DOMAIN"
229
289
  * ```
230
290
  */
231
- function getEmailProviderSync(email) {
291
+ function getEmailProviderSync(email, options) {
292
+ const extended = options?.extended === true;
232
293
  try {
233
294
  const parsed = validateAndParseEmailForLookup(email);
234
295
  if (!parsed.ok) {
235
- return {
296
+ // Try to normalize even invalid emails (may help with some edge cases)
297
+ let normalizedEmail = parsed.email;
298
+ try {
299
+ normalizedEmail = (0, alias_detection_1.normalizeEmail)(parsed.email);
300
+ }
301
+ catch {
302
+ // If normalization fails, use original email
303
+ }
304
+ const errorResult = {
236
305
  provider: null,
237
- email: parsed.email,
238
- loginUrl: null,
306
+ email: normalizedEmail,
239
307
  error: parsed.error
240
308
  };
309
+ if (extended) {
310
+ errorResult.loginUrl = null;
311
+ }
312
+ return extended ? errorResult : errorResult;
241
313
  }
242
314
  const domain = parsed.domain;
243
315
  // Load providers with verification
@@ -249,15 +321,18 @@ function getEmailProviderSync(email) {
249
321
  if (process.env.NODE_ENV !== 'test' && !process.env.JEST_WORKER_ID) {
250
322
  console.error('🚨 Provider lookup blocked due to validation failure');
251
323
  }
252
- return {
324
+ const errorResult = {
253
325
  provider: null,
254
326
  email,
255
- loginUrl: null,
256
327
  error: {
257
328
  type: 'NETWORK_ERROR',
258
329
  message: 'Service temporarily unavailable'
259
330
  }
260
331
  };
332
+ if (extended) {
333
+ errorResult.loginUrl = null;
334
+ }
335
+ return extended ? errorResult : errorResult;
261
336
  }
262
337
  const domainMap = getDomainMapFromProviders(result.providers);
263
338
  provider = domainMap.get(domain) || null;
@@ -266,20 +341,48 @@ function getEmailProviderSync(email) {
266
341
  if (process.env.NODE_ENV !== 'test' && !process.env.JEST_WORKER_ID) {
267
342
  console.error('🚨 Provider lookup failed:', error);
268
343
  }
269
- return {
344
+ const errorResult = {
270
345
  provider: null,
271
346
  email,
272
- loginUrl: null,
273
347
  error: {
274
348
  type: 'NETWORK_ERROR',
275
349
  message: 'Service temporarily unavailable'
276
350
  }
277
351
  };
352
+ if (extended) {
353
+ errorResult.loginUrl = null;
354
+ }
355
+ return extended ? errorResult : errorResult;
278
356
  }
357
+ // Normalize email using alias detection (even if no provider found)
358
+ // This ensures consistent email format regardless of provider detection result
359
+ let normalizedEmail = email;
360
+ try {
361
+ normalizedEmail = (0, alias_detection_1.normalizeEmail)(email);
362
+ }
363
+ catch {
364
+ // If normalization fails, use original email
365
+ }
366
+ if (extended) {
367
+ const result = {
368
+ provider: provider || null,
369
+ email: normalizedEmail,
370
+ loginUrl: provider?.loginUrl || null,
371
+ detectionMethod: 'domain_match'
372
+ };
373
+ // Add error context for null results
374
+ if (!result.provider) {
375
+ result.error = {
376
+ type: 'UNKNOWN_DOMAIN',
377
+ message: `No email provider found for domain: ${domain} (sync mode - business domains not supported)`
378
+ };
379
+ }
380
+ return result;
381
+ }
382
+ // Default: simplified response
279
383
  const result = {
280
- provider: provider || null,
281
- email,
282
- loginUrl: provider?.loginUrl || null,
384
+ provider: simplifyProvider(provider),
385
+ email: normalizedEmail,
283
386
  detectionMethod: 'domain_match'
284
387
  };
285
388
  // Add error context for null results
@@ -292,129 +395,56 @@ function getEmailProviderSync(email) {
292
395
  return result;
293
396
  }
294
397
  catch (error) {
295
- return {
398
+ const errorResult = {
296
399
  provider: null,
297
400
  email,
298
- loginUrl: null,
299
401
  error: {
300
402
  type: 'INVALID_EMAIL',
301
403
  message: error instanceof Error ? error.message : 'Invalid email address'
302
404
  }
303
405
  };
304
- }
305
- }
306
- /**
307
- * Normalize an email address to its canonical form.
308
- *
309
- * This handles provider-specific aliasing rules:
310
- * - Gmail: removes dots and plus addressing
311
- * - Other providers: removes plus addressing only
312
- *
313
- * @param email - The email address to normalize
314
- * @returns The canonical email address
315
- *
316
- * @example
317
- * ```typescript
318
- * const canonical = normalizeEmail('L.O.C.A.L+work@DOMAIN.TLD');
319
- * console.log(canonical); // 'local@domain.tld'
320
- *
321
- * const provider = normalizeEmail('local+newsletter@provider.tld');
322
- * console.log(provider); // 'local@provider.tld'
323
- * ```
324
- */
325
- function normalizeEmail(email) {
326
- if (!email || typeof email !== 'string') {
327
- return email;
328
- }
329
- // Convert to lowercase
330
- const lowercaseEmail = email.toLowerCase().trim();
331
- // Split email into local and domain parts
332
- const atIndex = lowercaseEmail.lastIndexOf('@');
333
- if (atIndex === -1) {
334
- return lowercaseEmail;
335
- }
336
- let localPart = lowercaseEmail.slice(0, atIndex);
337
- const domainPart = (0, idn_1.domainToPunycode)(lowercaseEmail.slice(atIndex + 1));
338
- // Use providers for domain lookup
339
- let provider = null;
340
- try {
341
- const result = (0, provider_loader_1.loadProviders)();
342
- if (!result.success) {
343
- return lowercaseEmail; // Return as-is if providers can't be loaded
406
+ if (extended) {
407
+ errorResult.loginUrl = null;
344
408
  }
345
- const domainMap = getDomainMapFromProviders(result.providers);
346
- provider = domainMap.get(domainPart) || null;
347
- }
348
- catch (error) {
349
- return lowercaseEmail; // Return as-is if error occurs
409
+ return extended ? errorResult : errorResult;
350
410
  }
351
- if (provider?.alias) {
352
- // Provider supports aliasing
353
- if (provider.alias.dots) {
354
- // Remove all dots from local part (e.g. Gmail)
355
- localPart = localPart.replace(/\./g, '');
356
- }
357
- if (provider.alias.plus) {
358
- // Remove plus addressing (everything after +)
359
- const plusIndex = localPart.indexOf('+');
360
- if (plusIndex !== -1) {
361
- localPart = localPart.slice(0, plusIndex);
362
- }
363
- }
364
- }
365
- return `${localPart}@${domainPart}`;
366
- }
367
- /**
368
- * Check if two email addresses are the same person (accounting for aliases).
369
- *
370
- * This normalizes both emails and compares their canonical forms.
371
- * Useful for preventing duplicate accounts and matching login attempts.
372
- *
373
- * @param email1 - First email address
374
- * @param email2 - Second email address
375
- * @returns true if the emails represent the same person
376
- *
377
- * @example
378
- * ```typescript
379
- * const match = emailsMatch('local@domain.tld', 'l.o.c.a.l+work@domain.tld');
380
- * console.log(match); // true
381
- *
382
- * const different = emailsMatch('local@domain.tld', 'other@domain.tld');
383
- * console.log(different); // false
384
- * ```
385
- */
386
- function emailsMatch(email1, email2) {
387
- if (!email1 || !email2 || typeof email1 !== 'string' || typeof email2 !== 'string') {
388
- return false;
389
- }
390
- // Normalize both emails and compare
391
- const normalized1 = normalizeEmail(email1);
392
- const normalized2 = normalizeEmail(email2);
393
- return normalized1 === normalized2;
394
411
  }
412
+ // Re-export alias detection functions from the dedicated module
413
+ var alias_detection_2 = require("./alias-detection");
414
+ Object.defineProperty(exports, "normalizeEmail", { enumerable: true, get: function () { return alias_detection_2.normalizeEmail; } });
415
+ Object.defineProperty(exports, "emailsMatch", { enumerable: true, get: function () { return alias_detection_2.emailsMatch; } });
395
416
  /**
396
417
  * Enhanced email provider detection with concurrent DNS for maximum performance.
397
418
  * This function uses parallel MX/TXT lookups for 2x faster business domain detection.
398
419
  *
420
+ * By default, returns a simplified response with only essential fields.
421
+ * Use the `extended` option to get full provider details including domains and alias configuration.
422
+ *
399
423
  * @param email - The email address to analyze
400
424
  * @param options - Configuration options for DNS detection
401
- * @returns Promise resolving to EmailProviderResult with enhanced performance data
425
+ * @returns Promise resolving to SimplifiedEmailProviderResult (default) or EmailProviderResult (if extended) with enhanced performance data
402
426
  *
403
427
  * @example
404
428
  * ```typescript
405
- * // High-performance detection with concurrent DNS
429
+ * // Default: Simplified response with performance data
406
430
  * const result = await getEmailProviderFast('user@mycompany.com', {
407
431
  * enableParallel: true,
408
432
  * collectDebugInfo: true
409
433
  * });
434
+ * // Returns: { provider: { companyProvider, loginUrl, type }, email, loginUrl, detectionMethod, timing, confidence }
410
435
  *
411
- * console.log(result.provider?.companyProvider); // "Google Workspace"
412
- * console.log(result.detectionMethod); // "mx_record"
413
- * console.log(result.timing); // { mx: 120, txt: 95, total: 125 }
436
+ * // Extended response (includes domains, alias config, etc.)
437
+ * const extended = await getEmailProviderFast('user@mycompany.com', {
438
+ * enableParallel: true,
439
+ * extended: true
440
+ * });
441
+ * console.log(extended.provider?.companyProvider); // "Google Workspace"
442
+ * console.log(extended.detectionMethod); // "mx_record"
443
+ * console.log(extended.timing); // { mx: 120, txt: 95, total: 125 }
414
444
  * ```
415
445
  */
416
446
  async function getEmailProviderFast(email, options = {}) {
417
- const { timeout = 5000, enableParallel = true, collectDebugInfo = false } = options;
447
+ const { timeout = 5000, enableParallel = true, collectDebugInfo = false, extended = false } = options;
418
448
  try {
419
449
  const parsed = validateAndParseEmailForLookup(email);
420
450
  if (!parsed.ok) {
@@ -428,8 +458,9 @@ async function getEmailProviderFast(email, options = {}) {
428
458
  const domain = parsed.domain;
429
459
  const trimmedEmail = parsed.trimmedEmail;
430
460
  // First try standard domain matching (fast path)
431
- const syncResult = getEmailProviderSync(trimmedEmail);
461
+ const syncResult = getEmailProviderSync(trimmedEmail, { extended });
432
462
  if (syncResult.provider) {
463
+ // Email is already normalized in getEmailProviderSync
433
464
  return {
434
465
  ...syncResult,
435
466
  detectionMethod: 'domain_match',
@@ -456,34 +487,62 @@ async function getEmailProviderFast(email, options = {}) {
456
487
  enableParallel,
457
488
  collectDebugInfo
458
489
  });
490
+ // Normalize email using alias detection (even if no provider found)
491
+ // This ensures consistent email format regardless of provider detection result
492
+ let normalizedEmail = trimmedEmail;
493
+ try {
494
+ normalizedEmail = (0, alias_detection_1.normalizeEmail)(trimmedEmail);
495
+ }
496
+ catch {
497
+ // If normalization fails, use original email
498
+ }
499
+ if (extended) {
500
+ const fastResult = {
501
+ provider: concurrentResult.provider,
502
+ email: normalizedEmail,
503
+ loginUrl: concurrentResult.provider?.loginUrl || null,
504
+ detectionMethod: concurrentResult.detectionMethod || 'mx_record',
505
+ timing: concurrentResult.timing,
506
+ confidence: concurrentResult.confidence,
507
+ debug: concurrentResult.debug,
508
+ error: !concurrentResult.provider && !concurrentResult.proxyService ? {
509
+ type: 'UNKNOWN_DOMAIN',
510
+ message: `No email provider found for domain: ${domain}`
511
+ } : undefined
512
+ };
513
+ if (concurrentResult.proxyService) {
514
+ fastResult.proxyService = concurrentResult.proxyService;
515
+ }
516
+ return fastResult;
517
+ }
518
+ // Default: simplified response
459
519
  const fastResult = {
460
- provider: concurrentResult.provider,
461
- email: trimmedEmail,
462
- loginUrl: concurrentResult.provider?.loginUrl || null,
520
+ provider: simplifyProvider(concurrentResult.provider),
521
+ email: normalizedEmail,
463
522
  detectionMethod: concurrentResult.detectionMethod || 'mx_record',
464
523
  timing: concurrentResult.timing,
465
524
  confidence: concurrentResult.confidence,
466
525
  debug: concurrentResult.debug,
467
- error: !concurrentResult.provider && !concurrentResult.proxyService ? {
526
+ error: !concurrentResult.provider ? {
468
527
  type: 'UNKNOWN_DOMAIN',
469
528
  message: `No email provider found for domain: ${domain}`
470
529
  } : undefined
471
530
  };
472
- if (concurrentResult.proxyService) {
473
- fastResult.proxyService = concurrentResult.proxyService;
474
- }
475
531
  return fastResult;
476
532
  }
477
533
  catch (error) {
478
- return {
534
+ const errorResult = {
479
535
  provider: null,
480
536
  email,
481
- loginUrl: null,
482
537
  error: {
483
538
  type: 'NETWORK_ERROR',
484
539
  message: error instanceof Error ? error.message : 'DNS detection failed'
485
540
  }
486
541
  };
542
+ if (extended) {
543
+ errorResult.loginUrl = null;
544
+ }
545
+ return errorResult;
487
546
  }
488
547
  }
489
548
  /**
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Email validation constants based on RFC 5321
3
+ *
4
+ * These limits are defined in RFC 5321 Section 4.5.3.1:
5
+ * - Maximum total email length: 254 characters
6
+ * - Maximum local part length: 64 characters
7
+ * - Maximum domain length: 253 characters
8
+ */
9
+ export declare const EmailLimits: {
10
+ /** Maximum total email address length (local + @ + domain) */
11
+ readonly MAX_EMAIL_LENGTH: 254;
12
+ /** Maximum local part length (before @) */
13
+ readonly MAX_LOCAL_PART_LENGTH: 64;
14
+ /** Maximum domain length (after @) */
15
+ readonly MAX_DOMAIN_LENGTH: 253;
16
+ };
17
+ /**
18
+ * Memory calculation constants
19
+ */
20
+ export declare const MemoryConstants: {
21
+ /** Bytes per kilobyte */
22
+ readonly BYTES_PER_KB: 1024;
23
+ /** Kilobytes per megabyte */
24
+ readonly KB_PER_MB: 1024;
25
+ };
26
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryConstants = exports.EmailLimits = void 0;
4
+ /**
5
+ * Email validation constants based on RFC 5321
6
+ *
7
+ * These limits are defined in RFC 5321 Section 4.5.3.1:
8
+ * - Maximum total email length: 254 characters
9
+ * - Maximum local part length: 64 characters
10
+ * - Maximum domain length: 253 characters
11
+ */
12
+ exports.EmailLimits = {
13
+ /** Maximum total email address length (local + @ + domain) */
14
+ MAX_EMAIL_LENGTH: 254,
15
+ /** Maximum local part length (before @) */
16
+ MAX_LOCAL_PART_LENGTH: 64,
17
+ /** Maximum domain length (after @) */
18
+ MAX_DOMAIN_LENGTH: 253,
19
+ };
20
+ /**
21
+ * Memory calculation constants
22
+ */
23
+ exports.MemoryConstants = {
24
+ /** Bytes per kilobyte */
25
+ BYTES_PER_KB: 1024,
26
+ /** Kilobytes per megabyte */
27
+ KB_PER_MB: 1024,
28
+ };
29
+ //# sourceMappingURL=constants.js.map