@mikkelscheike/email-provider-links 2.6.1 → 2.7.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
@@ -30,13 +30,13 @@ const loader_1 = require("./loader");
30
30
  * ```typescript
31
31
  * // Consumer email
32
32
  * const gmail = await getEmailProvider('user@gmail.com');
33
- * console.log(gmail.provider?.name); // "Gmail"
34
- * console.log(gmail.loginUrl); // "https://mail.google.com/mail/"
33
+ * console.log(gmail.provider?.companyProvider); // "Gmail"
34
+ * console.log(gmail.loginUrl); // "https://mail.google.com/mail/"
35
35
  *
36
36
  * // Business domain
37
37
  * const business = await getEmailProvider('user@mycompany.com');
38
- * console.log(business.provider?.name); // "Google Workspace" (if detected)
39
- * console.log(business.detectionMethod); // "mx_record"
38
+ * console.log(business.provider?.companyProvider); // "Google Workspace" (if detected)
39
+ * console.log(business.detectionMethod); // "mx_record"
40
40
  *
41
41
  * // Error handling
42
42
  * const invalid = await getEmailProvider('invalid-email');
@@ -102,9 +102,11 @@ async function getEmailProvider(email, timeout) {
102
102
  provider: concurrentResult.provider,
103
103
  email,
104
104
  loginUrl: concurrentResult.provider?.loginUrl || null,
105
- detectionMethod: concurrentResult.detectionMethod || undefined,
106
- proxyService: concurrentResult.proxyService
105
+ detectionMethod: concurrentResult.detectionMethod || 'mx_record'
107
106
  };
107
+ if (concurrentResult.proxyService) {
108
+ result.proxyService = concurrentResult.proxyService;
109
+ }
108
110
  // Add error context for null results
109
111
  if (!result.provider && !result.proxyService) {
110
112
  result.error = {
@@ -118,7 +120,7 @@ async function getEmailProvider(email, timeout) {
118
120
  // Enhanced error handling
119
121
  if (error.message?.includes('Rate limit exceeded')) {
120
122
  const retryMatch = error.message.match(/Try again in (\d+) seconds/);
121
- const retryAfter = retryMatch ? parseInt(retryMatch[1]) : undefined;
123
+ const retryAfter = retryMatch ? parseInt(retryMatch[1], 10) : undefined;
122
124
  return {
123
125
  provider: null,
124
126
  email,
@@ -126,7 +128,7 @@ async function getEmailProvider(email, timeout) {
126
128
  error: {
127
129
  type: 'RATE_LIMITED',
128
130
  message: 'DNS query rate limit exceeded',
129
- retryAfter
131
+ ...(retryAfter !== undefined ? { retryAfter } : {})
130
132
  }
131
133
  };
132
134
  }
@@ -165,7 +167,7 @@ async function getEmailProvider(email, timeout) {
165
167
  * ```typescript
166
168
  * // Works for known domains
167
169
  * const gmail = getEmailProviderSync('user@gmail.com');
168
- * console.log(gmail.provider?.name); // "Gmail"
170
+ * console.log(gmail.provider?.companyProvider); // "Gmail"
169
171
  *
170
172
  * // Unknown domains return null
171
173
  * const unknown = getEmailProviderSync('user@mycompany.com');
@@ -322,7 +324,6 @@ function emailsMatch(email1, email2) {
322
324
  const normalized2 = normalizeEmail(email2);
323
325
  return normalized1 === normalized2;
324
326
  }
