@emailcheck/email-validator-js 2.12.0 → 2.13.1-beta.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 +330 -77
- package/dist/adapters/lru-adapter.d.ts +19 -0
- package/dist/adapters/redis-adapter.d.ts +45 -0
- package/dist/cache-factory.d.ts +39 -0
- package/dist/cache-interface.d.ts +124 -0
- package/dist/cache.d.ts +28 -0
- package/dist/dns.d.ts +2 -1
- package/dist/domain-suggester.d.ts +6 -2
- package/dist/index.d.ts +6 -9
- package/dist/index.esm.js +202 -166
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +201 -166
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +4 -15
- package/dist/validator.d.ts +2 -1
- package/package.json +2 -2
package/dist/index.esm.js
CHANGED
|
@@ -4,6 +4,68 @@ import { promises } from 'node:dns';
|
|
|
4
4
|
import { stringSimilarity } from 'string-similarity-js';
|
|
5
5
|
import net from 'node:net';
|
|
6
6
|
|
|
7
|
+
class LRUAdapter {
|
|
8
|
+
constructor(maxSize = 1e3, ttlMs = 36e5) {
|
|
9
|
+
this.lru = lru(maxSize, ttlMs);
|
|
10
|
+
}
|
|
11
|
+
get(key) {
|
|
12
|
+
const value = this.lru.get(key);
|
|
13
|
+
return value === void 0 ? null : value;
|
|
14
|
+
}
|
|
15
|
+
async set(key, value, ttlMs) {
|
|
16
|
+
if (ttlMs !== void 0) {
|
|
17
|
+
this.lru.set(key, value);
|
|
18
|
+
} else {
|
|
19
|
+
this.lru.set(key, value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async delete(key) {
|
|
23
|
+
this.lru.delete(key);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
async has(key) {
|
|
27
|
+
return this.lru.has(key);
|
|
28
|
+
}
|
|
29
|
+
async clear() {
|
|
30
|
+
this.lru.clear();
|
|
31
|
+
}
|
|
32
|
+
size() {
|
|
33
|
+
return this.lru.size;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the underlying LRU instance for advanced operations
|
|
37
|
+
*/
|
|
38
|
+
getLRU() {
|
|
39
|
+
return this.lru;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const DEFAULT_CACHE_TTL = {
|
|
44
|
+
mx: 36e5,
|
|
45
|
+
// 1 hour
|
|
46
|
+
disposable: 864e5,
|
|
47
|
+
// 24 hours
|
|
48
|
+
free: 864e5,
|
|
49
|
+
// 24 hours
|
|
50
|
+
domainValid: 864e5,
|
|
51
|
+
// 24 hours
|
|
52
|
+
smtp: 18e5,
|
|
53
|
+
// 30 minutes
|
|
54
|
+
domainSuggestion: 864e5,
|
|
55
|
+
// 24 hours
|
|
56
|
+
whois: 36e5
|
|
57
|
+
// 1 hour
|
|
58
|
+
};
|
|
59
|
+
const DEFAULT_CACHE_SIZE = {
|
|
60
|
+
mx: 500,
|
|
61
|
+
disposable: 1e3,
|
|
62
|
+
free: 1e3,
|
|
63
|
+
domainValid: 1e3,
|
|
64
|
+
smtp: 500,
|
|
65
|
+
domainSuggestion: 1e3,
|
|
66
|
+
whois: 200
|
|
67
|
+
};
|
|
68
|
+
|
|
7
69
|
const mxCache = lru(500, 36e5);
|
|
8
70
|
const disposableCache = lru(1e3, 864e5);
|
|
9
71
|
const freeCache = lru(1e3, 864e5);
|
|
@@ -11,6 +73,19 @@ const domainValidCache = lru(1e3, 864e5);
|
|
|
11
73
|
const smtpCache = lru(500, 18e5);
|
|
12
74
|
const domainSuggestionCache = lru(1e3, 864e5);
|
|
13
75
|
const whoisCache = lru(200, 36e5);
|
|
76
|
+
function getCacheStore(defaultLru, cacheType, passedCache) {
|
|
77
|
+
if (passedCache && passedCache[cacheType]) {
|
|
78
|
+
return passedCache[cacheType];
|
|
79
|
+
}
|
|
80
|
+
return new LRUAdapter(DEFAULT_CACHE_SIZE[cacheType], DEFAULT_CACHE_TTL[cacheType]);
|
|
81
|
+
}
|
|
82
|
+
const mxCacheStore = (passedCache) => getCacheStore(mxCache, "mx", passedCache);
|
|
83
|
+
const disposableCacheStore = (passedCache) => getCacheStore(disposableCache, "disposable", passedCache);
|
|
84
|
+
const freeCacheStore = (passedCache) => getCacheStore(freeCache, "free", passedCache);
|
|
85
|
+
const domainValidCacheStore = (passedCache) => getCacheStore(domainValidCache, "domainValid", passedCache);
|
|
86
|
+
const smtpCacheStore = (passedCache) => getCacheStore(smtpCache, "smtp", passedCache);
|
|
87
|
+
const domainSuggestionCacheStore = (passedCache) => getCacheStore(domainSuggestionCache, "domainSuggestion", passedCache);
|
|
88
|
+
const whoisCacheStore = (passedCache) => getCacheStore(whoisCache, "whois", passedCache);
|
|
14
89
|
function clearAllCaches() {
|
|
15
90
|
mxCache.clear();
|
|
16
91
|
disposableCache.clear();
|
|
@@ -21,9 +96,10 @@ function clearAllCaches() {
|
|
|
21
96
|
whoisCache.clear();
|
|
22
97
|
}
|
|
23
98
|
|
|
24
|
-
async function resolveMxRecords(domain) {
|
|
25
|
-
const
|
|
26
|
-
|
|
99
|
+
async function resolveMxRecords(domain, cache) {
|
|
100
|
+
const cacheStore = mxCacheStore(cache);
|
|
101
|
+
const cached = await cacheStore.get(domain);
|
|
102
|
+
if (cached !== null && cached !== void 0) {
|
|
27
103
|
return cached;
|
|
28
104
|
}
|
|
29
105
|
try {
|
|
@@ -38,10 +114,10 @@ async function resolveMxRecords(domain) {
|
|
|
38
114
|
return 0;
|
|
39
115
|
});
|
|
40
116
|
const exchanges = records.map((record) => record.exchange);
|
|
41
|
-
|
|
117
|
+
await cacheStore.set(domain, exchanges);
|
|
42
118
|
return exchanges;
|
|
43
119
|
} catch (error) {
|
|
44
|
-
|
|
120
|
+
await cacheStore.set(domain, []);
|
|
45
121
|
throw error;
|
|
46
122
|
}
|
|
47
123
|
}
|
|
@@ -131,18 +207,73 @@ function getSimilarityThreshold(domain) {
|
|
|
131
207
|
return 0.75;
|
|
132
208
|
}
|
|
133
209
|
function defaultDomainSuggestionMethod(domain, commonDomains) {
|
|
210
|
+
const domainsToCheck = commonDomains || COMMON_EMAIL_DOMAINS;
|
|
211
|
+
const lowerDomain = domain.toLowerCase();
|
|
212
|
+
if (domainsToCheck.includes(lowerDomain)) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
for (const [correctDomain, typos] of Object.entries(TYPO_PATTERNS)) {
|
|
216
|
+
if (typos.includes(lowerDomain)) {
|
|
217
|
+
return {
|
|
218
|
+
original: domain,
|
|
219
|
+
suggested: correctDomain,
|
|
220
|
+
confidence: 0.95
|
|
221
|
+
// High confidence for known typo patterns
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
let bestMatch = null;
|
|
226
|
+
const threshold = getSimilarityThreshold(lowerDomain);
|
|
227
|
+
for (const commonDomain of domainsToCheck) {
|
|
228
|
+
const similarity = stringSimilarity(lowerDomain, commonDomain.toLowerCase());
|
|
229
|
+
if (similarity >= threshold) {
|
|
230
|
+
if (!bestMatch || similarity > bestMatch.similarity) {
|
|
231
|
+
bestMatch = { domain: commonDomain, similarity };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (!bestMatch) {
|
|
236
|
+
for (const commonDomain of domainsToCheck) {
|
|
237
|
+
if (Math.abs(lowerDomain.length - commonDomain.length) <= 2) {
|
|
238
|
+
const similarity = stringSimilarity(lowerDomain, commonDomain.toLowerCase());
|
|
239
|
+
if (similarity >= 0.7) {
|
|
240
|
+
if (!bestMatch || similarity > bestMatch.similarity) {
|
|
241
|
+
bestMatch = { domain: commonDomain, similarity };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (bestMatch) {
|
|
248
|
+
if (bestMatch.domain.charAt(0) !== lowerDomain.charAt(0) && bestMatch.similarity < 0.9) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
original: domain,
|
|
253
|
+
suggested: bestMatch.domain,
|
|
254
|
+
confidence: bestMatch.similarity
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
async function defaultDomainSuggestionMethodAsync(domain, commonDomains) {
|
|
260
|
+
return defaultDomainSuggestionMethodImpl(domain, commonDomains);
|
|
261
|
+
}
|
|
262
|
+
async function defaultDomainSuggestionMethodImpl(domain, commonDomains) {
|
|
134
263
|
if (!domain || domain.length < 3) {
|
|
135
264
|
return null;
|
|
136
265
|
}
|
|
137
266
|
const domainsToCheck = commonDomains || COMMON_EMAIL_DOMAINS;
|
|
138
267
|
const lowerDomain = domain.toLowerCase();
|
|
139
268
|
const cacheKey = `${lowerDomain}:${domainsToCheck.length}`;
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
269
|
+
const cache = domainSuggestionCacheStore();
|
|
270
|
+
const cached = cache.get(cacheKey);
|
|
271
|
+
const resolved = cached && typeof cached === "object" && "then" in cached ? await cached : cached;
|
|
272
|
+
if (resolved !== null && resolved !== void 0) {
|
|
273
|
+
return resolved ? { original: domain, suggested: resolved.suggested, confidence: resolved.confidence } : null;
|
|
143
274
|
}
|
|
144
275
|
if (domainsToCheck.includes(lowerDomain)) {
|
|
145
|
-
|
|
276
|
+
await cache.set(cacheKey, null);
|
|
146
277
|
return null;
|
|
147
278
|
}
|
|
148
279
|
for (const [correctDomain, typos] of Object.entries(TYPO_PATTERNS)) {
|
|
@@ -153,7 +284,7 @@ function defaultDomainSuggestionMethod(domain, commonDomains) {
|
|
|
153
284
|
confidence: 0.95
|
|
154
285
|
// High confidence for known typo patterns
|
|
155
286
|
};
|
|
156
|
-
|
|
287
|
+
await cache.set(cacheKey, { suggested: result.suggested, confidence: result.confidence });
|
|
157
288
|
return result;
|
|
158
289
|
}
|
|
159
290
|
}
|
|
@@ -181,7 +312,7 @@ function defaultDomainSuggestionMethod(domain, commonDomains) {
|
|
|
181
312
|
}
|
|
182
313
|
if (bestMatch) {
|
|
183
314
|
if (bestMatch.domain.charAt(0) !== lowerDomain.charAt(0) && bestMatch.similarity < 0.9) {
|
|
184
|
-
|
|
315
|
+
await cache.set(cacheKey, null);
|
|
185
316
|
return null;
|
|
186
317
|
}
|
|
187
318
|
const result = {
|
|
@@ -189,10 +320,10 @@ function defaultDomainSuggestionMethod(domain, commonDomains) {
|
|
|
189
320
|
suggested: bestMatch.domain,
|
|
190
321
|
confidence: bestMatch.similarity
|
|
191
322
|
};
|
|
192
|
-
|
|
323
|
+
await cache.set(cacheKey, { suggested: result.suggested, confidence: result.confidence });
|
|
193
324
|
return result;
|
|
194
325
|
}
|
|
195
|
-
|
|
326
|
+
await cache.set(cacheKey, null);
|
|
196
327
|
return null;
|
|
197
328
|
}
|
|
198
329
|
function suggestDomain(params) {
|
|
@@ -209,7 +340,7 @@ function suggestDomain(params) {
|
|
|
209
340
|
}
|
|
210
341
|
return defaultDomainSuggestionMethod(domain, commonDomains);
|
|
211
342
|
}
|
|
212
|
-
function suggestEmailDomain(email, commonDomains) {
|
|
343
|
+
async function suggestEmailDomain(email, commonDomains) {
|
|
213
344
|
if (!email || !email.includes("@")) {
|
|
214
345
|
return null;
|
|
215
346
|
}
|
|
@@ -217,7 +348,7 @@ function suggestEmailDomain(email, commonDomains) {
|
|
|
217
348
|
if (!domain || !localPart) {
|
|
218
349
|
return null;
|
|
219
350
|
}
|
|
220
|
-
const suggestion =
|
|
351
|
+
const suggestion = await defaultDomainSuggestionMethodAsync(domain, commonDomains);
|
|
221
352
|
if (suggestion) {
|
|
222
353
|
return {
|
|
223
354
|
original: email,
|
|
@@ -1089,7 +1220,7 @@ var VerificationErrorCode;
|
|
|
1089
1220
|
VerificationErrorCode2["FREE_EMAIL_PROVIDER"] = "FREE_EMAIL_PROVIDER";
|
|
1090
1221
|
})(VerificationErrorCode || (VerificationErrorCode = {}));
|
|
1091
1222
|
|
|
1092
|
-
function isValidEmailDomain(emailOrDomain) {
|
|
1223
|
+
async function isValidEmailDomain(emailOrDomain, cache) {
|
|
1093
1224
|
let [_, emailDomain] = (emailOrDomain === null || emailOrDomain === void 0 ? void 0 : emailOrDomain.split("@")) || [];
|
|
1094
1225
|
if (!emailDomain) {
|
|
1095
1226
|
emailDomain = _;
|
|
@@ -1097,16 +1228,17 @@ function isValidEmailDomain(emailOrDomain) {
|
|
|
1097
1228
|
if (!emailDomain) {
|
|
1098
1229
|
return false;
|
|
1099
1230
|
}
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1231
|
+
const cacheStore = domainValidCacheStore(cache);
|
|
1232
|
+
const cached = await cacheStore.get(emailDomain);
|
|
1233
|
+
if (cached !== null && cached !== void 0) {
|
|
1102
1234
|
return cached;
|
|
1103
1235
|
}
|
|
1104
1236
|
try {
|
|
1105
1237
|
const result = isValid(emailDomain) || false;
|
|
1106
|
-
|
|
1238
|
+
await cacheStore.set(emailDomain, result);
|
|
1107
1239
|
return result;
|
|
1108
1240
|
} catch (_e) {
|
|
1109
|
-
|
|
1241
|
+
await cacheStore.set(emailDomain, false);
|
|
1110
1242
|
return false;
|
|
1111
1243
|
}
|
|
1112
1244
|
}
|
|
@@ -1628,8 +1760,9 @@ function queryWhoisServer(domain, server, timeout = 5e3) {
|
|
|
1628
1760
|
async function getWhoisData(domain, timeout = 5e3) {
|
|
1629
1761
|
var _a;
|
|
1630
1762
|
const cacheKey = `whois:${domain}`;
|
|
1631
|
-
const
|
|
1632
|
-
|
|
1763
|
+
const cache = whoisCacheStore();
|
|
1764
|
+
const cached = await cache.get(cacheKey);
|
|
1765
|
+
if (cached !== null && cached !== void 0) {
|
|
1633
1766
|
return cached;
|
|
1634
1767
|
}
|
|
1635
1768
|
try {
|
|
@@ -1646,16 +1779,16 @@ async function getWhoisData(domain, timeout = 5e3) {
|
|
|
1646
1779
|
const referredServer = referMatch[1];
|
|
1647
1780
|
const whoisResponse2 = await queryWhoisServer(domain, referredServer, timeout);
|
|
1648
1781
|
const whoisData3 = parseWhoisData({ rawData: whoisResponse2, domain });
|
|
1649
|
-
|
|
1782
|
+
await cache.set(cacheKey, whoisData3);
|
|
1650
1783
|
return whoisData3;
|
|
1651
1784
|
}
|
|
1652
1785
|
const whoisData2 = parseWhoisData({ rawData: ianaResponse, domain });
|
|
1653
|
-
|
|
1786
|
+
await cache.set(cacheKey, whoisData2);
|
|
1654
1787
|
return whoisData2;
|
|
1655
1788
|
}
|
|
1656
1789
|
const whoisResponse = await queryWhoisServer(domain, whoisServer, timeout);
|
|
1657
1790
|
const whoisData = parseWhoisData({ rawData: whoisResponse, domain });
|
|
1658
|
-
|
|
1791
|
+
await cache.set(cacheKey, whoisData);
|
|
1659
1792
|
return whoisData;
|
|
1660
1793
|
} catch (_error) {
|
|
1661
1794
|
return null;
|
|
@@ -1756,7 +1889,7 @@ async function getDomainRegistrationStatus(domain, timeout = 5e3) {
|
|
|
1756
1889
|
}
|
|
1757
1890
|
|
|
1758
1891
|
async function verifyEmailBatch(params) {
|
|
1759
|
-
const { emailAddresses, concurrency = 5, timeout = 4e3, verifyMx = true, verifySmtp = false, checkDisposable = true, checkFree = true,
|
|
1892
|
+
const { emailAddresses, concurrency = 5, timeout = 4e3, verifyMx = true, verifySmtp = false, checkDisposable = true, checkFree = true, detectName = false, nameDetectionMethod, suggestDomain = false, domainSuggestionMethod, commonDomains, cache } = params;
|
|
1760
1893
|
const startTime = Date.now();
|
|
1761
1894
|
const results = /* @__PURE__ */ new Map();
|
|
1762
1895
|
const batches = [];
|
|
@@ -1769,7 +1902,7 @@ async function verifyEmailBatch(params) {
|
|
|
1769
1902
|
for (const batch of batches) {
|
|
1770
1903
|
const batchPromises = batch.map(async (email) => {
|
|
1771
1904
|
try {
|
|
1772
|
-
const result =
|
|
1905
|
+
const result = await verifyEmail({
|
|
1773
1906
|
emailAddress: email,
|
|
1774
1907
|
timeout,
|
|
1775
1908
|
verifyMx,
|
|
@@ -1780,39 +1913,20 @@ async function verifyEmailBatch(params) {
|
|
|
1780
1913
|
nameDetectionMethod,
|
|
1781
1914
|
suggestDomain,
|
|
1782
1915
|
domainSuggestionMethod,
|
|
1783
|
-
commonDomains
|
|
1784
|
-
|
|
1785
|
-
emailAddress: email,
|
|
1786
|
-
timeout,
|
|
1787
|
-
verifyMx,
|
|
1788
|
-
verifySmtp,
|
|
1789
|
-
detectName,
|
|
1790
|
-
nameDetectionMethod,
|
|
1791
|
-
suggestDomain,
|
|
1792
|
-
domainSuggestionMethod,
|
|
1793
|
-
commonDomains
|
|
1916
|
+
commonDomains,
|
|
1917
|
+
cache
|
|
1794
1918
|
});
|
|
1795
|
-
if (
|
|
1796
|
-
|
|
1797
|
-
if (detailedResult.valid) {
|
|
1798
|
-
totalValid++;
|
|
1799
|
-
} else {
|
|
1800
|
-
totalInvalid++;
|
|
1801
|
-
}
|
|
1919
|
+
if (result.valid) {
|
|
1920
|
+
totalValid++;
|
|
1802
1921
|
} else {
|
|
1803
|
-
|
|
1804
|
-
if (basicResult.validFormat && basicResult.validMx !== false) {
|
|
1805
|
-
totalValid++;
|
|
1806
|
-
} else {
|
|
1807
|
-
totalInvalid++;
|
|
1808
|
-
}
|
|
1922
|
+
totalInvalid++;
|
|
1809
1923
|
}
|
|
1810
1924
|
return { email, result };
|
|
1811
1925
|
} catch (error) {
|
|
1812
1926
|
totalErrors++;
|
|
1813
1927
|
return {
|
|
1814
1928
|
email,
|
|
1815
|
-
result:
|
|
1929
|
+
result: createErrorDetailedResult(email)
|
|
1816
1930
|
};
|
|
1817
1931
|
}
|
|
1818
1932
|
});
|
|
@@ -1850,38 +1964,56 @@ function createErrorDetailedResult(email, _error) {
|
|
|
1850
1964
|
|
|
1851
1965
|
let disposableEmailProviders;
|
|
1852
1966
|
let freeEmailProviders;
|
|
1853
|
-
function isDisposableEmail(emailOrDomain) {
|
|
1967
|
+
async function isDisposableEmail(emailOrDomain, cache) {
|
|
1854
1968
|
const parts = emailOrDomain.split("@");
|
|
1855
1969
|
const emailDomain = parts.length > 1 ? parts[1] : parts[0];
|
|
1856
1970
|
if (!emailDomain) {
|
|
1857
1971
|
return false;
|
|
1858
1972
|
}
|
|
1859
|
-
const
|
|
1860
|
-
|
|
1973
|
+
const cacheStore = disposableCacheStore(cache);
|
|
1974
|
+
let cached;
|
|
1975
|
+
try {
|
|
1976
|
+
cached = await cacheStore.get(emailDomain);
|
|
1977
|
+
} catch (_error) {
|
|
1978
|
+
cached = null;
|
|
1979
|
+
}
|
|
1980
|
+
if (cached !== null && cached !== void 0) {
|
|
1861
1981
|
return cached;
|
|
1862
1982
|
}
|
|
1863
1983
|
if (!disposableEmailProviders) {
|
|
1864
1984
|
disposableEmailProviders = new Set(require("./disposable-email-providers.json"));
|
|
1865
1985
|
}
|
|
1866
1986
|
const result = disposableEmailProviders.has(emailDomain);
|
|
1867
|
-
|
|
1987
|
+
try {
|
|
1988
|
+
await cacheStore.set(emailDomain, result);
|
|
1989
|
+
} catch (_error) {
|
|
1990
|
+
}
|
|
1868
1991
|
return result;
|
|
1869
1992
|
}
|
|
1870
|
-
function isFreeEmail(emailOrDomain) {
|
|
1993
|
+
async function isFreeEmail(emailOrDomain, cache) {
|
|
1871
1994
|
const parts = emailOrDomain.split("@");
|
|
1872
1995
|
const emailDomain = parts.length > 1 ? parts[1] : parts[0];
|
|
1873
1996
|
if (!emailDomain) {
|
|
1874
1997
|
return false;
|
|
1875
1998
|
}
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1999
|
+
const cacheStore = freeCacheStore(cache);
|
|
2000
|
+
let cached;
|
|
2001
|
+
try {
|
|
2002
|
+
cached = await cacheStore.get(emailDomain);
|
|
2003
|
+
} catch (_error) {
|
|
2004
|
+
cached = null;
|
|
2005
|
+
}
|
|
2006
|
+
if (cached !== null && cached !== void 0) {
|
|
1878
2007
|
return cached;
|
|
1879
2008
|
}
|
|
1880
2009
|
if (!freeEmailProviders) {
|
|
1881
2010
|
freeEmailProviders = new Set(require("./free-email-providers.json"));
|
|
1882
2011
|
}
|
|
1883
2012
|
const result = freeEmailProviders.has(emailDomain);
|
|
1884
|
-
|
|
2013
|
+
try {
|
|
2014
|
+
await cacheStore.set(emailDomain, result);
|
|
2015
|
+
} catch (_error) {
|
|
2016
|
+
}
|
|
1885
2017
|
return result;
|
|
1886
2018
|
}
|
|
1887
2019
|
const domainPorts = {
|
|
@@ -1890,103 +2022,6 @@ const domainPorts = {
|
|
|
1890
2022
|
"ovh.net": 465
|
|
1891
2023
|
};
|
|
1892
2024
|
async function verifyEmail(params) {
|
|
1893
|
-
const { emailAddress, timeout = 4e3, verifyMx = false, verifySmtp = false, debug = false, detectName: detectName2 = false, nameDetectionMethod, suggestDomain: suggestDomain2 = false, domainSuggestionMethod, commonDomains, checkDomainAge = false, checkDomainRegistration = false, whoisTimeout = 5e3 } = params;
|
|
1894
|
-
const result = { validFormat: false, validMx: null, validSmtp: null };
|
|
1895
|
-
const log = debug ? console.debug : (..._args) => {
|
|
1896
|
-
};
|
|
1897
|
-
let mxRecords;
|
|
1898
|
-
if (!isValidEmail(emailAddress)) {
|
|
1899
|
-
log("[verifyEmail] Failed on wellFormed check");
|
|
1900
|
-
return result;
|
|
1901
|
-
}
|
|
1902
|
-
const [local, domain] = emailAddress.split("@");
|
|
1903
|
-
if (!domain || !local) {
|
|
1904
|
-
log("[verifyEmail] Failed on wellFormed check");
|
|
1905
|
-
return result;
|
|
1906
|
-
}
|
|
1907
|
-
result.validFormat = true;
|
|
1908
|
-
if (detectName2) {
|
|
1909
|
-
result.detectedName = detectNameFromEmail({
|
|
1910
|
-
email: emailAddress,
|
|
1911
|
-
customMethod: nameDetectionMethod
|
|
1912
|
-
});
|
|
1913
|
-
}
|
|
1914
|
-
if (suggestDomain2) {
|
|
1915
|
-
const [, emailDomain] = emailAddress.split("@");
|
|
1916
|
-
if (emailDomain) {
|
|
1917
|
-
result.domainSuggestion = domainSuggestionMethod ? domainSuggestionMethod(emailDomain) : suggestEmailDomain(emailAddress, commonDomains);
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
if (checkDomainAge) {
|
|
1921
|
-
try {
|
|
1922
|
-
result.domainAge = await getDomainAge(domain, whoisTimeout);
|
|
1923
|
-
} catch (err) {
|
|
1924
|
-
log("[verifyEmail] Failed to get domain age", err);
|
|
1925
|
-
result.domainAge = null;
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
if (checkDomainRegistration) {
|
|
1929
|
-
try {
|
|
1930
|
-
result.domainRegistration = await getDomainRegistrationStatus(domain, whoisTimeout);
|
|
1931
|
-
} catch (err) {
|
|
1932
|
-
log("[verifyEmail] Failed to get domain registration status", err);
|
|
1933
|
-
result.domainRegistration = null;
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
if (!verifyMx && !verifySmtp)
|
|
1937
|
-
return result;
|
|
1938
|
-
try {
|
|
1939
|
-
mxRecords = await resolveMxRecords(domain);
|
|
1940
|
-
log("[verifyEmail] Found MX records", mxRecords);
|
|
1941
|
-
} catch (err) {
|
|
1942
|
-
log("[verifyEmail] Failed to resolve MX records", err);
|
|
1943
|
-
mxRecords = [];
|
|
1944
|
-
}
|
|
1945
|
-
if (verifyMx || verifySmtp) {
|
|
1946
|
-
result.validMx = mxRecords && mxRecords.length > 0;
|
|
1947
|
-
}
|
|
1948
|
-
if (verifySmtp && !(mxRecords === null || mxRecords === void 0 ? void 0 : mxRecords.length)) {
|
|
1949
|
-
result.validSmtp = false;
|
|
1950
|
-
}
|
|
1951
|
-
if (verifySmtp && (mxRecords === null || mxRecords === void 0 ? void 0 : mxRecords.length) > 0) {
|
|
1952
|
-
const cacheKey = `${emailAddress}:smtp`;
|
|
1953
|
-
const cachedSmtp = smtpCache.get(cacheKey);
|
|
1954
|
-
if (cachedSmtp !== void 0) {
|
|
1955
|
-
result.validSmtp = cachedSmtp;
|
|
1956
|
-
if (detectName2 && !result.detectedName) {
|
|
1957
|
-
result.detectedName = detectNameFromEmail({
|
|
1958
|
-
email: emailAddress,
|
|
1959
|
-
customMethod: nameDetectionMethod
|
|
1960
|
-
});
|
|
1961
|
-
}
|
|
1962
|
-
return result;
|
|
1963
|
-
}
|
|
1964
|
-
let domainPort = params.smtpPort;
|
|
1965
|
-
if (!domainPort) {
|
|
1966
|
-
const mxDomain = parse(mxRecords[0]);
|
|
1967
|
-
if ("domain" in mxDomain && mxDomain.domain) {
|
|
1968
|
-
domainPort = domainPorts[mxDomain.domain];
|
|
1969
|
-
log(`[verifyEmail] Found mxDomain ${mxDomain.domain} with port ${domainPort}`);
|
|
1970
|
-
}
|
|
1971
|
-
if ("error" in mxDomain) {
|
|
1972
|
-
log(`[verifyEmail] Failed to parse mxDomain ${mxDomain.error}`);
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
const smtpResult = await verifyMailboxSMTP({
|
|
1976
|
-
local,
|
|
1977
|
-
domain,
|
|
1978
|
-
mxRecords,
|
|
1979
|
-
timeout,
|
|
1980
|
-
debug,
|
|
1981
|
-
port: domainPort,
|
|
1982
|
-
retryAttempts: params.retryAttempts
|
|
1983
|
-
});
|
|
1984
|
-
smtpCache.set(cacheKey, smtpResult);
|
|
1985
|
-
result.validSmtp = smtpResult;
|
|
1986
|
-
}
|
|
1987
|
-
return result;
|
|
1988
|
-
}
|
|
1989
|
-
async function verifyEmailDetailed(params) {
|
|
1990
2025
|
const { emailAddress, timeout = 4e3, verifyMx = true, verifySmtp = false, debug = false, checkDisposable = true, checkFree = true, detectName: detectName2 = false, nameDetectionMethod, suggestDomain: suggestDomain2 = true, domainSuggestionMethod, commonDomains, checkDomainAge = false, checkDomainRegistration = false, whoisTimeout = 5e3 } = params;
|
|
1991
2026
|
const startTime = Date.now();
|
|
1992
2027
|
const log = debug ? console.debug : (..._args) => {
|
|
@@ -2021,7 +2056,7 @@ async function verifyEmailDetailed(params) {
|
|
|
2021
2056
|
if (suggestDomain2) {
|
|
2022
2057
|
const [, emailDomain] = emailAddress.split("@");
|
|
2023
2058
|
if (emailDomain) {
|
|
2024
|
-
result.domainSuggestion = domainSuggestionMethod ? domainSuggestionMethod(emailDomain) : suggestEmailDomain(emailAddress, commonDomains);
|
|
2059
|
+
result.domainSuggestion = domainSuggestionMethod ? domainSuggestionMethod(emailDomain) : await suggestEmailDomain(emailAddress, commonDomains);
|
|
2025
2060
|
}
|
|
2026
2061
|
}
|
|
2027
2062
|
const [local, domain] = emailAddress.split("@");
|
|
@@ -2032,7 +2067,7 @@ async function verifyEmailDetailed(params) {
|
|
|
2032
2067
|
}
|
|
2033
2068
|
return result;
|
|
2034
2069
|
}
|
|
2035
|
-
if (!isValidEmailDomain(domain)) {
|
|
2070
|
+
if (!await isValidEmailDomain(domain, params.cache)) {
|
|
2036
2071
|
result.domain.error = VerificationErrorCode.INVALID_DOMAIN;
|
|
2037
2072
|
if (result.metadata) {
|
|
2038
2073
|
result.metadata.verificationTime = Date.now() - startTime;
|
|
@@ -2040,14 +2075,14 @@ async function verifyEmailDetailed(params) {
|
|
|
2040
2075
|
return result;
|
|
2041
2076
|
}
|
|
2042
2077
|
if (checkDisposable) {
|
|
2043
|
-
result.disposable = isDisposableEmail(emailAddress);
|
|
2078
|
+
result.disposable = await isDisposableEmail(emailAddress, params.cache);
|
|
2044
2079
|
if (result.disposable) {
|
|
2045
2080
|
result.valid = false;
|
|
2046
2081
|
result.domain.error = VerificationErrorCode.DISPOSABLE_EMAIL;
|
|
2047
2082
|
}
|
|
2048
2083
|
}
|
|
2049
2084
|
if (checkFree) {
|
|
2050
|
-
result.freeProvider = isFreeEmail(emailAddress);
|
|
2085
|
+
result.freeProvider = await isFreeEmail(emailAddress, params.cache);
|
|
2051
2086
|
}
|
|
2052
2087
|
if (checkDomainAge) {
|
|
2053
2088
|
try {
|
|
@@ -2067,7 +2102,7 @@ async function verifyEmailDetailed(params) {
|
|
|
2067
2102
|
}
|
|
2068
2103
|
if (verifyMx || verifySmtp) {
|
|
2069
2104
|
try {
|
|
2070
|
-
const mxRecords = await resolveMxRecords(domain);
|
|
2105
|
+
const mxRecords = await resolveMxRecords(domain, params.cache);
|
|
2071
2106
|
result.domain.mxRecords = mxRecords;
|
|
2072
2107
|
result.domain.valid = mxRecords.length > 0;
|
|
2073
2108
|
if (!result.domain.valid) {
|
|
@@ -2075,8 +2110,9 @@ async function verifyEmailDetailed(params) {
|
|
|
2075
2110
|
}
|
|
2076
2111
|
if (verifySmtp && mxRecords.length > 0) {
|
|
2077
2112
|
const cacheKey = `${emailAddress}:smtp`;
|
|
2078
|
-
const
|
|
2079
|
-
|
|
2113
|
+
const smtpCacheInstance = smtpCacheStore(params.cache);
|
|
2114
|
+
const cachedSmtp = await smtpCacheInstance.get(cacheKey);
|
|
2115
|
+
if (cachedSmtp !== null && cachedSmtp !== void 0) {
|
|
2080
2116
|
result.smtp.valid = cachedSmtp;
|
|
2081
2117
|
if (result.metadata) {
|
|
2082
2118
|
result.metadata.cached = true;
|
|
@@ -2104,7 +2140,7 @@ async function verifyEmailDetailed(params) {
|
|
|
2104
2140
|
port: domainPort,
|
|
2105
2141
|
retryAttempts: params.retryAttempts
|
|
2106
2142
|
});
|
|
2107
|
-
|
|
2143
|
+
await smtpCacheInstance.set(cacheKey, smtpResult);
|
|
2108
2144
|
result.smtp.valid = smtpResult;
|
|
2109
2145
|
}
|
|
2110
2146
|
if (result.smtp.valid === false) {
|
|
@@ -2126,5 +2162,5 @@ async function verifyEmailDetailed(params) {
|
|
|
2126
2162
|
return result;
|
|
2127
2163
|
}
|
|
2128
2164
|
|
|
2129
|
-
export { COMMON_EMAIL_DOMAINS, VerificationErrorCode, clearAllCaches, defaultDomainSuggestionMethod, defaultNameDetectionMethod, detectName, detectNameFromEmail, domainPorts, getDomainAge, getDomainRegistrationStatus, getDomainSimilarity, isCommonDomain, isDisposableEmail, isFreeEmail, isValidEmail, isValidEmailDomain, suggestDomain, suggestEmailDomain, verifyEmail, verifyEmailBatch
|
|
2165
|
+
export { COMMON_EMAIL_DOMAINS, VerificationErrorCode, clearAllCaches, defaultDomainSuggestionMethod, defaultNameDetectionMethod, detectName, detectNameFromEmail, domainPorts, getDomainAge, getDomainRegistrationStatus, getDomainSimilarity, isCommonDomain, isDisposableEmail, isFreeEmail, isValidEmail, isValidEmailDomain, suggestDomain, suggestEmailDomain, verifyEmail, verifyEmailBatch };
|
|
2130
2166
|
//# sourceMappingURL=index.esm.js.map
|