@mikkelscheike/email-provider-links 2.7.0 โ 2.8.0
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 +92 -194
- package/dist/alias-detection.d.ts +1 -0
- package/dist/alias-detection.js +74 -13
- package/dist/api.d.ts +7 -6
- package/dist/api.js +21 -16
- package/dist/concurrent-dns.d.ts +3 -2
- package/dist/concurrent-dns.js +20 -9
- package/dist/hash-verifier.d.ts +1 -0
- package/dist/hash-verifier.js +3 -2
- package/dist/idn.d.ts +1 -0
- package/dist/idn.js +1 -0
- package/dist/index.d.ts +158 -10
- package/dist/index.js +300 -22
- package/dist/loader.d.ts +2 -1
- package/dist/loader.js +7 -2
- package/dist/schema.d.ts +4 -3
- package/dist/schema.js +5 -7
- package/dist/secure-loader.d.ts +1 -0
- package/dist/secure-loader.js +1 -0
- package/dist/url-validator.d.ts +1 -0
- package/dist/url-validator.js +1 -0
- package/package.json +6 -6
- package/providers/emailproviders.json +674 -282
package/README.md
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
# Email Provider Links
|
|
2
2
|
|
|
3
|
-
๐ **Modern email provider detection library with
|
|
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** (
|
|
5
|
+
A robust TypeScript library providing direct links to **93 email providers** (180 domains) with **concurrent DNS resolution**, **optimized performance**, **comprehensive email validation**, and advanced security features for login and password reset flows.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## ๐ Try it out
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**[Live Demo](https://demo.mikkelscheike.com)** - Test the library with any email address and see it in action!
|
|
10
|
+
|
|
11
|
+
## โจ New in Version 2.7.0
|
|
12
|
+
|
|
13
|
+
- ๐ **Modern TypeScript**: Updated to latest TypeScript 2025 standards with strict type checking
|
|
14
|
+
- ๐ **Enhanced International Support**: Improved IDN validation and Punycode handling
|
|
15
|
+
- ๐ง **Advanced Email Validation**: Comprehensive validation with detailed error reporting
|
|
16
|
+
- ๐ **Batch Processing**: Efficiently process multiple emails with deduplication
|
|
17
|
+
- ๐ก๏ธ **Improved Security**: Enhanced cryptographic integrity verification
|
|
18
|
+
- โก **Better Performance**: Optimized concurrent DNS with smart caching
|
|
19
|
+
- ๐ฏ **Developer Experience**: Enhanced error messages and debugging information
|
|
20
|
+
- ๐ **Development Mode**: Memory usage tracking when NODE_ENV=development
|
|
21
|
+
|
|
22
|
+
## โจ Core Features
|
|
23
|
+
|
|
24
|
+
- ๐ **Fast & Lightweight**: Zero dependencies, ultra-low memory (~0.08MB initial, ~0.03MB per 1000 ops)
|
|
10
25
|
- ๐ง **93 Email Providers**: Gmail, Outlook, Yahoo, ProtonMail, iCloud, and many more
|
|
11
|
-
- ๐ **
|
|
12
|
-
- ๐ **IDN Support**:
|
|
13
|
-
- โ
**Email Validation**: International email validation
|
|
26
|
+
- ๐ **207 Domains Supported**: Comprehensive international coverage
|
|
27
|
+
- ๐ **Full IDN Support**: International domain names with RFC compliance and Punycode
|
|
28
|
+
- โ
**Advanced Email Validation**: International email validation with detailed error reporting
|
|
14
29
|
- ๐ข **Business Domain Detection**: DNS-based detection for custom domains (Google Workspace, Microsoft 365, etc.)
|
|
15
30
|
- ๐ **Enterprise Security**: Multi-layer protection against malicious URLs and supply chain attacks
|
|
16
31
|
- ๐ก๏ธ **URL Validation**: HTTPS-only enforcement with domain allowlisting
|
|
@@ -20,7 +35,8 @@ A TypeScript library providing direct links to **93 email providers** (178 domai
|
|
|
20
35
|
- ๐ฆ **Rate Limiting**: Built-in DNS query rate limiting to prevent abuse
|
|
21
36
|
- ๐ **Email Alias Detection**: Normalize Gmail dots, plus addressing, and provider-specific aliases
|
|
22
37
|
- ๐ก๏ธ **Fraud Prevention**: Detect duplicate accounts through email alias manipulation
|
|
23
|
-
-
|
|
38
|
+
- ๐ฆ **Batch Processing**: Efficiently process multiple emails with deduplication
|
|
39
|
+
- ๐งช **Thoroughly Tested**: 424 tests with 93.16% code coverage
|
|
24
40
|
|
|
25
41
|
## Installation
|
|
26
42
|
|
|
@@ -32,7 +48,7 @@ npm install @mikkelscheike/email-provider-links
|
|
|
32
48
|
## Requirements
|
|
33
49
|
|
|
34
50
|
- **Node.js**: `>=18.0.0` (Tested on 18.x, 20.x, 22.x, **24.x**)
|
|
35
|
-
- **TypeScript**: `>=4.0.0` (optional)
|
|
51
|
+
- **TypeScript**: `>=4.0.0` (optional, but recommended)
|
|
36
52
|
- **Zero runtime dependencies** - No external packages required
|
|
37
53
|
|
|
38
54
|
### Node.js 24 Support โจ
|
|
@@ -43,30 +59,9 @@ Fully compatible with the latest Node.js 24.x! The library is tested on:
|
|
|
43
59
|
- Node.js 22.x (Current)
|
|
44
60
|
- **Node.js 24.x (Latest)** - Full support with latest features
|
|
45
61
|
|
|
46
|
-
## Quick Start
|
|
47
|
-
|
|
48
|
-
**One function handles everything** - consumer emails, business domains, and unknown providers:
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
import { getEmailProvider } from '@mikkelscheike/email-provider-links';
|
|
52
|
-
|
|
53
|
-
// Works for ANY email address - the only function you need
|
|
54
|
-
const result = await getEmailProvider('user@gmail.com');
|
|
55
|
-
console.log(result.loginUrl); // "https://mail.google.com/mail/"
|
|
56
|
-
console.log(result.provider?.companyProvider); // "Gmail"
|
|
57
|
-
|
|
58
|
-
// Automatically detects business domains too
|
|
59
|
-
const business = await getEmailProvider('user@mycompany.com');
|
|
60
|
-
console.log(business.provider?.companyProvider); // "Google Workspace" (if detected)
|
|
61
|
-
|
|
62
|
-
// Gracefully handles unknown providers
|
|
63
|
-
const unknown = await getEmailProvider('user@unknown.com');
|
|
64
|
-
console.log(unknown.loginUrl); // null
|
|
65
|
-
```
|
|
66
|
-
|
|
67
62
|
## Supported Providers
|
|
68
63
|
|
|
69
|
-
**๐ Current Coverage: 93 providers supporting
|
|
64
|
+
**๐ Current Coverage: 93 providers supporting 207 domains**
|
|
70
65
|
|
|
71
66
|
**Consumer Email Providers:**
|
|
72
67
|
- **Gmail** (2 domains): gmail.com, googlemail.com
|
|
@@ -95,7 +90,7 @@ console.log(unknown.loginUrl); // null
|
|
|
95
90
|
- **Eastern Europe**: Centrum (Czech/Slovak), Interia, Onet (Poland), Rambler (Russia)
|
|
96
91
|
- **Other Regions**: UOL, Terra (Brazil), Telkom (South Africa), Xtra (New Zealand)
|
|
97
92
|
|
|
98
|
-
## API
|
|
93
|
+
## API Reference
|
|
99
94
|
|
|
100
95
|
### `getEmailProvider(email, timeout?)`
|
|
101
96
|
**Recommended** - Detects any email provider including business domains.
|
|
@@ -128,21 +123,42 @@ const result = getEmailProviderSync('user@gmail.com');
|
|
|
128
123
|
// Returns: { provider, loginUrl, email }
|
|
129
124
|
```
|
|
130
125
|
|
|
126
|
+
### `getEmailProviderFast(email, options?)`
|
|
127
|
+
**High-performance** - Concurrent DNS with detailed timing information.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const result = await getEmailProviderFast('user@mycompany.com', {
|
|
131
|
+
enableParallel: true,
|
|
132
|
+
collectDebugInfo: true,
|
|
133
|
+
timeout: 3000
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
console.log(result.timing); // { mx: 120, txt: 95, total: 125 }
|
|
137
|
+
console.log(result.confidence); // 0.9
|
|
138
|
+
```
|
|
139
|
+
|
|
131
140
|
## Real-World Example
|
|
132
141
|
|
|
133
142
|
```typescript
|
|
134
143
|
async function handlePasswordReset(email: string) {
|
|
135
|
-
|
|
144
|
+
// Validate email first
|
|
145
|
+
const validation = validateEmailAddress(email);
|
|
146
|
+
if (!validation.isValid) {
|
|
147
|
+
throw new Error(`Invalid email: ${validation.error?.message}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Get provider information
|
|
151
|
+
const result = await getEmailProvider(validation.normalizedEmail);
|
|
136
152
|
|
|
137
153
|
return {
|
|
138
154
|
providerUrl: result.loginUrl,
|
|
139
155
|
providerName: result.provider?.companyProvider || null,
|
|
140
|
-
isSupported: result.provider !== null
|
|
156
|
+
isSupported: result.provider !== null,
|
|
157
|
+
detectionMethod: result.detectionMethod
|
|
141
158
|
};
|
|
142
159
|
}
|
|
143
160
|
```
|
|
144
161
|
|
|
145
|
-
|
|
146
162
|
## Configuration
|
|
147
163
|
|
|
148
164
|
```typescript
|
|
@@ -155,97 +171,24 @@ console.log('Max requests:', Config.MAX_DNS_REQUESTS_PER_MINUTE); // 10
|
|
|
155
171
|
console.log('Default timeout:', Config.DEFAULT_DNS_TIMEOUT); // 5000ms
|
|
156
172
|
```
|
|
157
173
|
|
|
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
174
|
## Advanced Usage
|
|
192
175
|
|
|
193
176
|
<details>
|
|
194
|
-
<summary><strong>๐
|
|
177
|
+
<summary><strong>๐ Advanced Features & Specialized Use Cases</strong></summary>
|
|
195
178
|
|
|
196
|
-
###
|
|
197
|
-
|
|
198
|
-
If you can't use async or don't want DNS lookups:
|
|
179
|
+
### Library Statistics
|
|
199
180
|
|
|
200
181
|
```typescript
|
|
201
|
-
import {
|
|
202
|
-
|
|
203
|
-
// Synchronous - only checks predefined domains
|
|
204
|
-
const result = getEmailProviderSync('user@gmail.com');
|
|
205
|
-
console.log(result.loginUrl); // Works for known domains only
|
|
206
|
-
```
|
|
182
|
+
import { getLibraryStats, getSupportedProviders } from '@mikkelscheike/email-provider-links';
|
|
207
183
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
import { isEmailProviderSupported, getSupportedProviders } from '@mikkelscheike/email-provider-links';
|
|
184
|
+
const stats = getLibraryStats();
|
|
185
|
+
console.log(`Version ${stats.version} supports ${stats.providerCount} providers`);
|
|
212
186
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// Get all supported providers
|
|
217
|
-
const allProviders = getSupportedProviders();
|
|
218
|
-
console.log(`Supports ${allProviders.length} providers`);
|
|
219
|
-
```
|
|
220
|
-
|
|
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
|
|
187
|
+
const providers = getSupportedProviders();
|
|
188
|
+
console.log(`Total providers: ${providers.length}`);
|
|
233
189
|
```
|
|
234
190
|
|
|
235
|
-
###
|
|
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:
|
|
191
|
+
### Email Alias Detection & Normalization
|
|
249
192
|
|
|
250
193
|
```typescript
|
|
251
194
|
import {
|
|
@@ -274,107 +217,63 @@ const canonical = normalizeEmail('u.s.e.r+work@gmail.com');
|
|
|
274
217
|
console.log(canonical); // 'user@gmail.com'
|
|
275
218
|
```
|
|
276
219
|
|
|
277
|
-
|
|
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
|
|
281
|
-
|
|
282
|
-
</details>
|
|
283
|
-
|
|
284
|
-
## TypeScript Support
|
|
220
|
+
### Provider Support Checking
|
|
285
221
|
|
|
286
222
|
```typescript
|
|
287
|
-
|
|
288
|
-
provider: EmailProvider | null;
|
|
289
|
-
email: string;
|
|
290
|
-
loginUrl: string | null;
|
|
291
|
-
detectionMethod?: 'domain_match' | 'mx_record' | 'txt_record' | 'proxy_detected';
|
|
292
|
-
proxyService?: string;
|
|
293
|
-
error?: {
|
|
294
|
-
type: 'INVALID_EMAIL' | 'DNS_TIMEOUT' | 'RATE_LIMITED' | 'UNKNOWN_DOMAIN' |
|
|
295
|
-
'NETWORK_ERROR' | 'IDN_VALIDATION_ERROR';
|
|
296
|
-
message: string;
|
|
297
|
-
idnError?: string; // Specific IDN validation error message
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
interface ConfigConstants {
|
|
302
|
-
DEFAULT_DNS_TIMEOUT: number; // 5000ms
|
|
303
|
-
MAX_DNS_REQUESTS_PER_MINUTE: number; // 10 requests
|
|
304
|
-
SUPPORTED_PROVIDERS_COUNT: number; // 93 providers
|
|
305
|
-
SUPPORTED_DOMAINS_COUNT: number; // 178 domains
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
## ๐ก๏ธ Security Features
|
|
310
|
-
|
|
311
|
-
This package implements **enterprise-grade security** to protect against malicious redirects and supply chain attacks:
|
|
223
|
+
import { isEmailProviderSupported, extractDomain } from '@mikkelscheike/email-provider-links';
|
|
312
224
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
- **HTTPS-Only Enforcement**: All provider URLs must use HTTPS protocol
|
|
316
|
-
- **Domain Allowlisting**: Only pre-approved domains are allowed (93+ verified providers)
|
|
317
|
-
- **Malicious Pattern Detection**: Blocks IP addresses, URL shorteners, suspicious TLDs
|
|
318
|
-
- **Path Traversal Prevention**: Detects and blocks `../` and encoded variants
|
|
319
|
-
- **JavaScript Injection Protection**: Prevents `javascript:`, `data:`, and script injections
|
|
320
|
-
- **File Integrity Verification**: SHA-256 hash verification for provider database
|
|
225
|
+
// Check if provider is supported
|
|
226
|
+
const supported = isEmailProviderSupported('user@gmail.com');
|
|
321
227
|
|
|
322
|
-
|
|
228
|
+
// Extract domain safely
|
|
229
|
+
const domain = extractDomain('USER@EXAMPLE.COM');
|
|
230
|
+
console.log(domain); // 'example.com'
|
|
231
|
+
```
|
|
323
232
|
|
|
324
|
-
|
|
325
|
-
- โ **URL Injection**: Blocked by strict allowlisting
|
|
326
|
-
- โ **Typosquatting**: Blocked by domain validation
|
|
327
|
-
- โ **URL Shorteners**: Blocked by pattern detection
|
|
328
|
-
- โ **Protocol Downgrade**: Blocked by HTTPS enforcement
|
|
329
|
-
- โ **Path Traversal**: Blocked by path validation
|
|
330
|
-
- โ **Script Injection**: Blocked by content validation
|
|
331
|
-
- โ **Supply Chain Attacks**: Blocked by integrity verification
|
|
233
|
+
</details>
|
|
332
234
|
|
|
333
|
-
|
|
235
|
+
## Performance and Detection System
|
|
334
236
|
|
|
335
|
-
|
|
336
|
-
- **Comprehensive security module coverage** with edge case testing
|
|
337
|
-
- **Automated security validation** in CI/CD pipeline
|
|
338
|
-
- **Regular security audits** of provider database
|
|
237
|
+
For detailed performance metrics and information about the detection system, refer to [Performance and Detection System](docs/PERFORMANCE.md).
|
|
339
238
|
|
|
340
|
-
###
|
|
239
|
+
### Development Mode Features
|
|
341
240
|
|
|
342
|
-
|
|
241
|
+
When `NODE_ENV` is set to 'development', the library provides additional insights:
|
|
343
242
|
|
|
344
243
|
```typescript
|
|
345
|
-
|
|
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
|
-
}
|
|
244
|
+
// Memory usage is automatically logged:
|
|
245
|
+
// ๐ Current memory usage: 0.08 MB
|
|
353
246
|
```
|
|
354
247
|
|
|
355
|
-
|
|
248
|
+
### Memory Management
|
|
356
249
|
|
|
357
|
-
|
|
250
|
+
The library implements careful memory management:
|
|
251
|
+
- Initial load: ~0.08MB heap usage
|
|
252
|
+
- Batch operations: ~0.03MB per 1000 operations
|
|
253
|
+
- Maximum load: < 25MB even under heavy concurrent operations
|
|
254
|
+
- Automatic garbage collection hints
|
|
255
|
+
- Memory usage logging in development mode
|
|
358
256
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
-
|
|
364
|
-
-
|
|
257
|
+
### Performance Benchmarks
|
|
258
|
+
|
|
259
|
+
This package is designed to be extremely memory efficient and fast:
|
|
260
|
+
|
|
261
|
+
- **Provider loading**: ~0.08MB heap usage, ~0.5ms
|
|
262
|
+
- **Email lookups**: ~0.03MB heap usage per 100 operations
|
|
263
|
+
- **Concurrent DNS**: ~0.03MB heap usage, ~27ms for 10 lookups
|
|
264
|
+
- **Large scale (1000 ops)**: ~0.03MB heap usage, ~1.1ms total
|
|
265
|
+
- **International validation**: <1ms for complex IDN domains
|
|
365
266
|
|
|
366
267
|
To run benchmarks locally:
|
|
367
268
|
```bash
|
|
368
269
|
npm run benchmark
|
|
369
270
|
```
|
|
370
271
|
|
|
371
|
-
Benchmarks are automatically run in CI to catch any performance regressions.
|
|
372
|
-
|
|
373
272
|
## Contributing
|
|
374
273
|
|
|
375
274
|
We welcome contributions! See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for guidelines on adding new email providers.
|
|
376
275
|
|
|
377
|
-
**Quality Assurance**: This project maintains high standards with
|
|
276
|
+
**Quality Assurance**: This project maintains high standards with 424 comprehensive tests achieving 93.16% code coverage (96.46% function coverage).
|
|
378
277
|
**Security Note**: All new providers undergo security validation and must pass our allowlist verification.
|
|
379
278
|
|
|
380
279
|
## Security
|
|
@@ -387,5 +286,4 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
387
286
|
|
|
388
287
|
---
|
|
389
288
|
|
|
390
|
-
**Zero dependencies โข TypeScript-first โข Production ready**
|
|
391
|
-
|
|
289
|
+
**Zero dependencies โข TypeScript-first โข Production ready โข International support**
|
package/dist/alias-detection.js
CHANGED
|
@@ -18,7 +18,12 @@ const ALIAS_RULES = [
|
|
|
18
18
|
supportsPlusAddressing: true,
|
|
19
19
|
ignoresDots: true,
|
|
20
20
|
normalize: (email) => {
|
|
21
|
-
const
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export interface EmailProvider {
|
|
8
8
|
companyProvider: string;
|
|
9
|
-
loginUrl: string;
|
|
9
|
+
loginUrl: string | null;
|
|
10
10
|
domains: string[];
|
|
11
11
|
customDomainDetection?: {
|
|
12
12
|
mxPatterns?: string[];
|
|
@@ -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?.
|
|
55
|
-
* console.log(gmail.loginUrl);
|
|
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?.
|
|
60
|
-
* console.log(business.detectionMethod);
|
|
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?.
|
|
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
|