325
- // Note: EmailProvider type is defined above
326
327
  /**
327
328
  * Enhanced email provider detection with concurrent DNS for maximum performance.
328
329
  * This function uses parallel MX/TXT lookups for 2x faster business domain detection.
@@ -401,12 +402,11 @@ async function getEmailProviderFast(email, options = {}) {
401
402
  enableParallel,
402
403
  collectDebugInfo
403
404
  });
404
- return {
405
+ const fastResult = {
405
406
  provider: concurrentResult.provider,
406
407
  email,
407
408
  loginUrl: concurrentResult.provider?.loginUrl || null,
408
- detectionMethod: concurrentResult.detectionMethod || undefined,
409
- proxyService: concurrentResult.proxyService,
409
+ detectionMethod: concurrentResult.detectionMethod || 'mx_record',
410
410
  timing: concurrentResult.timing,
411
411
  confidence: concurrentResult.confidence,
412
412
  debug: concurrentResult.debug,
@@ -415,6 +415,10 @@ async function getEmailProviderFast(email, options = {}) {
415
415
  message: `No email provider found for domain: ${domain}`
416
416
  } : undefined
417
417
  };
418
+ if (concurrentResult.proxyService) {
419
+ fastResult.proxyService = concurrentResult.proxyService;
420
+ }
421
+ return fastResult;
418
422
  }
419
423
  catch (error) {
420
424
  return {
@@ -437,3 +441,4 @@ exports.Config = {
437
441
  SUPPORTED_PROVIDERS_COUNT: 93,
438
442
  SUPPORTED_DOMAINS_COUNT: 180
439
443
  };
444
+ //# sourceMappingURL=api.js.map
@@ -62,7 +62,7 @@ export interface ConcurrentDNSResult {
62
62
  conflicts: boolean;
63
63
  queries: DNSQueryResult[];
64
64
  fallbackUsed: boolean;
65
- };
65
+ } | undefined;
66
66
  }
67
67
  /**
68
68
  * Concurrent DNS Detection Engine
@@ -130,3 +130,4 @@ export declare function createConcurrentDNSDetector(providers: EmailProvider[],
130
130
  * Utility function for quick concurrent DNS detection
131
131
  */
132
132
  export declare function detectProviderConcurrent(domain: string, providers: EmailProvider[], config?: Partial<ConcurrentDNSConfig>): Promise<ConcurrentDNSResult>;
