@rpcbase/server 0.617.0 → 0.619.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/dist/{email-CK8NNDQY.js → email-B7QOOLlZ.js} +21 -26
- package/dist/email-B7QOOLlZ.js.map +1 -0
- package/dist/email-validation/index.d.ts +34 -0
- package/dist/email-validation/index.d.ts.map +1 -0
- package/dist/email-validation/index.js +174 -0
- package/dist/email-validation/index.js.map +1 -0
- package/dist/email.d.ts +2 -1
- package/dist/email.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/node-yVzWCUin.js +56399 -0
- package/dist/node-yVzWCUin.js.map +1 -0
- package/dist/notifications.js +1 -1
- package/dist/rolldown-runtime-FDOR9p9I.js +24 -0
- package/package.json +7 -1
- package/dist/email-CK8NNDQY.js.map +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const DISPOSABLE_EMAIL_ERROR_CODE = "disposable_email";
|
|
2
|
+
export declare const INVALID_EMAIL_DOMAIN_ERROR_CODE = "invalid_email_domain";
|
|
3
|
+
export type EmailAddressValidationErrorCode = typeof DISPOSABLE_EMAIL_ERROR_CODE | typeof INVALID_EMAIL_DOMAIN_ERROR_CODE;
|
|
4
|
+
export type EmailDomainResolver = {
|
|
5
|
+
resolveMx(hostname: string): Promise<Array<{
|
|
6
|
+
exchange: string;
|
|
7
|
+
priority: number;
|
|
8
|
+
}>>;
|
|
9
|
+
resolve4(hostname: string): Promise<string[]>;
|
|
10
|
+
resolve6(hostname: string): Promise<string[]>;
|
|
11
|
+
};
|
|
12
|
+
export type EmailDomainValidationResult = {
|
|
13
|
+
status: "valid";
|
|
14
|
+
domain: string;
|
|
15
|
+
reason: "mx" | "implicit_mx";
|
|
16
|
+
} | {
|
|
17
|
+
status: "invalid";
|
|
18
|
+
domain?: string;
|
|
19
|
+
reason: "invalid_domain" | "null_mx" | "unresolvable_mx" | "no_mail_records";
|
|
20
|
+
} | {
|
|
21
|
+
status: "unknown";
|
|
22
|
+
domain: string;
|
|
23
|
+
reason: "dns_error";
|
|
24
|
+
};
|
|
25
|
+
export type ValidateEmailDomainOptions = {
|
|
26
|
+
resolver?: EmailDomainResolver;
|
|
27
|
+
useCache?: boolean;
|
|
28
|
+
};
|
|
29
|
+
export declare const getEmailAddressDomain: (email: unknown) => string | undefined;
|
|
30
|
+
export declare const clearEmailDomainValidationCache: () => void;
|
|
31
|
+
export declare const validateEmailDomain: (email: unknown, options?: ValidateEmailDomainOptions) => Promise<EmailDomainValidationResult>;
|
|
32
|
+
export declare const getEmailAddressValidationErrorCode: (email: unknown, options?: ValidateEmailDomainOptions) => Promise<EmailAddressValidationErrorCode | undefined>;
|
|
33
|
+
export declare const isEmailAddressValid: (email: unknown, options?: ValidateEmailDomainOptions) => Promise<boolean>;
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/email-validation/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,2BAA2B,qBAAqB,CAAA;AAC7D,eAAO,MAAM,+BAA+B,yBAAyB,CAAA;AAErE,MAAM,MAAM,+BAA+B,GACvC,OAAO,2BAA2B,GAClC,OAAO,+BAA+B,CAAA;AAE1C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAC9C,CAAA;AAED,MAAM,MAAM,2BAA2B,GACnC;IACA,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,IAAI,GAAG,aAAa,CAAA;CAC7B,GACC;IACA,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,gBAAgB,GAAG,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;CAC7E,GACC;IACA,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AAEH,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AA+CD,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAoB/D,CAAA;AAoED,eAAO,MAAM,+BAA+B,QAAO,IAGlD,CAAA;AAED,eAAO,MAAM,mBAAmB,GAC9B,OAAO,OAAO,EACd,UAAS,0BAA+B,KACvC,OAAO,CAAC,2BAA2B,CAgCrC,CAAA;AAoBD,eAAO,MAAM,kCAAkC,GAC7C,OAAO,OAAO,EACd,UAAS,0BAA+B,KACvC,OAAO,CAAC,+BAA+B,GAAG,SAAS,CAKrD,CAAA;AAED,eAAO,MAAM,mBAAmB,GAC9B,OAAO,OAAO,EACd,UAAS,0BAA+B,KACvC,OAAO,CAAC,OAAO,CAA6E,CAAA"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { n as __toESM } from "../rolldown-runtime-FDOR9p9I.js";
|
|
2
|
+
import { domainToASCII } from "node:url";
|
|
3
|
+
import { resolve4, resolve6, resolveMx } from "node:dns/promises";
|
|
4
|
+
//#region src/email-validation/index.ts
|
|
5
|
+
var DISPOSABLE_EMAIL_ERROR_CODE = "disposable_email";
|
|
6
|
+
var INVALID_EMAIL_DOMAIN_ERROR_CODE = "invalid_email_domain";
|
|
7
|
+
var VALID_CACHE_TTL_MS = 600 * 1e3;
|
|
8
|
+
var INVALID_CACHE_TTL_MS = 300 * 1e3;
|
|
9
|
+
var UNKNOWN_CACHE_TTL_MS = 30 * 1e3;
|
|
10
|
+
var nativeResolver = {
|
|
11
|
+
resolveMx: (hostname) => resolveMx(hostname),
|
|
12
|
+
resolve4: (hostname) => resolve4(hostname),
|
|
13
|
+
resolve6: (hostname) => resolve6(hostname)
|
|
14
|
+
};
|
|
15
|
+
var emailDomainValidationCache = /* @__PURE__ */ new Map();
|
|
16
|
+
var pendingEmailDomainValidations = /* @__PURE__ */ new Map();
|
|
17
|
+
var disposableEmailDomainsPromise;
|
|
18
|
+
var getDisposableEmailDomains = () => {
|
|
19
|
+
disposableEmailDomainsPromise ??= import("../node-yVzWCUin.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then(({ default: MailChecker }) => MailChecker.blacklist());
|
|
20
|
+
return disposableEmailDomainsPromise;
|
|
21
|
+
};
|
|
22
|
+
var getDnsErrorCode = (error) => {
|
|
23
|
+
if (!error || typeof error !== "object" || !("code" in error)) return void 0;
|
|
24
|
+
return typeof error.code === "string" ? error.code : void 0;
|
|
25
|
+
};
|
|
26
|
+
var isMissingDnsRecordError = (error) => {
|
|
27
|
+
const code = getDnsErrorCode(error);
|
|
28
|
+
return code === "ENODATA" || code === "ENOTFOUND" || code === "EBADNAME";
|
|
29
|
+
};
|
|
30
|
+
var getMailbox = (value) => {
|
|
31
|
+
const trimmed = value.trim();
|
|
32
|
+
return (trimmed.match(/<([^<>]+)>$/)?.[1] ?? trimmed).trim();
|
|
33
|
+
};
|
|
34
|
+
var getEmailAddressDomain = (email) => {
|
|
35
|
+
if (typeof email !== "string") return void 0;
|
|
36
|
+
const mailbox = getMailbox(email);
|
|
37
|
+
const atIndex = mailbox.lastIndexOf("@");
|
|
38
|
+
if (atIndex <= 0 || atIndex === mailbox.length - 1) return void 0;
|
|
39
|
+
const domain = mailbox.slice(atIndex + 1).toLowerCase();
|
|
40
|
+
if (!domain || /\s/.test(domain) || domain.includes("@") || domain.includes("[") || domain.includes("]") || domain.includes("<") || domain.includes(">")) return void 0;
|
|
41
|
+
return domainToASCII(domain) || void 0;
|
|
42
|
+
};
|
|
43
|
+
var resolveAddressRecords = async (hostname, resolver) => {
|
|
44
|
+
const results = await Promise.allSettled([resolver.resolve4(hostname), resolver.resolve6(hostname)]);
|
|
45
|
+
if (results.some((result) => result.status === "fulfilled" && result.value.length > 0)) return "resolved";
|
|
46
|
+
return results.filter((result) => result.status === "rejected").map((result) => result.reason).every(isMissingDnsRecordError) ? "missing" : "unknown";
|
|
47
|
+
};
|
|
48
|
+
var validateWithoutCache = async (domain, resolver) => {
|
|
49
|
+
let mxRecords;
|
|
50
|
+
try {
|
|
51
|
+
mxRecords = await resolver.resolveMx(domain);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (!isMissingDnsRecordError(error)) return {
|
|
54
|
+
status: "unknown",
|
|
55
|
+
domain,
|
|
56
|
+
reason: "dns_error"
|
|
57
|
+
};
|
|
58
|
+
const implicitMx = await resolveAddressRecords(domain, resolver);
|
|
59
|
+
if (implicitMx === "resolved") return {
|
|
60
|
+
status: "valid",
|
|
61
|
+
domain,
|
|
62
|
+
reason: "implicit_mx"
|
|
63
|
+
};
|
|
64
|
+
if (implicitMx === "unknown") return {
|
|
65
|
+
status: "unknown",
|
|
66
|
+
domain,
|
|
67
|
+
reason: "dns_error"
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
status: "invalid",
|
|
71
|
+
domain,
|
|
72
|
+
reason: "no_mail_records"
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (mxRecords.length === 0) {
|
|
76
|
+
const implicitMx = await resolveAddressRecords(domain, resolver);
|
|
77
|
+
if (implicitMx === "resolved") return {
|
|
78
|
+
status: "valid",
|
|
79
|
+
domain,
|
|
80
|
+
reason: "implicit_mx"
|
|
81
|
+
};
|
|
82
|
+
if (implicitMx === "unknown") return {
|
|
83
|
+
status: "unknown",
|
|
84
|
+
domain,
|
|
85
|
+
reason: "dns_error"
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
status: "invalid",
|
|
89
|
+
domain,
|
|
90
|
+
reason: "no_mail_records"
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const exchanges = mxRecords.map(({ exchange }) => exchange.trim().replace(/\.$/, ""));
|
|
94
|
+
if (exchanges.some((exchange) => !exchange)) return {
|
|
95
|
+
status: "invalid",
|
|
96
|
+
domain,
|
|
97
|
+
reason: "null_mx"
|
|
98
|
+
};
|
|
99
|
+
const exchangeResults = await Promise.all(Array.from(new Set(exchanges)).map((exchange) => resolveAddressRecords(exchange, resolver)));
|
|
100
|
+
if (exchangeResults.includes("resolved")) return {
|
|
101
|
+
status: "valid",
|
|
102
|
+
domain,
|
|
103
|
+
reason: "mx"
|
|
104
|
+
};
|
|
105
|
+
if (exchangeResults.includes("unknown")) return {
|
|
106
|
+
status: "unknown",
|
|
107
|
+
domain,
|
|
108
|
+
reason: "dns_error"
|
|
109
|
+
};
|
|
110
|
+
return {
|
|
111
|
+
status: "invalid",
|
|
112
|
+
domain,
|
|
113
|
+
reason: "unresolvable_mx"
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
var getCacheTtl = (result) => {
|
|
117
|
+
if (result.status === "valid") return VALID_CACHE_TTL_MS;
|
|
118
|
+
if (result.status === "invalid") return INVALID_CACHE_TTL_MS;
|
|
119
|
+
return UNKNOWN_CACHE_TTL_MS;
|
|
120
|
+
};
|
|
121
|
+
var clearEmailDomainValidationCache = () => {
|
|
122
|
+
emailDomainValidationCache.clear();
|
|
123
|
+
pendingEmailDomainValidations.clear();
|
|
124
|
+
};
|
|
125
|
+
var validateEmailDomain = async (email, options = {}) => {
|
|
126
|
+
const domain = getEmailAddressDomain(email);
|
|
127
|
+
if (!domain) return {
|
|
128
|
+
status: "invalid",
|
|
129
|
+
reason: "invalid_domain"
|
|
130
|
+
};
|
|
131
|
+
const resolver = options.resolver ?? nativeResolver;
|
|
132
|
+
if (!(options.useCache ?? options.resolver === void 0)) return validateWithoutCache(domain, resolver);
|
|
133
|
+
const now = Date.now();
|
|
134
|
+
const cached = emailDomainValidationCache.get(domain);
|
|
135
|
+
if (cached && cached.expiresAt > now) return cached.result;
|
|
136
|
+
if (cached) emailDomainValidationCache.delete(domain);
|
|
137
|
+
const pending = pendingEmailDomainValidations.get(domain);
|
|
138
|
+
if (pending) return pending;
|
|
139
|
+
const validation = validateWithoutCache(domain, resolver).then((result) => {
|
|
140
|
+
emailDomainValidationCache.set(domain, {
|
|
141
|
+
expiresAt: Date.now() + getCacheTtl(result),
|
|
142
|
+
result
|
|
143
|
+
});
|
|
144
|
+
return result;
|
|
145
|
+
});
|
|
146
|
+
pendingEmailDomainValidations.set(domain, validation);
|
|
147
|
+
try {
|
|
148
|
+
return await validation;
|
|
149
|
+
} finally {
|
|
150
|
+
if (pendingEmailDomainValidations.get(domain) === validation) pendingEmailDomainValidations.delete(domain);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
var hasDisposableEmailDomain = async (email) => {
|
|
154
|
+
const emailDomain = getEmailAddressDomain(email);
|
|
155
|
+
if (!emailDomain) return false;
|
|
156
|
+
const disposableEmailDomains = await getDisposableEmailDomains();
|
|
157
|
+
let domain = emailDomain;
|
|
158
|
+
while (domain) {
|
|
159
|
+
if (disposableEmailDomains.has(domain)) return true;
|
|
160
|
+
const nextDot = domain.indexOf(".");
|
|
161
|
+
if (nextDot === -1) return false;
|
|
162
|
+
domain = domain.slice(nextDot + 1);
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
};
|
|
166
|
+
var getEmailAddressValidationErrorCode = async (email, options = {}) => {
|
|
167
|
+
if (await hasDisposableEmailDomain(email)) return DISPOSABLE_EMAIL_ERROR_CODE;
|
|
168
|
+
return (await validateEmailDomain(email, options)).status === "invalid" ? INVALID_EMAIL_DOMAIN_ERROR_CODE : void 0;
|
|
169
|
+
};
|
|
170
|
+
var isEmailAddressValid = async (email, options = {}) => await getEmailAddressValidationErrorCode(email, options) === void 0;
|
|
171
|
+
//#endregion
|
|
172
|
+
export { DISPOSABLE_EMAIL_ERROR_CODE, INVALID_EMAIL_DOMAIN_ERROR_CODE, clearEmailDomainValidationCache, getEmailAddressDomain, getEmailAddressValidationErrorCode, isEmailAddressValid, validateEmailDomain };
|
|
173
|
+
|
|
174
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["resolve4","resolve6","resolveMx","domainToASCII","DISPOSABLE_EMAIL_ERROR_CODE","INVALID_EMAIL_DOMAIN_ERROR_CODE","EmailAddressValidationErrorCode","EmailDomainResolver","hostname","Promise","Array","exchange","priority","EmailDomainValidationResult","status","domain","reason","ValidateEmailDomainOptions","resolver","useCache","AddressResolution","CachedEmailDomainValidation","expiresAt","result","VALID_CACHE_TTL_MS","INVALID_CACHE_TTL_MS","UNKNOWN_CACHE_TTL_MS","nativeResolver","emailDomainValidationCache","Map","pendingEmailDomainValidations","disposableEmailDomainsPromise","Set","getDisposableEmailDomains","then","default","MailChecker","blacklist","getDnsErrorCode","error","undefined","code","isMissingDnsRecordError","getMailbox","value","trimmed","trim","displayAddress","match","getEmailAddressDomain","email","mailbox","atIndex","lastIndexOf","length","slice","toLowerCase","test","includes","asciiDomain","resolveAddressRecords","results","allSettled","some","errors","filter","PromiseRejectedResult","map","every","validateWithoutCache","mxRecords","Awaited","ReturnType","implicitMx","exchanges","replace","exchangeResults","all","from","getCacheTtl","clearEmailDomainValidationCache","clear","validateEmailDomain","options","now","Date","cached","get","delete","pending","validation","set","hasDisposableEmailDomain","emailDomain","disposableEmailDomains","has","nextDot","indexOf","getEmailAddressValidationErrorCode","domainValidation","isEmailAddressValid"],"sources":["../../src/email-validation/index.ts"],"sourcesContent":["import { resolve4, resolve6, resolveMx } from \"node:dns/promises\"\nimport { domainToASCII } from \"node:url\"\n\n\nexport const DISPOSABLE_EMAIL_ERROR_CODE = \"disposable_email\"\nexport const INVALID_EMAIL_DOMAIN_ERROR_CODE = \"invalid_email_domain\"\n\nexport type EmailAddressValidationErrorCode =\n | typeof DISPOSABLE_EMAIL_ERROR_CODE\n | typeof INVALID_EMAIL_DOMAIN_ERROR_CODE\n\nexport type EmailDomainResolver = {\n resolveMx(hostname: string): Promise<Array<{ exchange: string; priority: number }>>\n resolve4(hostname: string): Promise<string[]>\n resolve6(hostname: string): Promise<string[]>\n}\n\nexport type EmailDomainValidationResult =\n | {\n status: \"valid\"\n domain: string\n reason: \"mx\" | \"implicit_mx\"\n }\n | {\n status: \"invalid\"\n domain?: string\n reason: \"invalid_domain\" | \"null_mx\" | \"unresolvable_mx\" | \"no_mail_records\"\n }\n | {\n status: \"unknown\"\n domain: string\n reason: \"dns_error\"\n }\n\nexport type ValidateEmailDomainOptions = {\n resolver?: EmailDomainResolver\n useCache?: boolean\n}\n\ntype AddressResolution = \"resolved\" | \"missing\" | \"unknown\"\n\ntype CachedEmailDomainValidation = {\n expiresAt: number\n result: EmailDomainValidationResult\n}\n\nconst VALID_CACHE_TTL_MS = 10 * 60 * 1000\nconst INVALID_CACHE_TTL_MS = 5 * 60 * 1000\nconst UNKNOWN_CACHE_TTL_MS = 30 * 1000\n\nconst nativeResolver: EmailDomainResolver = {\n resolveMx: (hostname) => resolveMx(hostname),\n resolve4: (hostname) => resolve4(hostname),\n resolve6: (hostname) => resolve6(hostname),\n}\n\nconst emailDomainValidationCache = new Map<string, CachedEmailDomainValidation>()\nconst pendingEmailDomainValidations = new Map<string, Promise<EmailDomainValidationResult>>()\n\nlet disposableEmailDomainsPromise: Promise<Set<string>> | undefined\n\nconst getDisposableEmailDomains = (): Promise<Set<string>> => {\n disposableEmailDomainsPromise ??= import(\"mailchecker\").then(\n ({ default: MailChecker }) => MailChecker.blacklist(),\n )\n return disposableEmailDomainsPromise\n}\n\nconst getDnsErrorCode = (error: unknown): string | undefined => {\n if (!error || typeof error !== \"object\" || !(\"code\" in error)) return undefined\n return typeof error.code === \"string\" ? error.code : undefined\n}\n\nconst isMissingDnsRecordError = (error: unknown): boolean => {\n const code = getDnsErrorCode(error)\n return code === \"ENODATA\" || code === \"ENOTFOUND\" || code === \"EBADNAME\"\n}\n\nconst getMailbox = (value: string): string => {\n const trimmed = value.trim()\n const displayAddress = trimmed.match(/<([^<>]+)>$/)\n return (displayAddress?.[1] ?? trimmed).trim()\n}\n\nexport const getEmailAddressDomain = (email: unknown): string | undefined => {\n if (typeof email !== \"string\") return undefined\n\n const mailbox = getMailbox(email)\n const atIndex = mailbox.lastIndexOf(\"@\")\n if (atIndex <= 0 || atIndex === mailbox.length - 1) return undefined\n\n const domain = mailbox.slice(atIndex + 1).toLowerCase()\n if (\n !domain\n || /\\s/.test(domain)\n || domain.includes(\"@\")\n || domain.includes(\"[\")\n || domain.includes(\"]\")\n || domain.includes(\"<\")\n || domain.includes(\">\")\n ) return undefined\n\n const asciiDomain = domainToASCII(domain)\n return asciiDomain || undefined\n}\n\nconst resolveAddressRecords = async(\n hostname: string,\n resolver: EmailDomainResolver,\n): Promise<AddressResolution> => {\n const results = await Promise.allSettled([\n resolver.resolve4(hostname),\n resolver.resolve6(hostname),\n ])\n\n if (results.some((result) => result.status === \"fulfilled\" && result.value.length > 0)) {\n return \"resolved\"\n }\n\n const errors = results\n .filter((result): result is PromiseRejectedResult => result.status === \"rejected\")\n .map((result) => result.reason)\n\n return errors.every(isMissingDnsRecordError) ? \"missing\" : \"unknown\"\n}\n\nconst validateWithoutCache = async(\n domain: string,\n resolver: EmailDomainResolver,\n): Promise<EmailDomainValidationResult> => {\n let mxRecords: Awaited<ReturnType<EmailDomainResolver[\"resolveMx\"]>>\n\n try {\n mxRecords = await resolver.resolveMx(domain)\n } catch (error) {\n if (!isMissingDnsRecordError(error)) {\n return { status: \"unknown\", domain, reason: \"dns_error\" }\n }\n\n const implicitMx = await resolveAddressRecords(domain, resolver)\n if (implicitMx === \"resolved\") return { status: \"valid\", domain, reason: \"implicit_mx\" }\n if (implicitMx === \"unknown\") return { status: \"unknown\", domain, reason: \"dns_error\" }\n return { status: \"invalid\", domain, reason: \"no_mail_records\" }\n }\n\n if (mxRecords.length === 0) {\n const implicitMx = await resolveAddressRecords(domain, resolver)\n if (implicitMx === \"resolved\") return { status: \"valid\", domain, reason: \"implicit_mx\" }\n if (implicitMx === \"unknown\") return { status: \"unknown\", domain, reason: \"dns_error\" }\n return { status: \"invalid\", domain, reason: \"no_mail_records\" }\n }\n\n const exchanges = mxRecords.map(({ exchange }) => exchange.trim().replace(/\\.$/, \"\"))\n if (exchanges.some((exchange) => !exchange)) {\n return { status: \"invalid\", domain, reason: \"null_mx\" }\n }\n\n const exchangeResults = await Promise.all(\n Array.from(new Set(exchanges)).map((exchange) => resolveAddressRecords(exchange, resolver)),\n )\n\n if (exchangeResults.includes(\"resolved\")) return { status: \"valid\", domain, reason: \"mx\" }\n if (exchangeResults.includes(\"unknown\")) return { status: \"unknown\", domain, reason: \"dns_error\" }\n return { status: \"invalid\", domain, reason: \"unresolvable_mx\" }\n}\n\nconst getCacheTtl = (result: EmailDomainValidationResult): number => {\n if (result.status === \"valid\") return VALID_CACHE_TTL_MS\n if (result.status === \"invalid\") return INVALID_CACHE_TTL_MS\n return UNKNOWN_CACHE_TTL_MS\n}\n\nexport const clearEmailDomainValidationCache = (): void => {\n emailDomainValidationCache.clear()\n pendingEmailDomainValidations.clear()\n}\n\nexport const validateEmailDomain = async(\n email: unknown,\n options: ValidateEmailDomainOptions = {},\n): Promise<EmailDomainValidationResult> => {\n const domain = getEmailAddressDomain(email)\n if (!domain) return { status: \"invalid\", reason: \"invalid_domain\" }\n\n const resolver = options.resolver ?? nativeResolver\n const useCache = options.useCache ?? options.resolver === undefined\n if (!useCache) return validateWithoutCache(domain, resolver)\n\n const now = Date.now()\n const cached = emailDomainValidationCache.get(domain)\n if (cached && cached.expiresAt > now) return cached.result\n if (cached) emailDomainValidationCache.delete(domain)\n\n const pending = pendingEmailDomainValidations.get(domain)\n if (pending) return pending\n\n const validation = validateWithoutCache(domain, resolver).then((result) => {\n emailDomainValidationCache.set(domain, {\n expiresAt: Date.now() + getCacheTtl(result),\n result,\n })\n return result\n })\n\n pendingEmailDomainValidations.set(domain, validation)\n try {\n return await validation\n } finally {\n if (pendingEmailDomainValidations.get(domain) === validation) {\n pendingEmailDomainValidations.delete(domain)\n }\n }\n}\n\nconst hasDisposableEmailDomain = async(email: unknown): Promise<boolean> => {\n const emailDomain = getEmailAddressDomain(email)\n if (!emailDomain) return false\n\n const disposableEmailDomains = await getDisposableEmailDomains()\n let domain = emailDomain\n\n while (domain) {\n if (disposableEmailDomains.has(domain)) return true\n\n const nextDot = domain.indexOf(\".\")\n if (nextDot === -1) return false\n domain = domain.slice(nextDot + 1)\n }\n\n return false\n}\n\nexport const getEmailAddressValidationErrorCode = async(\n email: unknown,\n options: ValidateEmailDomainOptions = {},\n): Promise<EmailAddressValidationErrorCode | undefined> => {\n if (await hasDisposableEmailDomain(email)) return DISPOSABLE_EMAIL_ERROR_CODE\n\n const domainValidation = await validateEmailDomain(email, options)\n return domainValidation.status === \"invalid\" ? INVALID_EMAIL_DOMAIN_ERROR_CODE : undefined\n}\n\nexport const isEmailAddressValid = async(\n email: unknown,\n options: ValidateEmailDomainOptions = {},\n): Promise<boolean> => (await getEmailAddressValidationErrorCode(email, options)) === undefined\n"],"mappings":"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"}
|
package/dist/email.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EmailAddressValidationErrorCode } from './email-validation';
|
|
1
2
|
export type SendEmailParams = {
|
|
2
3
|
to: string | string[];
|
|
3
4
|
subject: string;
|
|
@@ -26,7 +27,7 @@ export type ResendEmailTransportOptions = {
|
|
|
26
27
|
apiKey: string;
|
|
27
28
|
defaultFrom?: string;
|
|
28
29
|
};
|
|
29
|
-
export type EmailDeliveryErrorCode = "missing_transport" | "provider_rejected" | "provider_unconfirmed" | "transport_error";
|
|
30
|
+
export type EmailDeliveryErrorCode = "missing_transport" | "provider_rejected" | "provider_unconfirmed" | "transport_error" | EmailAddressValidationErrorCode;
|
|
30
31
|
export declare class EmailDeliveryError extends Error {
|
|
31
32
|
readonly code: EmailDeliveryErrorCode;
|
|
32
33
|
constructor(code: EmailDeliveryErrorCode, message: string, cause?: unknown);
|
package/dist/email.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,oBAAoB,CAAA;AAG3B,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACrC,CAAA;AAED,MAAM,MAAM,eAAe,GACvB;IACA,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,GACC;IACA,EAAE,EAAE,SAAS,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,aAAa,EAAE,mBAAmB,CAAC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAA;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACzD,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAC9B,mBAAmB,GACnB,mBAAmB,GACnB,sBAAsB,GACtB,iBAAiB,GACjB,+BAA+B,CAAA;AAEnC,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;gBAEzB,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM3E;AA+CD,eAAO,MAAM,uBAAuB,GAAI,YAAY,cAAc,GAAG,IAAI,KAAG,IAG3E,CAAA;AAED,eAAO,MAAM,0BAA0B,GAAI,0BAGxC,2BAA2B,KAAG,cAqDhC,CAAA;AAED,eAAO,MAAM,SAAS,GACpB,QAAQ,eAAe,EACvB,UAAS,gBAAqB,KAC7B,OAAO,CAAC,eAAe,CAyBzB,CAAA"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,cAAc,SAAS,CAAA;AACvB,cAAc,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,cAAc,SAAS,CAAA;AACvB,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as __toESM, t as __commonJSMin } from "./rolldown-runtime-FDOR9p9I.js";
|
|
2
2
|
import { c as runRtsQuery, d as getDerivedKey, i as normalizeRtsQueryOptions, n as buildRtsAbilityFromRequest, o as resolveRtsRequestTenantId, r as isRtsRequestAuthorized, s as runRtsCount, t as RTS_QUERY_WINDOW_MAX_COUNT, u as syncAuthenticatedSessionMiddleware } from "./queryWindow-DNQxuY_M.js";
|
|
3
|
+
import { i as sendEmail, n as configureEmailTransport, r as createResendEmailTransport, t as EmailDeliveryError } from "./email-B7QOOLlZ.js";
|
|
4
|
+
import { DISPOSABLE_EMAIL_ERROR_CODE, INVALID_EMAIL_DOMAIN_ERROR_CODE, clearEmailDomainValidationCache, getEmailAddressDomain, getEmailAddressValidationErrorCode, isEmailAddressValid, validateEmailDomain } from "./email-validation/index.js";
|
|
3
5
|
import session from "express-session";
|
|
4
6
|
import { RedisStore } from "connect-redis";
|
|
5
7
|
import MongoStore from "connect-mongo";
|
|
@@ -5518,6 +5520,6 @@ var ssrMiddleware = ({ viteInstance, dataRoutes, errorExtraComponent, getHtmlOut
|
|
|
5518
5520
|
}
|
|
5519
5521
|
};
|
|
5520
5522
|
//#endregion
|
|
5521
|
-
export { EmailDeliveryError, RPCBASE_SERVICE_WORKER_MESSAGE_SOURCE, RPCBASE_SERVICE_WORKER_PATH, bindShutdownSignals, configureEmailTransport, createResendEmailTransport, getDerivedKey, hashPassword, hashPasswordForStorage, initServer, onShutdown, registerRpcbaseServiceWorkerRoute, rpcbaseServiceWorkerRequestHandler, rpcbaseServiceWorkerSource, sendEmail, ssrMiddleware, verifyPasswordFromStorage };
|
|
5523
|
+
export { DISPOSABLE_EMAIL_ERROR_CODE, EmailDeliveryError, INVALID_EMAIL_DOMAIN_ERROR_CODE, RPCBASE_SERVICE_WORKER_MESSAGE_SOURCE, RPCBASE_SERVICE_WORKER_PATH, bindShutdownSignals, clearEmailDomainValidationCache, configureEmailTransport, createResendEmailTransport, getDerivedKey, getEmailAddressDomain, getEmailAddressValidationErrorCode, hashPassword, hashPasswordForStorage, initServer, isEmailAddressValid, onShutdown, registerRpcbaseServiceWorkerRoute, rpcbaseServiceWorkerRequestHandler, rpcbaseServiceWorkerSource, sendEmail, ssrMiddleware, validateEmailDomain, verifyPasswordFromStorage };
|
|
5522
5524
|
|
|
5523
5525
|
//# sourceMappingURL=index.js.map
|