@lacspace/email-validate 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lacspace
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1,236 @@
1
+ 'use strict';
2
+
3
+ // src/index.ts
4
+ var FREE_PROVIDERS = /* @__PURE__ */ new Set([
5
+ "gmail.com",
6
+ "googlemail.com",
7
+ "yahoo.com",
8
+ "yahoo.co.in",
9
+ "yahoo.co.uk",
10
+ "hotmail.com",
11
+ "outlook.com",
12
+ "live.com",
13
+ "msn.com",
14
+ "icloud.com",
15
+ "me.com",
16
+ "aol.com",
17
+ "protonmail.com",
18
+ "proton.me",
19
+ "zoho.com",
20
+ "gmx.com",
21
+ "gmx.net",
22
+ "yandex.com",
23
+ "yandex.ru",
24
+ "mail.com",
25
+ "mail.ru",
26
+ "rediffmail.com"
27
+ ]);
28
+ var DISPOSABLE_DOMAINS = /* @__PURE__ */ new Set([
29
+ "mailinator.com",
30
+ "guerrillamail.com",
31
+ "guerrillamail.info",
32
+ "grr.la",
33
+ "10minutemail.com",
34
+ "10minutemail.net",
35
+ "tempmail.com",
36
+ "temp-mail.org",
37
+ "throwawaymail.com",
38
+ "yopmail.com",
39
+ "yopmail.fr",
40
+ "getnada.com",
41
+ "nada.email",
42
+ "trashmail.com",
43
+ "trashmail.de",
44
+ "sharklasers.com",
45
+ "spam4.me",
46
+ "dispostable.com",
47
+ "maildrop.cc",
48
+ "mailnesia.com",
49
+ "mohmal.com",
50
+ "fakeinbox.com",
51
+ "tempinbox.com",
52
+ "mintemail.com",
53
+ "mytemp.email",
54
+ "emailondeck.com",
55
+ "burnermail.io",
56
+ "33mail.com",
57
+ "spamgourmet.com",
58
+ "tempr.email",
59
+ "discard.email",
60
+ "mailcatch.com",
61
+ "inboxbear.com",
62
+ "tempmailo.com",
63
+ "temp-mail.io",
64
+ "1secmail.com",
65
+ "moakt.com",
66
+ "tmpmail.org",
67
+ "guerrillamailblock.com",
68
+ "pokemail.net",
69
+ "spambog.com",
70
+ "einrot.com"
71
+ ]);
72
+ var ROLE_LOCALS = /* @__PURE__ */ new Set([
73
+ "admin",
74
+ "administrator",
75
+ "info",
76
+ "support",
77
+ "sales",
78
+ "contact",
79
+ "help",
80
+ "no-reply",
81
+ "noreply",
82
+ "donotreply",
83
+ "do-not-reply",
84
+ "postmaster",
85
+ "webmaster",
86
+ "abuse",
87
+ "billing",
88
+ "hr",
89
+ "jobs",
90
+ "careers",
91
+ "marketing",
92
+ "team",
93
+ "hello",
94
+ "office",
95
+ "enquiry",
96
+ "enquiries",
97
+ "service",
98
+ "root",
99
+ "security",
100
+ "privacy"
101
+ ]);
102
+ var COMMON_DOMAINS = [
103
+ "gmail.com",
104
+ "googlemail.com",
105
+ "yahoo.com",
106
+ "hotmail.com",
107
+ "outlook.com",
108
+ "live.com",
109
+ "icloud.com",
110
+ "aol.com",
111
+ "protonmail.com",
112
+ "zoho.com",
113
+ "yandex.com",
114
+ "mail.com",
115
+ "msn.com"
116
+ ];
117
+ var LOCAL_RE = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$/;
118
+ var DOMAIN_RE = /^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/;
119
+ function splitEmail(email) {
120
+ const at = email.lastIndexOf("@");
121
+ if (at <= 0 || at === email.length - 1) return null;
122
+ return { local: email.slice(0, at), domain: email.slice(at + 1) };
123
+ }
124
+ function isValidEmail(email) {
125
+ if (typeof email !== "string") return false;
126
+ const trimmed = email.trim();
127
+ if (trimmed.length > 254) return false;
128
+ const parts = splitEmail(trimmed);
129
+ if (!parts) return false;
130
+ const { local, domain } = parts;
131
+ if (local.length > 64 || local.length === 0) return false;
132
+ if (domain.length > 255) return false;
133
+ if (!LOCAL_RE.test(local)) return false;
134
+ if (!DOMAIN_RE.test(domain)) return false;
135
+ return true;
136
+ }
137
+ function isDisposable(domain, extra) {
138
+ const d = domain.toLowerCase();
139
+ if (DISPOSABLE_DOMAINS.has(d)) return true;
140
+ return extra ? extra.map((x) => x.toLowerCase()).includes(d) : false;
141
+ }
142
+ function isRoleAddress(local) {
143
+ return ROLE_LOCALS.has(local.toLowerCase());
144
+ }
145
+ function isFreeProvider(domain) {
146
+ return FREE_PROVIDERS.has(domain.toLowerCase());
147
+ }
148
+ function normalizeEmail(email) {
149
+ const parts = splitEmail(email.trim());
150
+ if (!parts) return email.trim().toLowerCase();
151
+ let { local } = parts;
152
+ const domain = parts.domain.toLowerCase();
153
+ local = local.toLowerCase();
154
+ if (domain === "gmail.com" || domain === "googlemail.com") {
155
+ local = local.split("+")[0].replace(/\./g, "");
156
+ return `${local}@gmail.com`;
157
+ }
158
+ const plus = local.indexOf("+");
159
+ if (plus > 0) local = local.slice(0, plus);
160
+ return `${local}@${domain}`;
161
+ }
162
+ function levenshtein(a, b) {
163
+ const m = a.length;
164
+ const n = b.length;
165
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
166
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
167
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
168
+ for (let i = 1; i <= m; i++) {
169
+ for (let j = 1; j <= n; j++) {
170
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
171
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
172
+ }
173
+ }
174
+ return dp[m][n];
175
+ }
176
+ function suggestEmail(email) {
177
+ const parts = splitEmail(email.trim().toLowerCase());
178
+ if (!parts) return null;
179
+ const { local, domain } = parts;
180
+ if (COMMON_DOMAINS.includes(domain)) return null;
181
+ let best = null;
182
+ let bestDist = Infinity;
183
+ for (const candidate of COMMON_DOMAINS) {
184
+ const dist = levenshtein(domain, candidate);
185
+ if (dist < bestDist) {
186
+ bestDist = dist;
187
+ best = candidate;
188
+ }
189
+ }
190
+ if (best && bestDist > 0 && bestDist <= 2 && Math.abs(domain.length - best.length) <= 2) {
191
+ return `${local}@${best}`;
192
+ }
193
+ return null;
194
+ }
195
+ function validateEmail(email, opts = {}) {
196
+ const raw = typeof email === "string" ? email.trim() : "";
197
+ const parts = splitEmail(raw);
198
+ if (!isValidEmail(raw) || !parts) {
199
+ return {
200
+ valid: false,
201
+ normalized: null,
202
+ local: null,
203
+ domain: null,
204
+ disposable: false,
205
+ role: false,
206
+ free: false,
207
+ suggestion: opts.suggestions === false ? null : suggestEmail(raw),
208
+ reason: "invalid syntax"
209
+ };
210
+ }
211
+ const local = parts.local;
212
+ const domain = parts.domain.toLowerCase();
213
+ return {
214
+ valid: true,
215
+ normalized: normalizeEmail(raw),
216
+ local,
217
+ domain,
218
+ disposable: isDisposable(domain, opts.extraDisposable),
219
+ role: isRoleAddress(local),
220
+ free: isFreeProvider(domain),
221
+ suggestion: opts.suggestions === false ? null : suggestEmail(raw)
222
+ };
223
+ }
224
+
225
+ exports.DISPOSABLE_DOMAINS = DISPOSABLE_DOMAINS;
226
+ exports.FREE_PROVIDERS = FREE_PROVIDERS;
227
+ exports.ROLE_LOCALS = ROLE_LOCALS;
228
+ exports.isDisposable = isDisposable;
229
+ exports.isFreeProvider = isFreeProvider;
230
+ exports.isRoleAddress = isRoleAddress;
231
+ exports.isValidEmail = isValidEmail;
232
+ exports.normalizeEmail = normalizeEmail;
233
+ exports.suggestEmail = suggestEmail;
234
+ exports.validateEmail = validateEmail;
235
+ //# sourceMappingURL=index.cjs.map
236
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lacspace/email-validate\n * Smart email validation — beyond a regex.\n *\n * Syntax + disposable/temp-mail detection, role-address detection, free-provider\n * flags, Gmail normalization and \"did you mean?\" typo suggestions.\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\n/** Common free/consumer email providers. */\nexport const FREE_PROVIDERS: Set<string> = new Set([\n \"gmail.com\", \"googlemail.com\", \"yahoo.com\", \"yahoo.co.in\", \"yahoo.co.uk\",\n \"hotmail.com\", \"outlook.com\", \"live.com\", \"msn.com\", \"icloud.com\", \"me.com\",\n \"aol.com\", \"protonmail.com\", \"proton.me\", \"zoho.com\", \"gmx.com\", \"gmx.net\",\n \"yandex.com\", \"yandex.ru\", \"mail.com\", \"mail.ru\", \"rediffmail.com\",\n]);\n\n/** Well-known disposable / temporary-mail domains. Extend via {@link validateEmail} options. */\nexport const DISPOSABLE_DOMAINS: Set<string> = new Set([\n \"mailinator.com\", \"guerrillamail.com\", \"guerrillamail.info\", \"grr.la\",\n \"10minutemail.com\", \"10minutemail.net\", \"tempmail.com\", \"temp-mail.org\",\n \"throwawaymail.com\", \"yopmail.com\", \"yopmail.fr\", \"getnada.com\", \"nada.email\",\n \"trashmail.com\", \"trashmail.de\", \"sharklasers.com\", \"spam4.me\", \"dispostable.com\",\n \"maildrop.cc\", \"mailnesia.com\", \"mohmal.com\", \"fakeinbox.com\", \"tempinbox.com\",\n \"mintemail.com\", \"mytemp.email\", \"emailondeck.com\", \"burnermail.io\", \"33mail.com\",\n \"spamgourmet.com\", \"tempr.email\", \"discard.email\", \"mailcatch.com\", \"inboxbear.com\",\n \"tempmailo.com\", \"temp-mail.io\", \"1secmail.com\", \"moakt.com\", \"tmpmail.org\",\n \"guerrillamailblock.com\", \"pokemail.net\", \"spambog.com\", \"einrot.com\",\n]);\n\n/** Local-parts that indicate a shared/role mailbox rather than a person. */\nexport const ROLE_LOCALS: Set<string> = new Set([\n \"admin\", \"administrator\", \"info\", \"support\", \"sales\", \"contact\", \"help\",\n \"no-reply\", \"noreply\", \"donotreply\", \"do-not-reply\", \"postmaster\", \"webmaster\",\n \"abuse\", \"billing\", \"hr\", \"jobs\", \"careers\", \"marketing\", \"team\", \"hello\",\n \"office\", \"enquiry\", \"enquiries\", \"service\", \"root\", \"security\", \"privacy\",\n]);\n\n/** Popular domains used for typo suggestions. */\nconst COMMON_DOMAINS = [\n \"gmail.com\", \"googlemail.com\", \"yahoo.com\", \"hotmail.com\", \"outlook.com\",\n \"live.com\", \"icloud.com\", \"aol.com\", \"protonmail.com\", \"zoho.com\",\n \"yandex.com\", \"mail.com\", \"msn.com\",\n];\n\n// Pragmatic RFC-5321-ish address grammar (no comments/quoted-strings; good for real-world use).\nconst LOCAL_RE = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$/;\nconst DOMAIN_RE = /^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\.)+[A-Za-z]{2,}$/;\n\nexport interface ValidationOptions {\n /** Extra disposable domains to treat as disposable. */\n extraDisposable?: string[];\n /** Turn off \"did you mean?\" suggestions. */\n suggestions?: boolean;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n /** Lowercased address; for Gmail, dots and +tags stripped. `null` if invalid. */\n normalized: string | null;\n local: string | null;\n domain: string | null;\n disposable: boolean;\n /** A shared/role mailbox (info@, admin@, …). */\n role: boolean;\n /** A free consumer provider (gmail, yahoo, …). */\n free: boolean;\n /** A likely-correct address if a typo was detected, else `null`. */\n suggestion: string | null;\n /** Why it failed, when `valid` is false. */\n reason?: string;\n}\n\nfunction splitEmail(email: string): { local: string; domain: string } | null {\n const at = email.lastIndexOf(\"@\");\n if (at <= 0 || at === email.length - 1) return null;\n return { local: email.slice(0, at), domain: email.slice(at + 1) };\n}\n\n/** Fast boolean syntax + structure check. */\nexport function isValidEmail(email: string): boolean {\n if (typeof email !== \"string\") return false;\n const trimmed = email.trim();\n if (trimmed.length > 254) return false;\n const parts = splitEmail(trimmed);\n if (!parts) return false;\n const { local, domain } = parts;\n if (local.length > 64 || local.length === 0) return false;\n if (domain.length > 255) return false;\n if (!LOCAL_RE.test(local)) return false;\n if (!DOMAIN_RE.test(domain)) return false;\n return true;\n}\n\nexport function isDisposable(domain: string, extra?: string[]): boolean {\n const d = domain.toLowerCase();\n if (DISPOSABLE_DOMAINS.has(d)) return true;\n return extra ? extra.map((x) => x.toLowerCase()).includes(d) : false;\n}\n\nexport function isRoleAddress(local: string): boolean {\n return ROLE_LOCALS.has(local.toLowerCase());\n}\n\nexport function isFreeProvider(domain: string): boolean {\n return FREE_PROVIDERS.has(domain.toLowerCase());\n}\n\n/** Canonical form: lowercased; Gmail addresses get dots + `+tags` removed. */\nexport function normalizeEmail(email: string): string {\n const parts = splitEmail(email.trim());\n if (!parts) return email.trim().toLowerCase();\n let { local } = parts;\n const domain = parts.domain.toLowerCase();\n local = local.toLowerCase();\n if (domain === \"gmail.com\" || domain === \"googlemail.com\") {\n local = local.split(\"+\")[0]!.replace(/\\./g, \"\");\n return `${local}@gmail.com`;\n }\n const plus = local.indexOf(\"+\");\n if (plus > 0) local = local.slice(0, plus);\n return `${local}@${domain}`;\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n const dp = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));\n for (let i = 0; i <= m; i++) dp[i]![0] = i;\n for (let j = 0; j <= n; j++) dp[0]![j] = j;\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n dp[i]![j] = Math.min(dp[i - 1]![j]! + 1, dp[i]![j - 1]! + 1, dp[i - 1]![j - 1]! + cost);\n }\n }\n return dp[m]![n]!;\n}\n\n/** Suggest a corrected address when the domain looks like a typo of a common one. */\nexport function suggestEmail(email: string): string | null {\n const parts = splitEmail(email.trim().toLowerCase());\n if (!parts) return null;\n const { local, domain } = parts;\n if (COMMON_DOMAINS.includes(domain)) return null;\n let best: string | null = null;\n let bestDist = Infinity;\n for (const candidate of COMMON_DOMAINS) {\n const dist = levenshtein(domain, candidate);\n if (dist < bestDist) {\n bestDist = dist;\n best = candidate;\n }\n }\n // Only suggest for close typos, and never \"correct\" a longer legit domain.\n if (best && bestDist > 0 && bestDist <= 2 && Math.abs(domain.length - best.length) <= 2) {\n return `${local}@${best}`;\n }\n return null;\n}\n\n/** Full analysis of an email address. */\nexport function validateEmail(email: string, opts: ValidationOptions = {}): ValidationResult {\n const raw = typeof email === \"string\" ? email.trim() : \"\";\n const parts = splitEmail(raw);\n\n if (!isValidEmail(raw) || !parts) {\n return {\n valid: false,\n normalized: null,\n local: null,\n domain: null,\n disposable: false,\n role: false,\n free: false,\n suggestion: opts.suggestions === false ? null : suggestEmail(raw),\n reason: \"invalid syntax\",\n };\n }\n\n const local = parts.local;\n const domain = parts.domain.toLowerCase();\n return {\n valid: true,\n normalized: normalizeEmail(raw),\n local,\n domain,\n disposable: isDisposable(domain, opts.extraDisposable),\n role: isRoleAddress(local),\n free: isFreeProvider(domain),\n suggestion: opts.suggestions === false ? null : suggestEmail(raw),\n };\n}\n"]}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @lacspace/email-validate
3
+ * Smart email validation — beyond a regex.
4
+ *
5
+ * Syntax + disposable/temp-mail detection, role-address detection, free-provider
6
+ * flags, Gmail normalization and "did you mean?" typo suggestions.
7
+ *
8
+ * Zero dependencies · isomorphic · fully typed.
9
+ */
10
+ /** Common free/consumer email providers. */
11
+ declare const FREE_PROVIDERS: Set<string>;
12
+ /** Well-known disposable / temporary-mail domains. Extend via {@link validateEmail} options. */
13
+ declare const DISPOSABLE_DOMAINS: Set<string>;
14
+ /** Local-parts that indicate a shared/role mailbox rather than a person. */
15
+ declare const ROLE_LOCALS: Set<string>;
16
+ interface ValidationOptions {
17
+ /** Extra disposable domains to treat as disposable. */
18
+ extraDisposable?: string[];
19
+ /** Turn off "did you mean?" suggestions. */
20
+ suggestions?: boolean;
21
+ }
22
+ interface ValidationResult {
23
+ valid: boolean;
24
+ /** Lowercased address; for Gmail, dots and +tags stripped. `null` if invalid. */
25
+ normalized: string | null;
26
+ local: string | null;
27
+ domain: string | null;
28
+ disposable: boolean;
29
+ /** A shared/role mailbox (info@, admin@, …). */
30
+ role: boolean;
31
+ /** A free consumer provider (gmail, yahoo, …). */
32
+ free: boolean;
33
+ /** A likely-correct address if a typo was detected, else `null`. */
34
+ suggestion: string | null;
35
+ /** Why it failed, when `valid` is false. */
36
+ reason?: string;
37
+ }
38
+ /** Fast boolean syntax + structure check. */
39
+ declare function isValidEmail(email: string): boolean;
40
+ declare function isDisposable(domain: string, extra?: string[]): boolean;
41
+ declare function isRoleAddress(local: string): boolean;
42
+ declare function isFreeProvider(domain: string): boolean;
43
+ /** Canonical form: lowercased; Gmail addresses get dots + `+tags` removed. */
44
+ declare function normalizeEmail(email: string): string;
45
+ /** Suggest a corrected address when the domain looks like a typo of a common one. */
46
+ declare function suggestEmail(email: string): string | null;
47
+ /** Full analysis of an email address. */
48
+ declare function validateEmail(email: string, opts?: ValidationOptions): ValidationResult;
49
+
50
+ export { DISPOSABLE_DOMAINS, FREE_PROVIDERS, ROLE_LOCALS, type ValidationOptions, type ValidationResult, isDisposable, isFreeProvider, isRoleAddress, isValidEmail, normalizeEmail, suggestEmail, validateEmail };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @lacspace/email-validate
3
+ * Smart email validation — beyond a regex.
4
+ *
5
+ * Syntax + disposable/temp-mail detection, role-address detection, free-provider
6
+ * flags, Gmail normalization and "did you mean?" typo suggestions.
7
+ *
8
+ * Zero dependencies · isomorphic · fully typed.
9
+ */
10
+ /** Common free/consumer email providers. */
11
+ declare const FREE_PROVIDERS: Set<string>;
12
+ /** Well-known disposable / temporary-mail domains. Extend via {@link validateEmail} options. */
13
+ declare const DISPOSABLE_DOMAINS: Set<string>;
14
+ /** Local-parts that indicate a shared/role mailbox rather than a person. */
15
+ declare const ROLE_LOCALS: Set<string>;
16
+ interface ValidationOptions {
17
+ /** Extra disposable domains to treat as disposable. */
18
+ extraDisposable?: string[];
19
+ /** Turn off "did you mean?" suggestions. */
20
+ suggestions?: boolean;
21
+ }
22
+ interface ValidationResult {
23
+ valid: boolean;
24
+ /** Lowercased address; for Gmail, dots and +tags stripped. `null` if invalid. */
25
+ normalized: string | null;
26
+ local: string | null;
27
+ domain: string | null;
28
+ disposable: boolean;
29
+ /** A shared/role mailbox (info@, admin@, …). */
30
+ role: boolean;
31
+ /** A free consumer provider (gmail, yahoo, …). */
32
+ free: boolean;
33
+ /** A likely-correct address if a typo was detected, else `null`. */
34
+ suggestion: string | null;
35
+ /** Why it failed, when `valid` is false. */
36
+ reason?: string;
37
+ }
38
+ /** Fast boolean syntax + structure check. */
39
+ declare function isValidEmail(email: string): boolean;
40
+ declare function isDisposable(domain: string, extra?: string[]): boolean;
41
+ declare function isRoleAddress(local: string): boolean;
42
+ declare function isFreeProvider(domain: string): boolean;
43
+ /** Canonical form: lowercased; Gmail addresses get dots + `+tags` removed. */
44
+ declare function normalizeEmail(email: string): string;
45
+ /** Suggest a corrected address when the domain looks like a typo of a common one. */
46
+ declare function suggestEmail(email: string): string | null;
47
+ /** Full analysis of an email address. */
48
+ declare function validateEmail(email: string, opts?: ValidationOptions): ValidationResult;
49
+
50
+ export { DISPOSABLE_DOMAINS, FREE_PROVIDERS, ROLE_LOCALS, type ValidationOptions, type ValidationResult, isDisposable, isFreeProvider, isRoleAddress, isValidEmail, normalizeEmail, suggestEmail, validateEmail };
package/dist/index.js ADDED
@@ -0,0 +1,225 @@
1
+ // src/index.ts
2
+ var FREE_PROVIDERS = /* @__PURE__ */ new Set([
3
+ "gmail.com",
4
+ "googlemail.com",
5
+ "yahoo.com",
6
+ "yahoo.co.in",
7
+ "yahoo.co.uk",
8
+ "hotmail.com",
9
+ "outlook.com",
10
+ "live.com",
11
+ "msn.com",
12
+ "icloud.com",
13
+ "me.com",
14
+ "aol.com",
15
+ "protonmail.com",
16
+ "proton.me",
17
+ "zoho.com",
18
+ "gmx.com",
19
+ "gmx.net",
20
+ "yandex.com",
21
+ "yandex.ru",
22
+ "mail.com",
23
+ "mail.ru",
24
+ "rediffmail.com"
25
+ ]);
26
+ var DISPOSABLE_DOMAINS = /* @__PURE__ */ new Set([
27
+ "mailinator.com",
28
+ "guerrillamail.com",
29
+ "guerrillamail.info",
30
+ "grr.la",
31
+ "10minutemail.com",
32
+ "10minutemail.net",
33
+ "tempmail.com",
34
+ "temp-mail.org",
35
+ "throwawaymail.com",
36
+ "yopmail.com",
37
+ "yopmail.fr",
38
+ "getnada.com",
39
+ "nada.email",
40
+ "trashmail.com",
41
+ "trashmail.de",
42
+ "sharklasers.com",
43
+ "spam4.me",
44
+ "dispostable.com",
45
+ "maildrop.cc",
46
+ "mailnesia.com",
47
+ "mohmal.com",
48
+ "fakeinbox.com",
49
+ "tempinbox.com",
50
+ "mintemail.com",
51
+ "mytemp.email",
52
+ "emailondeck.com",
53
+ "burnermail.io",
54
+ "33mail.com",
55
+ "spamgourmet.com",
56
+ "tempr.email",
57
+ "discard.email",
58
+ "mailcatch.com",
59
+ "inboxbear.com",
60
+ "tempmailo.com",
61
+ "temp-mail.io",
62
+ "1secmail.com",
63
+ "moakt.com",
64
+ "tmpmail.org",
65
+ "guerrillamailblock.com",
66
+ "pokemail.net",
67
+ "spambog.com",
68
+ "einrot.com"
69
+ ]);
70
+ var ROLE_LOCALS = /* @__PURE__ */ new Set([
71
+ "admin",
72
+ "administrator",
73
+ "info",
74
+ "support",
75
+ "sales",
76
+ "contact",
77
+ "help",
78
+ "no-reply",
79
+ "noreply",
80
+ "donotreply",
81
+ "do-not-reply",
82
+ "postmaster",
83
+ "webmaster",
84
+ "abuse",
85
+ "billing",
86
+ "hr",
87
+ "jobs",
88
+ "careers",
89
+ "marketing",
90
+ "team",
91
+ "hello",
92
+ "office",
93
+ "enquiry",
94
+ "enquiries",
95
+ "service",
96
+ "root",
97
+ "security",
98
+ "privacy"
99
+ ]);
100
+ var COMMON_DOMAINS = [
101
+ "gmail.com",
102
+ "googlemail.com",
103
+ "yahoo.com",
104
+ "hotmail.com",
105
+ "outlook.com",
106
+ "live.com",
107
+ "icloud.com",
108
+ "aol.com",
109
+ "protonmail.com",
110
+ "zoho.com",
111
+ "yandex.com",
112
+ "mail.com",
113
+ "msn.com"
114
+ ];
115
+ var LOCAL_RE = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$/;
116
+ var DOMAIN_RE = /^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/;
117
+ function splitEmail(email) {
118
+ const at = email.lastIndexOf("@");
119
+ if (at <= 0 || at === email.length - 1) return null;
120
+ return { local: email.slice(0, at), domain: email.slice(at + 1) };
121
+ }
122
+ function isValidEmail(email) {
123
+ if (typeof email !== "string") return false;
124
+ const trimmed = email.trim();
125
+ if (trimmed.length > 254) return false;
126
+ const parts = splitEmail(trimmed);
127
+ if (!parts) return false;
128
+ const { local, domain } = parts;
129
+ if (local.length > 64 || local.length === 0) return false;
130
+ if (domain.length > 255) return false;
131
+ if (!LOCAL_RE.test(local)) return false;
132
+ if (!DOMAIN_RE.test(domain)) return false;
133
+ return true;
134
+ }
135
+ function isDisposable(domain, extra) {
136
+ const d = domain.toLowerCase();
137
+ if (DISPOSABLE_DOMAINS.has(d)) return true;
138
+ return extra ? extra.map((x) => x.toLowerCase()).includes(d) : false;
139
+ }
140
+ function isRoleAddress(local) {
141
+ return ROLE_LOCALS.has(local.toLowerCase());
142
+ }
143
+ function isFreeProvider(domain) {
144
+ return FREE_PROVIDERS.has(domain.toLowerCase());
145
+ }
146
+ function normalizeEmail(email) {
147
+ const parts = splitEmail(email.trim());
148
+ if (!parts) return email.trim().toLowerCase();
149
+ let { local } = parts;
150
+ const domain = parts.domain.toLowerCase();
151
+ local = local.toLowerCase();
152
+ if (domain === "gmail.com" || domain === "googlemail.com") {
153
+ local = local.split("+")[0].replace(/\./g, "");
154
+ return `${local}@gmail.com`;
155
+ }
156
+ const plus = local.indexOf("+");
157
+ if (plus > 0) local = local.slice(0, plus);
158
+ return `${local}@${domain}`;
159
+ }
160
+ function levenshtein(a, b) {
161
+ const m = a.length;
162
+ const n = b.length;
163
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
164
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
165
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
166
+ for (let i = 1; i <= m; i++) {
167
+ for (let j = 1; j <= n; j++) {
168
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
169
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
170
+ }
171
+ }
172
+ return dp[m][n];
173
+ }
174
+ function suggestEmail(email) {
175
+ const parts = splitEmail(email.trim().toLowerCase());
176
+ if (!parts) return null;
177
+ const { local, domain } = parts;
178
+ if (COMMON_DOMAINS.includes(domain)) return null;
179
+ let best = null;
180
+ let bestDist = Infinity;
181
+ for (const candidate of COMMON_DOMAINS) {
182
+ const dist = levenshtein(domain, candidate);
183
+ if (dist < bestDist) {
184
+ bestDist = dist;
185
+ best = candidate;
186
+ }
187
+ }
188
+ if (best && bestDist > 0 && bestDist <= 2 && Math.abs(domain.length - best.length) <= 2) {
189
+ return `${local}@${best}`;
190
+ }
191
+ return null;
192
+ }
193
+ function validateEmail(email, opts = {}) {
194
+ const raw = typeof email === "string" ? email.trim() : "";
195
+ const parts = splitEmail(raw);
196
+ if (!isValidEmail(raw) || !parts) {
197
+ return {
198
+ valid: false,
199
+ normalized: null,
200
+ local: null,
201
+ domain: null,
202
+ disposable: false,
203
+ role: false,
204
+ free: false,
205
+ suggestion: opts.suggestions === false ? null : suggestEmail(raw),
206
+ reason: "invalid syntax"
207
+ };
208
+ }
209
+ const local = parts.local;
210
+ const domain = parts.domain.toLowerCase();
211
+ return {
212
+ valid: true,
213
+ normalized: normalizeEmail(raw),
214
+ local,
215
+ domain,
216
+ disposable: isDisposable(domain, opts.extraDisposable),
217
+ role: isRoleAddress(local),
218
+ free: isFreeProvider(domain),
219
+ suggestion: opts.suggestions === false ? null : suggestEmail(raw)
220
+ };
221
+ }
222
+
223
+ export { DISPOSABLE_DOMAINS, FREE_PROVIDERS, ROLE_LOCALS, isDisposable, isFreeProvider, isRoleAddress, isValidEmail, normalizeEmail, suggestEmail, validateEmail };
224
+ //# sourceMappingURL=index.js.map
225
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @lacspace/email-validate\n * Smart email validation — beyond a regex.\n *\n * Syntax + disposable/temp-mail detection, role-address detection, free-provider\n * flags, Gmail normalization and \"did you mean?\" typo suggestions.\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\n/** Common free/consumer email providers. */\nexport const FREE_PROVIDERS: Set<string> = new Set([\n \"gmail.com\", \"googlemail.com\", \"yahoo.com\", \"yahoo.co.in\", \"yahoo.co.uk\",\n \"hotmail.com\", \"outlook.com\", \"live.com\", \"msn.com\", \"icloud.com\", \"me.com\",\n \"aol.com\", \"protonmail.com\", \"proton.me\", \"zoho.com\", \"gmx.com\", \"gmx.net\",\n \"yandex.com\", \"yandex.ru\", \"mail.com\", \"mail.ru\", \"rediffmail.com\",\n]);\n\n/** Well-known disposable / temporary-mail domains. Extend via {@link validateEmail} options. */\nexport const DISPOSABLE_DOMAINS: Set<string> = new Set([\n \"mailinator.com\", \"guerrillamail.com\", \"guerrillamail.info\", \"grr.la\",\n \"10minutemail.com\", \"10minutemail.net\", \"tempmail.com\", \"temp-mail.org\",\n \"throwawaymail.com\", \"yopmail.com\", \"yopmail.fr\", \"getnada.com\", \"nada.email\",\n \"trashmail.com\", \"trashmail.de\", \"sharklasers.com\", \"spam4.me\", \"dispostable.com\",\n \"maildrop.cc\", \"mailnesia.com\", \"mohmal.com\", \"fakeinbox.com\", \"tempinbox.com\",\n \"mintemail.com\", \"mytemp.email\", \"emailondeck.com\", \"burnermail.io\", \"33mail.com\",\n \"spamgourmet.com\", \"tempr.email\", \"discard.email\", \"mailcatch.com\", \"inboxbear.com\",\n \"tempmailo.com\", \"temp-mail.io\", \"1secmail.com\", \"moakt.com\", \"tmpmail.org\",\n \"guerrillamailblock.com\", \"pokemail.net\", \"spambog.com\", \"einrot.com\",\n]);\n\n/** Local-parts that indicate a shared/role mailbox rather than a person. */\nexport const ROLE_LOCALS: Set<string> = new Set([\n \"admin\", \"administrator\", \"info\", \"support\", \"sales\", \"contact\", \"help\",\n \"no-reply\", \"noreply\", \"donotreply\", \"do-not-reply\", \"postmaster\", \"webmaster\",\n \"abuse\", \"billing\", \"hr\", \"jobs\", \"careers\", \"marketing\", \"team\", \"hello\",\n \"office\", \"enquiry\", \"enquiries\", \"service\", \"root\", \"security\", \"privacy\",\n]);\n\n/** Popular domains used for typo suggestions. */\nconst COMMON_DOMAINS = [\n \"gmail.com\", \"googlemail.com\", \"yahoo.com\", \"hotmail.com\", \"outlook.com\",\n \"live.com\", \"icloud.com\", \"aol.com\", \"protonmail.com\", \"zoho.com\",\n \"yandex.com\", \"mail.com\", \"msn.com\",\n];\n\n// Pragmatic RFC-5321-ish address grammar (no comments/quoted-strings; good for real-world use).\nconst LOCAL_RE = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$/;\nconst DOMAIN_RE = /^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\.)+[A-Za-z]{2,}$/;\n\nexport interface ValidationOptions {\n /** Extra disposable domains to treat as disposable. */\n extraDisposable?: string[];\n /** Turn off \"did you mean?\" suggestions. */\n suggestions?: boolean;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n /** Lowercased address; for Gmail, dots and +tags stripped. `null` if invalid. */\n normalized: string | null;\n local: string | null;\n domain: string | null;\n disposable: boolean;\n /** A shared/role mailbox (info@, admin@, …). */\n role: boolean;\n /** A free consumer provider (gmail, yahoo, …). */\n free: boolean;\n /** A likely-correct address if a typo was detected, else `null`. */\n suggestion: string | null;\n /** Why it failed, when `valid` is false. */\n reason?: string;\n}\n\nfunction splitEmail(email: string): { local: string; domain: string } | null {\n const at = email.lastIndexOf(\"@\");\n if (at <= 0 || at === email.length - 1) return null;\n return { local: email.slice(0, at), domain: email.slice(at + 1) };\n}\n\n/** Fast boolean syntax + structure check. */\nexport function isValidEmail(email: string): boolean {\n if (typeof email !== \"string\") return false;\n const trimmed = email.trim();\n if (trimmed.length > 254) return false;\n const parts = splitEmail(trimmed);\n if (!parts) return false;\n const { local, domain } = parts;\n if (local.length > 64 || local.length === 0) return false;\n if (domain.length > 255) return false;\n if (!LOCAL_RE.test(local)) return false;\n if (!DOMAIN_RE.test(domain)) return false;\n return true;\n}\n\nexport function isDisposable(domain: string, extra?: string[]): boolean {\n const d = domain.toLowerCase();\n if (DISPOSABLE_DOMAINS.has(d)) return true;\n return extra ? extra.map((x) => x.toLowerCase()).includes(d) : false;\n}\n\nexport function isRoleAddress(local: string): boolean {\n return ROLE_LOCALS.has(local.toLowerCase());\n}\n\nexport function isFreeProvider(domain: string): boolean {\n return FREE_PROVIDERS.has(domain.toLowerCase());\n}\n\n/** Canonical form: lowercased; Gmail addresses get dots + `+tags` removed. */\nexport function normalizeEmail(email: string): string {\n const parts = splitEmail(email.trim());\n if (!parts) return email.trim().toLowerCase();\n let { local } = parts;\n const domain = parts.domain.toLowerCase();\n local = local.toLowerCase();\n if (domain === \"gmail.com\" || domain === \"googlemail.com\") {\n local = local.split(\"+\")[0]!.replace(/\\./g, \"\");\n return `${local}@gmail.com`;\n }\n const plus = local.indexOf(\"+\");\n if (plus > 0) local = local.slice(0, plus);\n return `${local}@${domain}`;\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n const dp = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));\n for (let i = 0; i <= m; i++) dp[i]![0] = i;\n for (let j = 0; j <= n; j++) dp[0]![j] = j;\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n dp[i]![j] = Math.min(dp[i - 1]![j]! + 1, dp[i]![j - 1]! + 1, dp[i - 1]![j - 1]! + cost);\n }\n }\n return dp[m]![n]!;\n}\n\n/** Suggest a corrected address when the domain looks like a typo of a common one. */\nexport function suggestEmail(email: string): string | null {\n const parts = splitEmail(email.trim().toLowerCase());\n if (!parts) return null;\n const { local, domain } = parts;\n if (COMMON_DOMAINS.includes(domain)) return null;\n let best: string | null = null;\n let bestDist = Infinity;\n for (const candidate of COMMON_DOMAINS) {\n const dist = levenshtein(domain, candidate);\n if (dist < bestDist) {\n bestDist = dist;\n best = candidate;\n }\n }\n // Only suggest for close typos, and never \"correct\" a longer legit domain.\n if (best && bestDist > 0 && bestDist <= 2 && Math.abs(domain.length - best.length) <= 2) {\n return `${local}@${best}`;\n }\n return null;\n}\n\n/** Full analysis of an email address. */\nexport function validateEmail(email: string, opts: ValidationOptions = {}): ValidationResult {\n const raw = typeof email === \"string\" ? email.trim() : \"\";\n const parts = splitEmail(raw);\n\n if (!isValidEmail(raw) || !parts) {\n return {\n valid: false,\n normalized: null,\n local: null,\n domain: null,\n disposable: false,\n role: false,\n free: false,\n suggestion: opts.suggestions === false ? null : suggestEmail(raw),\n reason: \"invalid syntax\",\n };\n }\n\n const local = parts.local;\n const domain = parts.domain.toLowerCase();\n return {\n valid: true,\n normalized: normalizeEmail(raw),\n local,\n domain,\n disposable: isDisposable(domain, opts.extraDisposable),\n role: isRoleAddress(local),\n free: isFreeProvider(domain),\n suggestion: opts.suggestions === false ? null : suggestEmail(raw),\n };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@lacspace/email-validate",
3
+ "version": "1.0.0",
4
+ "description": "Smart email validation — syntax, disposable/temp-mail detection, role & free-provider flags, Gmail normalization and 'did you mean?' typo suggestions. Zero-dependency, isomorphic.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "sideEffects": false,
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "email-validation",
31
+ "email-validator",
32
+ "disposable-email",
33
+ "temp-mail",
34
+ "email-typo",
35
+ "did-you-mean",
36
+ "normalize-email",
37
+ "role-account",
38
+ "typescript"
39
+ ],
40
+ "author": "Lacspace <contact@lacspace.com>",
41
+ "license": "MIT",
42
+ "homepage": "https://lacspace.com/packages",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/lacspace/npm-packages.git",
46
+ "directory": "email-validate"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/lacspace/npm-packages/issues"
50
+ },
51
+ "engines": {
52
+ "node": ">=18"
53
+ }
54
+ }