@emailcheck/email-validator-js 2.13.1-beta.1 → 2.13.1-beta.3

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/index.js CHANGED
@@ -1734,37 +1734,50 @@ const WHOIS_SERVERS = {
1734
1734
  ar: "whois.nic.ar",
1735
1735
  cl: "whois.nic.cl"
1736
1736
  };
1737
- function queryWhoisServer(domain, server, timeout = 5e3) {
1737
+ function queryWhoisServer(domain, server, timeout = 5e3, debug = false) {
1738
+ const log = debug ? console.debug : (..._args) => {
1739
+ };
1738
1740
  return new Promise((resolve, reject) => {
1739
1741
  const client = new net.Socket();
1740
1742
  let data = "";
1743
+ log(`[whois] querying ${server} for domain ${domain}`);
1741
1744
  const timer = setTimeout(() => {
1745
+ log(`[whois] timeout after ${timeout}ms for ${domain} at ${server}`);
1742
1746
  client.destroy();
1743
1747
  reject(new Error("WHOIS query timeout"));
1744
1748
  }, timeout);
1745
1749
  client.connect(43, server, () => {
1750
+ log(`[whois] connected to ${server}, sending query for ${domain}`);
1746
1751
  client.write(`${domain}\r
1747
1752
  `);
1748
1753
  });
1749
1754
  client.on("data", (chunk) => {
1750
- data += chunk.toString();
1755
+ const chunkStr = chunk.toString();
1756
+ data += chunkStr;
1757
+ log(`[whois] received ${chunkStr.length} bytes from ${server}`);
1751
1758
  });
1752
1759
  client.on("close", () => {
1753
1760
  clearTimeout(timer);
1761
+ log(`[whois] connection closed, received total ${data.length} bytes from ${server}`);
1754
1762
  resolve(data);
1755
1763
  });
1756
1764
  client.on("error", (err) => {
1757
1765
  clearTimeout(timer);
1766
+ log(`[whois] error querying ${server}: ${err.message}`);
1758
1767
  reject(err);
1759
1768
  });
1760
1769
  });
1761
1770
  }
1762
- async function getWhoisData(domain, timeout = 5e3) {
1771
+ async function getWhoisData(domain, timeout = 5e3, debug = false) {
1763
1772
  var _a;
1773
+ const log = debug ? console.debug : (..._args) => {
1774
+ };
1764
1775
  const cacheKey = `whois:${domain}`;
1765
1776
  const cache = whoisCacheStore();
1777
+ log(`[whois] getting WHOIS data for ${domain}`);
1766
1778
  const cached = await cache.get(cacheKey);
1767
1779
  if (cached !== null && cached !== void 0) {
1780
+ log(`[whois] using cached data for ${domain}`);
1768
1781
  return cached;
1769
1782
  }
1770
1783
  try {
@@ -1772,41 +1785,55 @@ async function getWhoisData(domain, timeout = 5e3) {
1772
1785
  if (!tld) {
1773
1786
  throw new Error("Invalid domain");
1774
1787
  }
1788
+ log(`[whois] extracted TLD: ${tld} for domain: ${domain}`);
1775
1789
  const whoisServer = WHOIS_SERVERS[tld];
1776
1790
  if (!whoisServer) {
1791
+ log(`[whois] no specific server for TLD ${tld}, trying IANA`);
1777
1792
  const defaultServer = "whois.iana.org";
1778
- const ianaResponse = await queryWhoisServer(domain, defaultServer, timeout);
1793
+ const ianaResponse = await queryWhoisServer(domain, defaultServer, timeout, debug);
1779
1794
  const referMatch = ianaResponse.match(/refer:\s+(\S+)/i);
1780
1795
  if (referMatch === null || referMatch === void 0 ? void 0 : referMatch[1]) {
1781
1796
  const referredServer = referMatch[1];
1782
- const whoisResponse2 = await queryWhoisServer(domain, referredServer, timeout);
1797
+ log(`[whois] IANA referred to ${referredServer} for ${domain}`);
1798
+ const whoisResponse2 = await queryWhoisServer(domain, referredServer, timeout, debug);
1783
1799
  const whoisData3 = parseWhoisData({ rawData: whoisResponse2, domain });
1784
1800
  await cache.set(cacheKey, whoisData3);
1801
+ log(`[whois] successfully retrieved and cached WHOIS data from referred server for ${domain}`);
1785
1802
  return whoisData3;
1786
1803
  }
1787
1804
  const whoisData2 = parseWhoisData({ rawData: ianaResponse, domain });
1788
1805
  await cache.set(cacheKey, whoisData2);
1806
+ log(`[whois] successfully retrieved and cached WHOIS data from IANA for ${domain}`);
1789
1807
  return whoisData2;
1790
1808
  }
1791
- const whoisResponse = await queryWhoisServer(domain, whoisServer, timeout);
1809
+ log(`[whois] using WHOIS server ${whoisServer} for TLD ${tld}`);
1810
+ const whoisResponse = await queryWhoisServer(domain, whoisServer, timeout, debug);
1792
1811
  const whoisData = parseWhoisData({ rawData: whoisResponse, domain });
1793
1812
  await cache.set(cacheKey, whoisData);
1813
+ log(`[whois] successfully retrieved and cached WHOIS data for ${domain}`);
1794
1814
  return whoisData;
1795
1815
  } catch (_error) {
1816
+ log(`[whois] failed to get WHOIS data for ${domain}: ${_error instanceof Error ? _error.message : "Unknown error"}`);
1796
1817
  return null;
1797
1818
  }
1798
1819
  }
1799
- async function getDomainAge(domain, timeout = 5e3) {
1820
+ async function getDomainAge(domain, timeout = 5e3, debug = false) {
1821
+ const log = debug ? console.debug : (..._args) => {
1822
+ };
1800
1823
  try {
1801
1824
  const cleanDomain = domain.replace(/^https?:\/\//, "").split("/")[0].split("@").pop();
1802
1825
  if (!cleanDomain) {
1826
+ log(`[whois] invalid domain format: ${domain}`);
1803
1827
  return null;
1804
1828
  }
1829
+ log(`[whois] checking domain age for ${cleanDomain}`);
1805
1830
  if (!psl.isValid(cleanDomain)) {
1831
+ log(`[whois] domain validation failed: ${cleanDomain}`);
1806
1832
  return null;
1807
1833
  }
1808
- const whoisData = await getWhoisData(cleanDomain, timeout);
1834
+ const whoisData = await getWhoisData(cleanDomain, timeout, debug);
1809
1835
  if (!whoisData || !whoisData.creationDate) {
1836
+ log(`[whois] no creation date found for ${cleanDomain}`);
1810
1837
  return null;
1811
1838
  }
1812
1839
  const now = /* @__PURE__ */ new Date();
@@ -1814,6 +1841,7 @@ async function getDomainAge(domain, timeout = 5e3) {
1814
1841
  const ageInMilliseconds = now.getTime() - creationDate.getTime();
1815
1842
  const ageInDays = Math.floor(ageInMilliseconds / (1e3 * 60 * 60 * 24));
1816
1843
  const ageInYears = ageInDays / 365.25;
1844
+ log(`[whois] calculated age for ${cleanDomain}: ${ageInDays} days (${ageInYears.toFixed(2)} years)`);
1817
1845
  return {
1818
1846
  domain: cleanDomain,
1819
1847
  creationDate,
@@ -1823,20 +1851,27 @@ async function getDomainAge(domain, timeout = 5e3) {
1823
1851
  updatedDate: whoisData.updatedDate ? new Date(whoisData.updatedDate) : null
1824
1852
  };
1825
1853
  } catch (_error) {
1854
+ log(`[whois] error getting domain age for ${domain}: ${_error instanceof Error ? _error.message : "Unknown error"}`);
1826
1855
  return null;
1827
1856
  }
1828
1857
  }
1829
- async function getDomainRegistrationStatus(domain, timeout = 5e3) {
1858
+ async function getDomainRegistrationStatus(domain, timeout = 5e3, debug = false) {
1859
+ const log = debug ? console.debug : (..._args) => {
1860
+ };
1830
1861
  try {
1831
1862
  const cleanDomain = domain.replace(/^https?:\/\//, "").split("/")[0].split("@").pop();
1832
1863
  if (!cleanDomain) {
1864
+ log(`[whois] invalid domain format: ${domain}`);
1833
1865
  return null;
1834
1866
  }
1867
+ log(`[whois] checking domain registration status for ${cleanDomain}`);
1835
1868
  if (!psl.isValid(cleanDomain)) {
1869
+ log(`[whois] domain validation failed: ${cleanDomain}`);
1836
1870
  return null;
1837
1871
  }
1838
- const whoisData = await getWhoisData(cleanDomain, timeout);
1872
+ const whoisData = await getWhoisData(cleanDomain, timeout, debug);
1839
1873
  if (!whoisData || whoisData.isAvailable) {
1874
+ log(`[whois] domain ${cleanDomain} is available or not registered`);
1840
1875
  return {
1841
1876
  domain: cleanDomain,
1842
1877
  isRegistered: false,
@@ -1864,6 +1899,7 @@ async function getDomainRegistrationStatus(domain, timeout = 5e3) {
1864
1899
  if (!isExpired) {
1865
1900
  daysUntilExpiration = Math.floor((expirationTime - currentTime) / (1e3 * 60 * 60 * 24));
1866
1901
  }
1902
+ log(`[whois] domain ${cleanDomain} expires in ${daysUntilExpiration} days`);
1867
1903
  }
1868
1904
  const statusList = whoisData.status || [];
1869
1905
  const formattedStatusList = statusList.map((s) => {
@@ -1872,6 +1908,7 @@ async function getDomainRegistrationStatus(domain, timeout = 5e3) {
1872
1908
  });
1873
1909
  const isPendingDelete = formattedStatusList.some((s) => s.toLowerCase().includes("pendingdelete") || s.toLowerCase().includes("redemption"));
1874
1910
  const isLocked = formattedStatusList.some((s) => s.toLowerCase().includes("clienttransferprohibited") || s.toLowerCase().includes("servertransferprohibited"));
1911
+ log(`[whois] domain ${cleanDomain} - registered: ${isRegistered}, expired: ${isExpired}, locked: ${isLocked}, pending delete: ${isPendingDelete}`);
1875
1912
  return {
1876
1913
  domain: cleanDomain,
1877
1914
  isRegistered,
@@ -1886,12 +1923,13 @@ async function getDomainRegistrationStatus(domain, timeout = 5e3) {
1886
1923
  isLocked
1887
1924
  };
1888
1925
  } catch (_error) {
1926
+ log(`[whois] error getting domain registration status for ${domain}: ${_error instanceof Error ? _error.message : "Unknown error"}`);
1889
1927
  return null;
1890
1928
  }
1891
1929
  }
1892
1930
 
1893
1931
  async function verifyEmailBatch(params) {
1894
- const { emailAddresses, concurrency = 5, timeout = 4e3, verifyMx = true, verifySmtp = false, checkDisposable = true, checkFree = true, detectName = false, nameDetectionMethod, suggestDomain = false, domainSuggestionMethod, commonDomains, cache } = params;
1932
+ const { emailAddresses, concurrency = 5, timeout = 4e3, verifyMx = true, verifySmtp = false, checkDisposable = true, checkFree = true, detectName = false, nameDetectionMethod, suggestDomain = false, domainSuggestionMethod, commonDomains, skipMxForDisposable = false, skipDomainWhoisForDisposable = false, cache } = params;
1895
1933
  const startTime = Date.now();
1896
1934
  const results = /* @__PURE__ */ new Map();
1897
1935
  const batches = [];
@@ -1916,9 +1954,11 @@ async function verifyEmailBatch(params) {
1916
1954
  suggestDomain,
1917
1955
  domainSuggestionMethod,
1918
1956
  commonDomains,
1957
+ skipMxForDisposable,
1958
+ skipDomainWhoisForDisposable,
1919
1959
  cache
1920
1960
  });
1921
- if (result.valid) {
1961
+ if (result.validFormat) {
1922
1962
  totalValid++;
1923
1963
  } else {
1924
1964
  totalInvalid++;
@@ -1928,7 +1968,7 @@ async function verifyEmailBatch(params) {
1928
1968
  totalErrors++;
1929
1969
  return {
1930
1970
  email,
1931
- result: createErrorDetailedResult(email)
1971
+ result: createErrorResult(email)
1932
1972
  };
1933
1973
  }
1934
1974
  });
@@ -1948,18 +1988,18 @@ async function verifyEmailBatch(params) {
1948
1988
  }
1949
1989
  };
1950
1990
  }
1951
- function createErrorDetailedResult(email, _error) {
1991
+ function createErrorResult(email, _error) {
1952
1992
  return {
1953
- valid: false,
1954
1993
  email,
1955
- format: { valid: false },
1956
- domain: { valid: null },
1957
- smtp: { valid: null },
1958
- disposable: false,
1959
- freeProvider: false,
1994
+ validFormat: false,
1995
+ validMx: null,
1996
+ validSmtp: null,
1997
+ isDisposable: false,
1998
+ isFree: false,
1960
1999
  metadata: {
1961
2000
  verificationTime: 0,
1962
- cached: false
2001
+ cached: false,
2002
+ error: exports.VerificationErrorCode.SMTP_CONNECTION_FAILED
1963
2003
  }
1964
2004
  };
1965
2005
  }
@@ -2024,31 +2064,30 @@ const domainPorts = {
2024
2064
  "ovh.net": 465
2025
2065
  };
2026
2066
  async function verifyEmail(params) {
2027
- 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;
2067
+ 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, skipMxForDisposable = false, skipDomainWhoisForDisposable = false } = params;
2028
2068
  const startTime = Date.now();
2029
2069
  const log = debug ? console.debug : (..._args) => {
2030
2070
  };
2031
2071
  const result = {
2032
- valid: false,
2033
2072
  email: emailAddress,
2034
- format: { valid: false },
2035
- domain: { valid: null },
2036
- smtp: { valid: null },
2037
- disposable: false,
2038
- freeProvider: false,
2073
+ validFormat: false,
2074
+ validMx: null,
2075
+ validSmtp: null,
2076
+ isDisposable: false,
2077
+ isFree: false,
2039
2078
  metadata: {
2040
2079
  verificationTime: 0,
2041
2080
  cached: false
2042
2081
  }
2043
2082
  };
2044
2083
  if (!isValidEmail(emailAddress)) {
2045
- result.format.error = exports.VerificationErrorCode.INVALID_FORMAT;
2046
2084
  if (result.metadata) {
2047
2085
  result.metadata.verificationTime = Date.now() - startTime;
2086
+ result.metadata.error = exports.VerificationErrorCode.INVALID_FORMAT;
2048
2087
  }
2049
2088
  return result;
2050
2089
  }
2051
- result.format.valid = true;
2090
+ result.validFormat = true;
2052
2091
  if (detectName2) {
2053
2092
  result.detectedName = detectNameFromEmail({
2054
2093
  email: emailAddress,
@@ -2058,64 +2097,69 @@ async function verifyEmail(params) {
2058
2097
  if (suggestDomain2) {
2059
2098
  const [, emailDomain] = emailAddress.split("@");
2060
2099
  if (emailDomain) {
2061
- result.domainSuggestion = domainSuggestionMethod ? domainSuggestionMethod(emailDomain) : await suggestEmailDomain(emailAddress, commonDomains);
2100
+ const suggestion = domainSuggestionMethod ? domainSuggestionMethod(emailDomain) : await suggestEmailDomain(emailAddress, commonDomains);
2101
+ if (suggestion) {
2102
+ result.domainSuggestion = suggestion;
2103
+ } else {
2104
+ result.domainSuggestion = null;
2105
+ }
2062
2106
  }
2063
2107
  }
2064
2108
  const [local, domain] = emailAddress.split("@");
2065
2109
  if (!domain || !local) {
2066
- result.format.error = exports.VerificationErrorCode.INVALID_FORMAT;
2067
2110
  if (result.metadata) {
2068
2111
  result.metadata.verificationTime = Date.now() - startTime;
2112
+ result.metadata.error = exports.VerificationErrorCode.INVALID_FORMAT;
2069
2113
  }
2070
2114
  return result;
2071
2115
  }
2072
2116
  if (!await isValidEmailDomain(domain, params.cache)) {
2073
- result.domain.error = exports.VerificationErrorCode.INVALID_DOMAIN;
2074
2117
  if (result.metadata) {
2075
2118
  result.metadata.verificationTime = Date.now() - startTime;
2119
+ result.metadata.error = exports.VerificationErrorCode.INVALID_DOMAIN;
2076
2120
  }
2077
2121
  return result;
2078
2122
  }
2079
2123
  if (checkDisposable) {
2080
- result.disposable = await isDisposableEmail(emailAddress, params.cache);
2081
- if (result.disposable) {
2082
- result.valid = false;
2083
- result.domain.error = exports.VerificationErrorCode.DISPOSABLE_EMAIL;
2124
+ result.isDisposable = await isDisposableEmail(emailAddress, params.cache);
2125
+ if (result.isDisposable && result.metadata) {
2126
+ result.metadata.error = exports.VerificationErrorCode.DISPOSABLE_EMAIL;
2084
2127
  }
2085
2128
  }
2086
2129
  if (checkFree) {
2087
- result.freeProvider = await isFreeEmail(emailAddress, params.cache);
2130
+ result.isFree = await isFreeEmail(emailAddress, params.cache);
2088
2131
  }
2089
- if (checkDomainAge) {
2132
+ const shouldSkipMx = skipMxForDisposable && result.isDisposable;
2133
+ const shouldSkipDomainWhois = skipDomainWhoisForDisposable && result.isDisposable;
2134
+ if (checkDomainAge && !shouldSkipDomainWhois) {
2090
2135
  try {
2091
- result.domainAge = await getDomainAge(domain, whoisTimeout);
2136
+ result.domainAge = await getDomainAge(domain, whoisTimeout, debug);
2092
2137
  } catch (err) {
2093
- log("[verifyEmailDetailed] Failed to get domain age", err);
2138
+ log("[verifyEmail] Failed to get domain age", err);
2094
2139
  result.domainAge = null;
2095
2140
  }
2096
2141
  }
2097
- if (checkDomainRegistration) {
2142
+ if (checkDomainRegistration && !shouldSkipDomainWhois) {
2098
2143
  try {
2099
- result.domainRegistration = await getDomainRegistrationStatus(domain, whoisTimeout);
2144
+ result.domainRegistration = await getDomainRegistrationStatus(domain, whoisTimeout, debug);
2100
2145
  } catch (err) {
2101
- log("[verifyEmailDetailed] Failed to get domain registration status", err);
2146
+ log("[verifyEmail] Failed to get domain registration status", err);
2102
2147
  result.domainRegistration = null;
2103
2148
  }
2104
2149
  }
2105
- if (verifyMx || verifySmtp) {
2150
+ if ((verifyMx || verifySmtp) && !shouldSkipMx) {
2106
2151
  try {
2107
2152
  const mxRecords = await resolveMxRecords(domain, params.cache);
2108
- result.domain.mxRecords = mxRecords;
2109
- result.domain.valid = mxRecords.length > 0;
2110
- if (!result.domain.valid) {
2111
- result.domain.error = exports.VerificationErrorCode.NO_MX_RECORDS;
2153
+ result.validMx = mxRecords.length > 0;
2154
+ if (!result.validMx && result.metadata) {
2155
+ result.metadata.error = exports.VerificationErrorCode.NO_MX_RECORDS;
2112
2156
  }
2113
2157
  if (verifySmtp && mxRecords.length > 0) {
2114
2158
  const cacheKey = `${emailAddress}:smtp`;
2115
2159
  const smtpCacheInstance = smtpCacheStore(params.cache);
2116
2160
  const cachedSmtp = await smtpCacheInstance.get(cacheKey);
2117
2161
  if (cachedSmtp !== null && cachedSmtp !== void 0) {
2118
- result.smtp.valid = cachedSmtp;
2162
+ result.validSmtp = cachedSmtp;
2119
2163
  if (result.metadata) {
2120
2164
  result.metadata.cached = true;
2121
2165
  }
@@ -2143,21 +2187,22 @@ async function verifyEmail(params) {
2143
2187
  retryAttempts: params.retryAttempts
2144
2188
  });
2145
2189
  await smtpCacheInstance.set(cacheKey, smtpResult);
2146
- result.smtp.valid = smtpResult;
2190
+ result.validSmtp = smtpResult;
2147
2191
  }
2148
- if (result.smtp.valid === false) {
2149
- result.smtp.error = exports.VerificationErrorCode.MAILBOX_NOT_FOUND;
2150
- } else if (result.smtp.valid === null) {
2151
- result.smtp.error = exports.VerificationErrorCode.SMTP_CONNECTION_FAILED;
2192
+ if (result.validSmtp === false && result.metadata) {
2193
+ result.metadata.error = exports.VerificationErrorCode.MAILBOX_NOT_FOUND;
2194
+ } else if (result.validSmtp === null && result.metadata) {
2195
+ result.metadata.error = exports.VerificationErrorCode.SMTP_CONNECTION_FAILED;
2152
2196
  }
2153
2197
  }
2154
2198
  } catch (err) {
2155
- log("[verifyEmailDetailed] Failed to resolve MX records", err);
2156
- result.domain.valid = false;
2157
- result.domain.error = exports.VerificationErrorCode.NO_MX_RECORDS;
2199
+ log("[verifyEmail] Failed to resolve MX records", err);
2200
+ result.validMx = false;
2201
+ if (result.metadata) {
2202
+ result.metadata.error = exports.VerificationErrorCode.NO_MX_RECORDS;
2203
+ }
2158
2204
  }
2159
2205
  }
2160
- result.valid = result.format.valid && result.domain.valid !== false && result.smtp.valid !== false && !result.disposable;
2161
2206
  if (result.metadata) {
2162
2207
  result.metadata.verificationTime = Date.now() - startTime;
2163
2208
  }