@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/README.md CHANGED
@@ -1,16 +1,26 @@
1
1
  # Email Provider Links
2
2
 
3
- πŸ”’ **Modern email provider detection library with concurrent DNS resolution and enterprise security**
3
+ πŸ”’ **Modern email provider detection library with enhanced TypeScript support and enterprise security**
4
4
 
5
- A TypeScript library providing direct links to **93 email providers** (178 domains) with **concurrent DNS resolution**, **optimized performance**, **email alias detection**, and comprehensive security features for login and password reset flows.
5
+ A robust TypeScript library providing direct links to **93 email providers** (178 domains) with **concurrent DNS resolution**, **optimized performance**, **comprehensive email validation**, and advanced security features for login and password reset flows.
6
6
 
7
- ## ✨ Features
7
+ ## ✨ New in Version 2.7.0
8
+
9
+ - πŸš€ **Modern TypeScript**: Updated to latest TypeScript 2025 standards with strict type checking
10
+ - 🌍 **Enhanced International Support**: Improved IDN validation and Punycode handling
11
+ - πŸ“§ **Advanced Email Validation**: Comprehensive validation with detailed error reporting
12
+ - πŸ”„ **Batch Processing**: Efficiently process multiple emails with deduplication
13
+ - πŸ›‘οΈ **Improved Security**: Enhanced cryptographic integrity verification
14
+ - ⚑ **Better Performance**: Optimized concurrent DNS with smart caching
15
+ - 🎯 **Developer Experience**: Enhanced error messages and debugging information
16
+
17
+ ## ✨ Core Features
8
18
 
9
19
  - πŸš€ **Fast & Lightweight**: Zero dependencies, ultra-low memory (~0.39MB initial, ~0.02MB per 1000 ops)
10
20
  - πŸ“§ **93 Email Providers**: Gmail, Outlook, Yahoo, ProtonMail, iCloud, and many more
11
21
  - 🌐 **178 Domains Supported**: Comprehensive international coverage
12
- - 🌍 **IDN Support**: Full internationalized domain name (punycode) support with RFC compliance
13
- - βœ… **Email Validation**: International email validation following RFC 5321, 5322, and 6530 standards
22
+ - 🌍 **Full IDN Support**: International domain names with RFC compliance and Punycode
23
+ - βœ… **Advanced Email Validation**: International email validation with detailed error reporting
14
24
  - 🏒 **Business Domain Detection**: DNS-based detection for custom domains (Google Workspace, Microsoft 365, etc.)
15
25
  - πŸ”’ **Enterprise Security**: Multi-layer protection against malicious URLs and supply chain attacks
16
26
  - πŸ›‘οΈ **URL Validation**: HTTPS-only enforcement with domain allowlisting