133
+ //# sourceMappingURL=concurrent-dns.d.ts.map
@@ -28,6 +28,8 @@ const DEFAULT_CONFIG = {
28
28
  * Concurrent DNS Detection Engine
29
29
  */
30
30
  class ConcurrentDNSDetector {
31
+ // Store active query states
32
+ activeQueries = new Set();
31
33
  // Cleanup method for tests
32
34
  cleanup() {
33
35
  // Cancel any in-progress timeouts
@@ -38,9 +40,9 @@ class ConcurrentDNSDetector {
38
40
  this.activeQueries.clear();
39
41
  return Promise.resolve();
40
42
  }
43
+ config;
44
+ providers;
41
45
  constructor(providers, config = {}) {
42
- // Store active query states
43
- this.activeQueries = new Set();
44
46
  this.config = { ...DEFAULT_CONFIG, ...config };
45
47
  this.providers = providers.filter(p => p.customDomainDetection &&
46
48
  (p.customDomainDetection.mxPatterns || p.customDomainDetection.txtPatterns));
@@ -154,13 +156,20 @@ class ConcurrentDNSDetector {
154
156
  // and potentially ignore TXT timing for performance reporting
155
157
  const mxResult = mappedResults[0];
156
158
  const txtResult = mappedResults[1];
157
- if (mxResult.success && this.hasMXMatch(mxResult) && this.config.prioritizeMX) {
159
+ if (mxResult && mxResult.success && this.hasMXMatch(mxResult) && this.config.prioritizeMX) {
158
160
  // Create an optimized TXT result that indicates it wasn't needed
159
161
  const optimizedTxtResult = {
160
- ...txtResult,
161
- timing: 0, // Don't count TXT time if MX was sufficient
162
- optimized: true
162
+ type: 'txt',
163
+ success: txtResult?.success || false,
164
+ records: txtResult?.records || [],
165
+ timing: 0 // Don't count TXT time if MX was sufficient
163
166
  };
167
+ if (txtResult?.error) {
168
+ optimizedTxtResult.error = txtResult.error;
169
+ }
170
+ if (txtResult?.rawResponse) {
171
+ optimizedTxtResult.rawResponse = txtResult.rawResponse;
172
+ }
164
173
  return [mxResult, optimizedTxtResult];
165
174
  }
166
175
  return mappedResults;
@@ -323,9 +332,9 @@ class ConcurrentDNSDetector {
323
332
  if (matches.length === 0)
324
333
  return null;
325
334
  if (matches.length === 1)
326
- return matches[0];
335
+ return matches[0] ?? null;
327
336
  // Sort by confidence and preference for MX records
328
- return matches.sort((a, b) => {
337
+ const sortedMatches = matches.sort((a, b) => {
329
338
  // Prioritize MX records if configured
330
339
  if (this.config.prioritizeMX) {
331
340
  if (a.method === 'mx_record' && b.method !== 'mx_record')
@@ -335,7 +344,8 @@ class ConcurrentDNSDetector {
335
344
  }
336
345
  // Then by confidence
337
346
  return b.confidence - a.confidence;
338
- })[0];
347
+ });
348
+ return sortedMatches.length > 0 ? (sortedMatches[0] ?? null) : null;
339
349
  }
340
350
  /**
341
351
  * Check if MX result has potential matches (for sequential optimization)
@@ -428,3 +438,4 @@ async function detectProviderConcurrent(domain, providers, config) {
428
438
  const detector = createConcurrentDNSDetector(providers, config);
429
439
  return detector.detectProvider(domain);
430
440
  }
441
+ //# sourceMappingURL=concurrent-dns.js.map
@@ -91,3 +91,4 @@ export declare function createProviderManifest(providers: any[]): {
91
91
  urlHashes: Record<string, string>;
92
92
  manifestHash: string;
93
93
  };
94
+ //# sourceMappingURL=hash-verifier.d.ts.map
@@ -29,7 +29,7 @@ const KNOWN_GOOD_HASHES = {
29
29
  // SHA-256 hash of the legitimate emailproviders.json
30
30
  'emailproviders.json': 'f77814bf0537019c6f38bf2744ae21640f04a2d39cb67c5116f6e03160c9486f',
31
31
  // You can add hashes for other critical files
32
- 'package.json': '1057de7ce3b03211001dcc6e4533de5f5e64760a287418f994682ba2684cf53b'
32
+ 'package.json': '67927e7e27636b55dc1fee5e34f16bbbf721a33103b0bc94c3c42923e2325cef'
33
33
  };
34
34
  /**
35
35
  * Calculates SHA-256 hash of a file or string content
@@ -281,3 +281,4 @@ function createProviderManifest(providers) {
281
281
  manifestHash
282
282
  };
283
283
  }
284
+ //# sourceMappingURL=hash-verifier.js.map
package/dist/idn.d.ts CHANGED
@@ -44,3 +44,4 @@ export declare function validateInternationalEmail(email: string): {
44
44
  code: IDNValidationError;
45
45
  message: string;
46
46
  } | undefined;
47
+ //# sourceMappingURL=idn.d.ts.map
package/dist/idn.js CHANGED
@@ -246,3 +246,4 @@ function validateInternationalEmail(email) {
246
246
  // If we get here, the email is valid
247
247
  return undefined;
248
248
  }
249
+ //# sourceMappingURL=idn.js.map
package/dist/index.d.ts CHANGED
@@ -1,59 +1,202 @@
1
1
  /**
2
2
  * Email Provider Links
3
3
  *
4
- * A clean, modern email provider detection library with:
4
+ * A modern, robust email provider detection library with:
5
5
  * - 93+ verified email providers covering 180+ domains
6
6
  * - Concurrent DNS detection for business domains
7
7
  * - Zero runtime dependencies
8
- * - Comprehensive error handling
9
- * - Email alias normalization
8
+ * - Comprehensive error handling with detailed context
9
+ * - International email validation (IDN support)
10
+ * - Email alias normalization and deduplication
11
+ * - Enterprise-grade security features
10
12
  *
11
13
  * @author Email Provider Links Team
12
14
  * @license MIT
15
+ * @version 2.7.0
13
16
  */
14
17
  export { getEmailProvider, getEmailProviderSync, getEmailProviderFast, normalizeEmail, emailsMatch, Config } from './api';
15
18
  export type { EmailProvider, EmailProviderResult } from './api';
16
19
  export { loadProviders } from './loader';
17
20
  export { detectProviderConcurrent } from './concurrent-dns';
21
+ export { validateInternationalEmail, emailToPunycode, domainToPunycode } from './idn';
18
22
  export type { ConcurrentDNSConfig, ConcurrentDNSResult } from './concurrent-dns';
23
+ /**
24
+ * Enhanced email validation with comprehensive error reporting
25
+ *
26
+ * @param email - Email address to validate
27
+ * @returns Validation result with detailed error information
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const result = validateEmailAddress('user@example.com');
32
+ * if (result.isValid) {
33
+ * console.log('Email is valid');
34
+ * } else {
35
+ * console.log('Error:', result.error.message);
36
+ * }
37
+ * ```
38
+ */
39
+ export declare function validateEmailAddress(email: string): {
40
+ isValid: boolean;
41
+ normalizedEmail?: string;
42
+ error?: {
43
+ type: string;
44
+ code: string;
45
+ message: string;
46
+ };
47
+ };
48
+ import { loadProviders } from './loader';
19
49
  import { getEmailProvider, getEmailProviderSync, getEmailProviderFast, normalizeEmail, emailsMatch } from './api';
50
+ import { detectProviderConcurrent } from './concurrent-dns';
51
+ import { validateInternationalEmail } from './idn';
20
52
  /**
21
- * Get list of all supported email providers
22
- * @returns Array of all email providers in the database
53
+ * Get comprehensive list of all supported email providers
54
+ *
55
+ * @returns Array of all email providers with metadata
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * const providers = getSupportedProviders();
60
+ * console.log(`Supports ${providers.length} providers`);
61
+ *
62
+ * const gmailProvider = providers.find(p => p.domains.includes('gmail.com'));
63
+ * console.log(gmailProvider?.companyProvider); // "Gmail"
64
+ * ```
23
65
  */
24
66
  export declare function getSupportedProviders(): import("./api").EmailProvider[];
25
67
  /**
26
- * Check if an email provider is supported
68
+ * Check if an email provider is supported (synchronous)
69
+ *
27
70
  * @param email - Email address to check
28
71
  * @returns true if the provider is supported
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * if (isEmailProviderSupported('user@gmail.com')) {
76
+ * console.log('Gmail is supported');
77
+ * }
78
+ * ```
29
79
  */
30
80
  export declare function isEmailProviderSupported(email: string): boolean;
31
81
  /**
32
- * Extract domain from email address
82
+ * Extract and normalize domain from email address
83
+ *
33
84
  * @param email - Email address
34
- * @returns Domain portion or null if invalid
85
+ * @returns Normalized domain portion or null if invalid
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const domain = extractDomain('USER@GMAIL.COM');
90
+ * console.log(domain); // "gmail.com"
91
+ *
92
+ * const invalid = extractDomain('invalid-email');
93
+ * console.log(invalid); // null
94
+ * ```
35
95
  */
36
96
  export declare function extractDomain(email: string): string | null;
37
97
  /**
38
- * Validate email format
98
+ * Validate email format using enhanced rules
99
+ *
39
100
  * @param email - Email address to validate
40
101
  * @returns true if valid format
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * if (isValidEmail('user@example.com')) {
106
+ * console.log('Email format is valid');
107
+ * }
108
+ *
109
+ * if (isValidEmail('user@münchen.de')) {
110
+ * console.log('International domain is valid');
111
+ * }
112
+ * ```
41
113
  */
42
114
  export declare function isValidEmail(email: string): boolean;
43
115
  /**
44
- * Library metadata
116
+ * Get library metadata and statistics
117
+ *
118
+ * @returns Object with current library statistics
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * const stats = getLibraryStats();
123
+ * console.log(`Supports ${stats.providerCount} providers across ${stats.domainCount} domains`);
124
+ * ```
125
+ */
126
+ export declare function getLibraryStats(): {
127
+ providerCount: number;
128
+ domainCount: number;
129
+ version: string;
130
+ supportsAsync: boolean;
131
+ supportsIDN: boolean;
132
+ supportsAliasDetection: boolean;
133
+ supportsConcurrentDNS: boolean;
134
+ };
135
+ /**
136
+ * Batch process multiple email addresses efficiently
137
+ *
138
+ * @param emails - Array of email addresses to process
139
+ * @param options - Processing options
140
+ * @returns Array of results in the same order as input
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const emails = ['user@gmail.com', 'test@yahoo.com', 'invalid-email'];
145
+ * const results = batchProcessEmails(emails);
146
+ *
147
+ * results.forEach((result, index) => {
148
+ * console.log(`${emails[index]}: ${result.isValid ? 'Valid' : 'Invalid'}`);
149
+ * });
150
+ * ```
151
+ */
152
+ export declare function batchProcessEmails(emails: string[], options?: {
153
+ includeProviderInfo?: boolean;
154
+ normalizeEmails?: boolean;
155
+ deduplicateAliases?: boolean;
156
+ }): Array<{
157
+ email: string;
158
+ isValid: boolean;
159
+ provider?: string | null;
160
+ loginUrl?: string | null;
161
+ normalized?: string;
162
+ isDuplicate?: boolean;
163
+ error?: string;
164
+ }>;
165
+ /**
166
+ * @deprecated Use validateEmailAddress instead for better error handling
167
+ */
168
+ export declare const isValidEmailAddress: typeof isValidEmail;
169
+ /**
170
+ * Library metadata (legacy constants)
45
171
  */
46
172
  export declare const PROVIDER_COUNT = 93;
47
173
  export declare const DOMAIN_COUNT = 178;
48
174
  /**
49
175
  * Default export for convenience
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * import EmailProviderLinks from '@mikkelscheike/email-provider-links';
180
+ *
181
+ * const result = await EmailProviderLinks.getEmailProvider('user@gmail.com');
182
+ * ```
50
183
  */
51
184
  declare const _default: {
52
185
  getEmailProvider: typeof getEmailProvider;
53
186
  getEmailProviderSync: typeof getEmailProviderSync;
54
187
  getEmailProviderFast: typeof getEmailProviderFast;
188
+ validateEmailAddress: typeof validateEmailAddress;
189
+ isValidEmail: typeof isValidEmail;
55
190
  normalizeEmail: typeof normalizeEmail;
56
191
  emailsMatch: typeof emailsMatch;
192
+ getSupportedProviders: typeof getSupportedProviders;
193
+ isEmailProviderSupported: typeof isEmailProviderSupported;
194
+ extractDomain: typeof extractDomain;
195
+ getLibraryStats: typeof getLibraryStats;
196
+ batchProcessEmails: typeof batchProcessEmails;
197
+ loadProviders: typeof loadProviders;
198
+ detectProviderConcurrent: typeof detectProviderConcurrent;
199
+ validateInternationalEmail: typeof validateInternationalEmail;
57
200
  Config: {
58
201
  readonly DEFAULT_DNS_TIMEOUT: 5000;
59
202
  readonly MAX_DNS_REQUESTS_PER_MINUTE: 10;
@@ -64,3 +207,8 @@ declare const _default: {
64
207
  DOMAIN_COUNT: number;
65
208
  };
66
209
  export default _default;
210
+ /**
211
+ * Version information
212
+ */
213
+ export declare const VERSION = "2.7.0";
214
+ //# sourceMappingURL=index.d.ts.map