@@ -20,7 +30,8 @@ A TypeScript library providing direct links to **93 email providers** (178 domai
20
30
  - 🚦 **Rate Limiting**: Built-in DNS query rate limiting to prevent abuse
21
31
  - πŸ”„ **Email Alias Detection**: Normalize Gmail dots, plus addressing, and provider-specific aliases
22
32
  - πŸ›‘οΈ **Fraud Prevention**: Detect duplicate accounts through email alias manipulation
23
- - πŸ§ͺ **Thoroughly Tested**: 370 tests with 92.89% code coverage
33
+ - πŸ“¦ **Batch Processing**: Efficiently process multiple emails with deduplication
34
+ - πŸ§ͺ **Thoroughly Tested**: 396 tests with comprehensive code coverage
24
35
 
25
36
  ## Installation
26
37
 
@@ -32,7 +43,7 @@ npm install @mikkelscheike/email-provider-links
32
43
  ## Requirements
33
44
 
34
45
  - **Node.js**: `>=18.0.0` (Tested on 18.x, 20.x, 22.x, **24.x**)
35
- - **TypeScript**: `>=4.0.0` (optional)
46
+ - **TypeScript**: `>=4.0.0` (optional, but recommended)
36
47
  - **Zero runtime dependencies** - No external packages required
37
48
 
38
49
  ### Node.js 24 Support ✨
@@ -64,6 +75,59 @@ const unknown = await getEmailProvider('user@unknown.com');
64
75
  console.log(unknown.loginUrl); // null
65
76
  ```
66
77
 
78
+ ## Enhanced Email Validation
79
+
80
+ **New in 2.7.0**: Comprehensive email validation with international support:
81
+
82
+ ```typescript
83
+ import { validateEmailAddress, validateInternationalEmail } from '@mikkelscheike/email-provider-links';
84
+
85
+ // Enhanced validation with detailed error reporting
86
+ const result = validateEmailAddress('user@example.com');
87
+ if (result.isValid) {
88
+ console.log('Valid email:', result.normalizedEmail);
89
+ } else {
90
+ console.log('Error:', result.error?.message);
91
+ console.log('Error code:', result.error?.code);
92
+ }
93
+
94
+ // International domain validation
95
+ const intlResult = validateInternationalEmail('user@mΓΌnchen.de');
96
+ if (!intlResult) {
97
+ console.log('Valid international email');
98
+ } else {
99
+ console.log('Validation error:', intlResult.message);
100
+ }
101
+ ```
102
+
103
+ ## Batch Processing
104
+
105
+ **New in 2.7.0**: Process multiple emails efficiently with deduplication:
106
+
107
+ ```typescript
108
+ import { batchProcessEmails } from '@mikkelscheike/email-provider-links';
109
+
110
+ const emails = [
111
+ 'user@gmail.com',
112
+ 'u.s.e.r+work@gmail.com', // Alias of the first email
113
+ 'test@yahoo.com',
114
+ 'invalid-email'
115
+ ];
116
+
117
+ const results = batchProcessEmails(emails, {
118
+ includeProviderInfo: true,
119
+ normalizeEmails: true,
120
+ deduplicateAliases: true
121
+ });
122
+
123
+ results.forEach(result => {
124
+ console.log(`${result.email}: ${result.isValid ? 'Valid' : 'Invalid'}`);
125
+ if (result.isDuplicate) {
126
+ console.log(' πŸ”„ Duplicate detected');
127
+ }
128
+ });
129
+ ```
130
+
67
131
  ## Supported Providers
68
132
 
69
133
  **πŸ“Š Current Coverage: 93 providers supporting 178 domains**
@@ -95,7 +159,7 @@ console.log(unknown.loginUrl); // null
95
159
  - **Eastern Europe**: Centrum (Czech/Slovak), Interia, Onet (Poland), Rambler (Russia)
96
160
  - **Other Regions**: UOL, Terra (Brazil), Telkom (South Africa), Xtra (New Zealand)
97
161
 
98
- ## API
162
+ ## API Reference
99
163
 
100
164
  ### `getEmailProvider(email, timeout?)`
101
165
  **Recommended** - Detects any email provider including business domains.
@@ -128,21 +192,42 @@ const result = getEmailProviderSync('user@gmail.com');
128
192
  // Returns: { provider, loginUrl, email }
129
193
  ```
130
194
 
195
+ ### `getEmailProviderFast(email, options?)`
196
+ **High-performance** - Concurrent DNS with detailed timing information.
197
+
198
+ ```typescript
199
+ const result = await getEmailProviderFast('user@mycompany.com', {
200
+ enableParallel: true,
201
+ collectDebugInfo: true,
202
+ timeout: 3000
203
+ });
204
+
205
+ console.log(result.timing); // { mx: 120, txt: 95, total: 125 }
206
+ console.log(result.confidence); // 0.9
207
+ ```
208
+
131
209
  ## Real-World Example
132
210
 
133
211
  ```typescript
134
212
  async function handlePasswordReset(email: string) {
135
- const result = await getEmailProvider(email);
213
+ // Validate email first
214
+ const validation = validateEmailAddress(email);
215
+ if (!validation.isValid) {
216
+ throw new Error(`Invalid email: ${validation.error?.message}`);
217
+ }
218
+
219
+ // Get provider information
220
+ const result = await getEmailProvider(validation.normalizedEmail);
136
221
 
137
222
  return {
138
223
  providerUrl: result.loginUrl,
139
224
  providerName: result.provider?.companyProvider || null,
140
- isSupported: result.provider !== null
225
+ isSupported: result.provider !== null,
226
+ detectionMethod: result.detectionMethod
141
227
  };
142
228
  }
143
229
  ```
144
230
 
145
-
146
231
  ## Configuration
147
232
 
148
233
  ```typescript
@@ -155,97 +240,24 @@ console.log('Max requests:', Config.MAX_DNS_REQUESTS_PER_MINUTE); // 10
155
240
  console.log('Default timeout:', Config.DEFAULT_DNS_TIMEOUT); // 5000ms
156
241
  ```
157
242
 
158
- ## Email Validation
159
-
160
- The library includes comprehensive email validation following international standards:
161
-
162
- ```typescript
163
- import { validateInternationalEmail } from '@mikkelscheike/email-provider-links';
164
-
165
- // Validate any email address
166
- const result = validateInternationalEmail('user@example.com');
167
-
168
- // Returns undefined for valid emails
169
- console.log(result); // undefined
170
-
171
- // Returns detailed error information for invalid emails
172
- const invalid = validateInternationalEmail('user@mΓΌnchen.com');
173
- if (invalid) {
174
- console.log(invalid.code); // IDN_VALIDATION_ERROR
175
- console.log(invalid.message); // Human-readable error message
176
- }
177
- ```
178
-
179
- ### Validation Features
180
-
181
- - βœ… **RFC Compliance**: Follows RFC 5321, 5322, and 6530 standards
182
- - 🌍 **International Support**: Full IDN (Punycode) validation
183
- - πŸ“ **Detailed Errors**: Clear, translatable error messages
184
- - πŸ” **Comprehensive Checks**:
185
- - Local part validation (username)
186
- - Domain format validation
187
- - IDN encoding validation
188
- - Length limits (local part, domain, total)
189
- - TLD validation
190
-
191
243
  ## Advanced Usage
192
244
 
193
245
  <details>
194
- <summary><strong>πŸ“š Secondary Functions & Specialized Use Cases</strong></summary>
195
-
196
- ### Synchronous Provider Detection (No DNS)
246
+ <summary><strong>πŸ“š Advanced Features & Specialized Use Cases</strong></summary>
197
247
 
198
- If you can't use async or don't want DNS lookups:
248
+ ### Library Statistics
199
249
 
200
250
  ```typescript
201
- import { getEmailProviderSync } from '@mikkelscheike/email-provider-links';
251
+ import { getLibraryStats, getSupportedProviders } from '@mikkelscheike/email-provider-links';
202
252
 
203
- // Synchronous - only checks predefined domains
204
- const result = getEmailProviderSync('user@gmail.com');
205
- console.log(result.loginUrl); // Works for known domains only
206
- ```
253
+ const stats = getLibraryStats();
254
+ console.log(`Version ${stats.version} supports ${stats.providerCount} providers`);
207
255
 
208
- ### Provider Support Checking
209
-
210
- ```typescript
211
- import { isEmailProviderSupported, getSupportedProviders } from '@mikkelscheike/email-provider-links';
212
-
213
- // Check if provider is supported
214
- const supported = isEmailProviderSupported('user@gmail.com');
215
-
216
- // Get all supported providers
217
- const allProviders = getSupportedProviders();
218
- console.log(`Supports ${allProviders.length} providers`);
256
+ const providers = getSupportedProviders();
257
+ console.log(`Total providers: ${providers.length}`);
219
258
  ```
220
259
 
221
- ### Advanced Provider Detection
222
-
223
- ```typescript
224
- import { getEmailProviderFast, detectProviderConcurrent } from '@mikkelscheike/email-provider-links';
225
-
226
- // High-performance detection with concurrent DNS
227
- const fastResult = await getEmailProviderFast('user@mycompany.com', {
228
- enableParallel: true,
229
- collectDebugInfo: true
230
- });
231
- console.log(fastResult.provider?.companyProvider); // "Google Workspace"
232
- console.log(fastResult.timing); // Performance metrics
233
- ```
234
-
235
- ### Configuration Options
236
-
237
- ```typescript
238
- import { Config } from '@mikkelscheike/email-provider-links';
239
-
240
- // Access configuration constants
241
- console.log(Config.DEFAULT_DNS_TIMEOUT); // 5000ms
242
- console.log(Config.MAX_DNS_REQUESTS_PER_MINUTE); // 10
243
- console.log(Config.SUPPORTED_PROVIDERS_COUNT); // 93
244
- ```
245
-
246
- ### πŸ”„ Email Alias Detection & Normalization
247
-
248
- **Specialized feature** for preventing duplicate accounts and fraud detection:
260
+ ### Email Alias Detection & Normalization
249
261
 
250
262
  ```typescript
251
263
  import {
@@ -274,27 +286,38 @@ const canonical = normalizeEmail('u.s.e.r+work@gmail.com');
274
286
  console.log(canonical); // 'user@gmail.com'
275
287
  ```
276
288
 
277
- **Supported alias types:**
278
- - **Gmail dots**: `u.s.e.r@gmail.com` β†’ `user@gmail.com`
279
- - **Plus addressing**: `user+tag@provider.com` β†’ `user@provider.com`
280
- - **Provider-specific rules**: Different providers have different capabilities
289
+ ### Provider Support Checking
290
+
291
+ ```typescript
292
+ import { isEmailProviderSupported, extractDomain } from '@mikkelscheike/email-provider-links';
293
+
294
+ // Check if provider is supported
295
+ const supported = isEmailProviderSupported('user@gmail.com');
296
+
297
+ // Extract domain safely
298
+ const domain = extractDomain('USER@EXAMPLE.COM');
299
+ console.log(domain); // 'example.com'
300
+ ```
281
301
 
282
302
  </details>
283
303
 
284
304
  ## TypeScript Support
285
305
 
306
+ Full TypeScript support with comprehensive interfaces:
307
+
286
308
  ```typescript
287
309
  interface EmailProviderResult {
288
310
  provider: EmailProvider | null;
289
311
  email: string;
290
312
  loginUrl: string | null;
291
- detectionMethod?: 'domain_match' | 'mx_record' | 'txt_record' | 'proxy_detected';
313
+ detectionMethod?: 'domain_match' | 'mx_record' | 'txt_record' | 'both' | 'proxy_detected';
292
314
  proxyService?: string;
293
315
  error?: {
294
316
  type: 'INVALID_EMAIL' | 'DNS_TIMEOUT' | 'RATE_LIMITED' | 'UNKNOWN_DOMAIN' |
295
317
  'NETWORK_ERROR' | 'IDN_VALIDATION_ERROR';
296
318
  message: string;
297
- idnError?: string; // Specific IDN validation error message
319
+ retryAfter?: number; // seconds until retry allowed (for rate limiting)
320
+ idnError?: string; // specific IDN validation error message
298
321
  };
299
322
  }
300
323
 
@@ -332,49 +355,39 @@ Protects against common attack vectors:
332
355
 
333
356
  ### πŸ§ͺ Security Testing
334
357
 
335
- - **92 dedicated security tests** covering all attack vectors
336
- - **Comprehensive security module coverage** with edge case testing
358
+ - **396 comprehensive tests** covering all functionality and edge cases
359
+ - **92+ dedicated security tests** covering all attack vectors
337
360
  - **Automated security validation** in CI/CD pipeline
338
361
  - **Regular security audits** of provider database
339
362
 
340
- ### πŸ” For Security Teams
341
-
342
- Security validation can be integrated into your workflow:
343
-
344
- ```typescript
345
- import { secureLoadProviders } from '@mikkelscheike/email-provider-links/security';
346
-
347
- // Secure loading with integrity verification
348
- const result = secureLoadProviders();
349
- if (result.securityReport.securityLevel === 'CRITICAL') {
350
- // Handle security incident
351
- console.error('Security validation failed:', result.securityReport.issues);
352
- }
353
- ```
354
-
355
363
  ## Performance Benchmarks
356
364
 
357
- This package is designed to be extremely memory efficient and fast. We continuously monitor performance metrics through automated benchmarks that run on every PR and release.
365
+ This package is designed to be extremely memory efficient and fast:
358
366
 
359
- Latest benchmark results show:
360
- - Provider loading: ~0.39MB heap usage, <0.5ms
361
- - Email lookups: ~0.02MB heap usage per 100 operations
362
- - Concurrent DNS: ~0.03MB heap usage, ~110ms for 10 lookups
363
- - Large scale (1000 ops): ~0.02MB heap usage, <3ms total
364
- - Cache effectiveness: ~0.01MB impact on subsequent loads
367
+ - **Provider loading**: ~0.39MB heap usage, <0.5ms
368
+ - **Email lookups**: ~0.02MB heap usage per 100 operations
369
+ - **Concurrent DNS**: ~0.03MB heap usage, ~110ms for 10 lookups
370
+ - **Large scale (1000 ops)**: ~0.02MB heap usage, <3ms total
371
+ - **International validation**: <1ms for complex IDN domains
365
372
 
366
373
  To run benchmarks locally:
367
374
  ```bash
368
375
  npm run benchmark
369
376
  ```
370
377
 
371
- Benchmarks are automatically run in CI to catch any performance regressions.
378
+ ## Examples
379
+
380
+ Run the modern example to see all features in action:
381
+
382
+ ```bash
383
+ npx tsx examples/modern-example.ts
384
+ ```
372
385
 
373
386
  ## Contributing
374
387
 
375
388
  We welcome contributions! See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for guidelines on adding new email providers.
376
389
 
377
- **Quality Assurance**: This project maintains high standards with 370 comprehensive tests achieving 92.89% code coverage.
390
+ **Quality Assurance**: This project maintains high standards with 396 comprehensive tests achieving excellent code coverage.
378
391
  **Security Note**: All new providers undergo security validation and must pass our allowlist verification.
379
392
 
380
393
  ## Security
@@ -387,5 +400,4 @@ MIT License - see [LICENSE](LICENSE) file for details.
387
400
 
388
401
  ---
389
402
 
390
- **Zero dependencies β€’ TypeScript-first β€’ Production ready**
391
-
403
+ **Zero dependencies β€’ TypeScript-first β€’ Production ready β€’ International support**
@@ -56,3 +56,4 @@ export declare function normalizeEmail(email: string): string;
56
56
  * ```
57
57
  */
58
58
  export declare function emailsMatch(email1: string, email2: string): boolean;
59
+ //# sourceMappingURL=alias-detection.d.ts.map
@@ -18,7 +18,12 @@ const ALIAS_RULES = [
18
18
  supportsPlusAddressing: true,
19
19
  ignoresDots: true,
20
20
  normalize: (email) => {
21
- const [username, domain] = email.toLowerCase().split('@');
21
+ const parts = email.toLowerCase().split('@');
22
+ const username = parts[0];
23
+ const domain = parts[1];
24
+ if (!username || !domain) {
25
+ return email.toLowerCase();
26
+ }
22
27
  // Remove dots and everything after +
23
28
  const cleanUsername = username.replace(/\./g, '').split('+')[0];
24
29
  return `${cleanUsername}@${domain}`;
@@ -29,7 +34,12 @@ const ALIAS_RULES = [
29
34
  supportsPlusAddressing: true,
30
35
  ignoresDots: false,
31
36
  normalize: (email) => {
32
- const [username, domain] = email.toLowerCase().split('@');
37
+ const parts = email.toLowerCase().split('@');
38
+ const username = parts[0];
39
+ const domain = parts[1];
40
+ if (!username || !domain) {
41
+ return email.toLowerCase();
42
+ }
33
43
  // Only remove plus addressing for Outlook
34
44
  const cleanUsername = username.split('+')[0];
35
45
  return `${cleanUsername}@${domain}`;
@@ -40,7 +50,12 @@ const ALIAS_RULES = [
40
50
  supportsPlusAddressing: true,
41
51
  ignoresDots: false,
42
52
  normalize: (email) => {
43
- const [username, domain] = email.toLowerCase().split('@');
53
+ const parts = email.toLowerCase().split('@');
54
+ const username = parts[0];
55
+ const domain = parts[1];
56
+ if (!username || !domain) {
57
+ return email.toLowerCase();
58
+ }
44
59
  const cleanUsername = username.split('+')[0];
45
60
  return `${cleanUsername}@${domain}`;
46
61
  }
@@ -50,7 +65,12 @@ const ALIAS_RULES = [
50
65
  supportsPlusAddressing: true,
51
66
  ignoresDots: false,
52
67
  normalize: (email) => {
53
- const [username, domain] = email.toLowerCase().split('@');
68
+ const parts = email.toLowerCase().split('@');
69
+ const username = parts[0];
70
+ const domain = parts[1];
71
+ if (!username || !domain) {
72
+ return email.toLowerCase();
73
+ }
54
74
  const cleanUsername = username.split('+')[0];
55
75
  return `${cleanUsername}@${domain}`;
56
76
  }
@@ -60,7 +80,12 @@ const ALIAS_RULES = [
60
80
  supportsPlusAddressing: true,
61
81
  ignoresDots: false,
62
82
  normalize: (email) => {
63
- const [username, domain] = email.toLowerCase().split('@');
83
+ const parts = email.toLowerCase().split('@');
84
+ const username = parts[0];
85
+ const domain = parts[1];
86
+ if (!username || !domain) {
87
+ return email.toLowerCase();
88
+ }
64
89
  const cleanUsername = username.split('+')[0];
65
90
  return `${cleanUsername}@${domain}`;
66
91
  }
@@ -70,7 +95,12 @@ const ALIAS_RULES = [
70
95
  supportsPlusAddressing: true,
71
96
  ignoresDots: false,
72
97
  normalize: (email) => {
73
- const [username, domain] = email.toLowerCase().split('@');
98
+ const parts = email.toLowerCase().split('@');
99
+ const username = parts[0];
100
+ const domain = parts[1];
101
+ if (!username || !domain) {
102
+ return email.toLowerCase();
103
+ }
74
104
  const cleanUsername = username.split('+')[0];
75
105
  return `${cleanUsername}@${domain}`;
76
106
  }
@@ -80,7 +110,12 @@ const ALIAS_RULES = [
80
110
  supportsPlusAddressing: true,
81
111
  ignoresDots: false,
82
112
  normalize: (email) => {
83
- const [username, domain] = email.toLowerCase().split('@');
113
+ const parts = email.toLowerCase().split('@');
114
+ const username = parts[0];
115
+ const domain = parts[1];
116
+ if (!username || !domain) {
117
+ return email.toLowerCase();
118
+ }
84
119
  const cleanUsername = username.split('+')[0];
85
120
  return `${cleanUsername}@${domain}`;
86
121
  }
@@ -90,7 +125,12 @@ const ALIAS_RULES = [
90
125
  supportsPlusAddressing: true,
91
126
  ignoresDots: false,
92
127
  normalize: (email) => {
93
- const [username, domain] = email.toLowerCase().split('@');
128
+ const parts = email.toLowerCase().split('@');
129
+ const username = parts[0];
130
+ const domain = parts[1];
131
+ if (!username || !domain) {
132
+ return email.toLowerCase();
133
+ }
94
134
  const cleanUsername = username.split('+')[0];
95
135
  return `${cleanUsername}@${domain}`;
96
136
  }
@@ -100,7 +140,12 @@ const ALIAS_RULES = [
100
140
  supportsPlusAddressing: true,
101
141
  ignoresDots: false,
102
142
  normalize: (email) => {
103
- const [username, domain] = email.toLowerCase().split('@');
143
+ const parts = email.toLowerCase().split('@');
144
+ const username = parts[0];
145
+ const domain = parts[1];
146
+ if (!username || !domain) {
147
+ return email.toLowerCase();
148
+ }
104
149
  const cleanUsername = username.split('+')[0];
105
150
  return `${cleanUsername}@${domain}`;
106
151
  }
@@ -116,7 +161,12 @@ const ALIAS_RULES = [
116
161
  supportsPlusAddressing: true,
117
162
  ignoresDots: false,
118
163
  normalize: (email) => {
119
- const [username, domain] = email.toLowerCase().split('@');
164
+ const parts = email.toLowerCase().split('@');
165
+ const username = parts[0];
166
+ const domain = parts[1];
167
+ if (!username || !domain) {
168
+ return email.toLowerCase();
169
+ }
120
170
  const cleanUsername = username.split('+')[0];
121
171
  return `${cleanUsername}@${domain}`;
122
172
  }
@@ -126,7 +176,12 @@ const ALIAS_RULES = [
126
176
  supportsPlusAddressing: true,
127
177
  ignoresDots: false,
128
178
  normalize: (email) => {
129
- const [username, domain] = email.toLowerCase().split('@');
179
+ const parts = email.toLowerCase().split('@');
180
+ const username = parts[0];
181
+ const domain = parts[1];
182
+ if (!username || !domain) {
183
+ return email.toLowerCase();
184
+ }
130
185
  const cleanUsername = username.split('+')[0];
131
186
  return `${cleanUsername}@${domain}`;
132
187
  }
@@ -143,7 +198,7 @@ function isValidEmail(email) {
143
198
  * Gets the alias rule for a given domain
144
199
  */
145
200
  function getAliasRule(domain) {
146
- return ALIAS_RULES.find(rule => rule.domains.includes(domain.toLowerCase()));
201
+ return ALIAS_RULES.find(rule => rule.domains.includes(domain.toLowerCase())) || null;
147
202
  }
148
203
  /**
149
204
  * Detects and analyzes email aliases
@@ -156,7 +211,12 @@ function detectEmailAlias(email) {
156
211
  throw new Error('Invalid email format');
157
212
  }
158
213
  const originalEmail = email.trim();
159
- const [username, domain] = originalEmail.toLowerCase().split('@');
214
+ const emailParts = originalEmail.toLowerCase().split('@');
215
+ const username = emailParts[0];
216
+ const domain = emailParts[1];
217
+ if (!username || !domain) {
218
+ throw new Error('Invalid email format - missing username or domain');
219
+ }
160
220
  const rule = getAliasRule(domain);
161
221
  const result = {
162
222
  canonical: originalEmail.toLowerCase(),
@@ -243,3 +303,4 @@ function emailsMatch(email1, email2) {
243
303
  return false;
244
304
  }
245
305
  }
306
+ //# sourceMappingURL=alias-detection.js.map
package/dist/api.d.ts CHANGED
@@ -51,13 +51,13 @@ export interface EmailProviderResult {
51
51
  * ```typescript
52
52
  * // Consumer email
53
53
  * const gmail = await getEmailProvider('user@gmail.com');
54
- * console.log(gmail.provider?.name); // "Gmail"
55
- * console.log(gmail.loginUrl); // "https://mail.google.com/mail/"
54
+ * console.log(gmail.provider?.companyProvider); // "Gmail"
55
+ * console.log(gmail.loginUrl); // "https://mail.google.com/mail/"
56
56
  *
57
57
  * // Business domain
58
58
  * const business = await getEmailProvider('user@mycompany.com');
59
- * console.log(business.provider?.name); // "Google Workspace" (if detected)
60
- * console.log(business.detectionMethod); // "mx_record"
59
+ * console.log(business.provider?.companyProvider); // "Google Workspace" (if detected)
60
+ * console.log(business.detectionMethod); // "mx_record"
61
61
  *
62
62
  * // Error handling
63
63
  * const invalid = await getEmailProvider('invalid-email');
@@ -79,7 +79,7 @@ export declare function getEmailProvider(email: string, timeout?: number): Promi
79
79
  * ```typescript
80
80
  * // Works for known domains
81
81
  * const gmail = getEmailProviderSync('user@gmail.com');
82
- * console.log(gmail.provider?.name); // "Gmail"
82
+ * console.log(gmail.provider?.companyProvider); // "Gmail"
83
83
  *
84
84
  * // Unknown domains return null
85
85
  * const unknown = getEmailProviderSync('user@mycompany.com');
@@ -171,3 +171,4 @@ export declare const Config: {
171
171
  readonly SUPPORTED_PROVIDERS_COUNT: 93;
172
172
  readonly SUPPORTED_DOMAINS_COUNT: 180;
173
173
  };
174
+ //# sourceMappingURL=api.d.ts.map