phasmid 0.0.1 → 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 +5 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/src/normalize.js +149 -0
- package/dist/src/normalize.js.map +1 -0
- package/dist/src/providers.js +182 -0
- package/dist/src/providers.js.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/src/normalize.d.ts +30 -0
- package/dist/types/src/normalize.d.ts.map +1 -0
- package/dist/types/src/providers.d.ts +20 -0
- package/dist/types/src/providers.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +100 -0
- package/dist/types/src/types.d.ts.map +1 -0
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright <2026> <Smiduweorc>
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
4
|
+
|
|
5
|
+
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phasmid: provider-aware email normalization and canonicalization.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { normalizeEmail, isSameEmail } from "Phasmid";
|
|
7
|
+
*
|
|
8
|
+
* normalizeEmail("John.Doe+newsletter@googlemail.com"); // "johndoe@gmail.com"
|
|
9
|
+
* isSameEmail("a.b@gmail.com", "ab@gmail.com"); // true
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export { normalizeEmail, normalizeEmailDetailed, getEmailProvider, isSameEmail, } from "./src/normalize.js";
|
|
13
|
+
export { DEFAULT_PROVIDERS } from "./src/providers.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,GACX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { DEFAULT_PROVIDERS } from "./providers.js";
|
|
2
|
+
/** Conservative fallback used for domains that match no provider. */
|
|
3
|
+
const CONSERVATIVE_DEFAULT = {
|
|
4
|
+
lowercaseLocal: false,
|
|
5
|
+
removeDots: false,
|
|
6
|
+
subaddressSeparators: [],
|
|
7
|
+
};
|
|
8
|
+
/** A basic domain shape: labels separated by dots, with a final TLD label. */
|
|
9
|
+
const DOMAIN_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/i;
|
|
10
|
+
/** Lazily-built registry for the default-only case (the common path). */
|
|
11
|
+
let defaultRegistry = null;
|
|
12
|
+
function buildRegistry(providers) {
|
|
13
|
+
const map = new Map();
|
|
14
|
+
for (const provider of providers) {
|
|
15
|
+
for (const domain of provider.domains) {
|
|
16
|
+
map.set(domain.toLowerCase(), provider);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return map;
|
|
20
|
+
}
|
|
21
|
+
function getRegistry(options) {
|
|
22
|
+
if (!options.providers && !options.replaceDefaultProviders) {
|
|
23
|
+
return (defaultRegistry ??= buildRegistry(DEFAULT_PROVIDERS));
|
|
24
|
+
}
|
|
25
|
+
const base = options.replaceDefaultProviders ? [] : DEFAULT_PROVIDERS;
|
|
26
|
+
// Later entries override earlier ones, so user providers take precedence.
|
|
27
|
+
return buildRegistry([...base, ...(options.providers ?? [])]);
|
|
28
|
+
}
|
|
29
|
+
/** Split on the last `@`, the way most parsers treat the local/domain boundary. */
|
|
30
|
+
function splitEmail(email) {
|
|
31
|
+
const at = email.lastIndexOf("@");
|
|
32
|
+
if (at <= 0 || at === email.length - 1)
|
|
33
|
+
return null;
|
|
34
|
+
return { local: email.slice(0, at), domain: email.slice(at + 1) };
|
|
35
|
+
}
|
|
36
|
+
/** A quoted local part (`"a b"@x.com`) is preserved verbatim. */
|
|
37
|
+
function isQuoted(local) {
|
|
38
|
+
return local.length >= 2 && local.startsWith("\"") && local.endsWith("\"");
|
|
39
|
+
}
|
|
40
|
+
function stripSubaddress(local, separators) {
|
|
41
|
+
let cut = -1;
|
|
42
|
+
let cutLen = 0;
|
|
43
|
+
for (const sep of separators) {
|
|
44
|
+
if (!sep)
|
|
45
|
+
continue;
|
|
46
|
+
const idx = local.indexOf(sep);
|
|
47
|
+
// Ignore a separator at index 0; cutting there yields an empty local part.
|
|
48
|
+
if (idx > 0 && (cut === -1 || idx < cut)) {
|
|
49
|
+
cut = idx;
|
|
50
|
+
cutLen = sep.length;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (cut === -1)
|
|
54
|
+
return { local, subaddress: null };
|
|
55
|
+
return { local: local.slice(0, cut), subaddress: local.slice(cut + cutLen) };
|
|
56
|
+
}
|
|
57
|
+
function isValidLocal(local) {
|
|
58
|
+
if (local.length === 0)
|
|
59
|
+
return false;
|
|
60
|
+
if (isQuoted(local))
|
|
61
|
+
return true;
|
|
62
|
+
return !/[\s@]/.test(local);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Normalize an email address and return the full structured result, including
|
|
66
|
+
* the matched provider, the stripped sub-address, and a validity flag.
|
|
67
|
+
*
|
|
68
|
+
* @throws {TypeError} if `email` is not a string.
|
|
69
|
+
*/
|
|
70
|
+
export function normalizeEmailDetailed(email, options = {}) {
|
|
71
|
+
if (typeof email !== "string") {
|
|
72
|
+
throw new TypeError(`Expected email to be a string, received ${typeof email}`);
|
|
73
|
+
}
|
|
74
|
+
const lowercaseDomain = options.lowercaseDomain ?? true;
|
|
75
|
+
const trimmed = email.trim();
|
|
76
|
+
const parts = splitEmail(trimmed);
|
|
77
|
+
if (!parts) {
|
|
78
|
+
return {
|
|
79
|
+
normalized: trimmed,
|
|
80
|
+
local: trimmed,
|
|
81
|
+
domain: "",
|
|
82
|
+
providerId: null,
|
|
83
|
+
subaddress: null,
|
|
84
|
+
valid: false,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const lookupDomain = parts.domain.toLowerCase();
|
|
88
|
+
const provider = getRegistry(options).get(lookupDomain) ?? null;
|
|
89
|
+
const rule = provider ?? options.defaultRule ?? CONSERVATIVE_DEFAULT;
|
|
90
|
+
let local = parts.local;
|
|
91
|
+
let subaddress = null;
|
|
92
|
+
if (!isQuoted(local)) {
|
|
93
|
+
const stripped = stripSubaddress(local, rule.subaddressSeparators ?? []);
|
|
94
|
+
local = stripped.local;
|
|
95
|
+
subaddress = stripped.subaddress;
|
|
96
|
+
if (rule.removeDots)
|
|
97
|
+
local = local.replace(/\./g, "");
|
|
98
|
+
if (rule.lowercaseLocal)
|
|
99
|
+
local = local.toLowerCase();
|
|
100
|
+
}
|
|
101
|
+
let domain = lowercaseDomain ? lookupDomain : parts.domain;
|
|
102
|
+
if (provider?.canonicalDomain) {
|
|
103
|
+
domain = lowercaseDomain
|
|
104
|
+
? provider.canonicalDomain.toLowerCase()
|
|
105
|
+
: provider.canonicalDomain;
|
|
106
|
+
}
|
|
107
|
+
const valid = isValidLocal(local) && DOMAIN_RE.test(domain);
|
|
108
|
+
return {
|
|
109
|
+
normalized: `${local}@${domain}`,
|
|
110
|
+
local,
|
|
111
|
+
domain,
|
|
112
|
+
providerId: provider?.id ?? null,
|
|
113
|
+
subaddress,
|
|
114
|
+
valid,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Normalize an email address to its canonical form.
|
|
119
|
+
*
|
|
120
|
+
* Applies the matching provider's rules (sub-address stripping, dot removal,
|
|
121
|
+
* case-folding, alias-domain collapsing) and returns the canonical string.
|
|
122
|
+
* Unknown domains get a conservative treatment: the domain is lowercased and
|
|
123
|
+
* the local part is left untouched.
|
|
124
|
+
*
|
|
125
|
+
* @throws {TypeError} if `email` is not a string.
|
|
126
|
+
*/
|
|
127
|
+
export function normalizeEmail(email, options) {
|
|
128
|
+
return normalizeEmailDetailed(email, options).normalized;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Return the id of the provider that handles the given address's domain, or
|
|
132
|
+
* `null` if no provider matches (or the input is not a valid address).
|
|
133
|
+
*/
|
|
134
|
+
export function getEmailProvider(email, options = {}) {
|
|
135
|
+
if (typeof email !== "string")
|
|
136
|
+
return null;
|
|
137
|
+
const parts = splitEmail(email.trim());
|
|
138
|
+
if (!parts)
|
|
139
|
+
return null;
|
|
140
|
+
return getRegistry(options).get(parts.domain.toLowerCase())?.id ?? null;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Returns `true` if two addresses normalize to the same canonical address,
|
|
144
|
+
* i.e. they deliver to the same mailbox under the configured rules.
|
|
145
|
+
*/
|
|
146
|
+
export function isSameEmail(a, b, options) {
|
|
147
|
+
return normalizeEmail(a, options) === normalizeEmail(b, options);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in provider rules.
|
|
3
|
+
*
|
|
4
|
+
* These encode the well-documented, widely-relied-upon behaviors of major mail
|
|
5
|
+
* providers. They are deliberately conservative: domains are only collapsed
|
|
6
|
+
* where aliases truly deliver to the same mailbox (Gmail), and local parts are
|
|
7
|
+
* only lowercased for providers known to be case-insensitive.
|
|
8
|
+
*
|
|
9
|
+
* Sources cross-checked while compiling this list:
|
|
10
|
+
* - Wikipedia, "Email address" (sub-addressing section).
|
|
11
|
+
* - aaronbassett's "Email sub addressing for different providers" gist.
|
|
12
|
+
* - validator.js `normalizeEmail` provider conventions.
|
|
13
|
+
* - Fastmail / Microsoft Learn / Proton provider documentation.
|
|
14
|
+
*
|
|
15
|
+
* Consumers can extend or override any of these via
|
|
16
|
+
* {@link NormalizeOptions.providers}.
|
|
17
|
+
*/
|
|
18
|
+
export const DEFAULT_PROVIDERS = Object.freeze([
|
|
19
|
+
{
|
|
20
|
+
// Gmail ignores dots, supports `+` tagging, and treats googlemail.com as
|
|
21
|
+
// an alias of gmail.com.
|
|
22
|
+
id: "gmail",
|
|
23
|
+
domains: ["gmail.com", "googlemail.com"],
|
|
24
|
+
canonicalDomain: "gmail.com",
|
|
25
|
+
lowercaseLocal: true,
|
|
26
|
+
removeDots: true,
|
|
27
|
+
subaddressSeparators: ["+"],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
// Microsoft consumer mail (Outlook.com / Hotmail / Live / MSN). Dots are
|
|
31
|
+
// significant; `+` tagging is supported. The domains are distinct
|
|
32
|
+
// mailboxes, so they are not collapsed.
|
|
33
|
+
id: "microsoft",
|
|
34
|
+
domains: [
|
|
35
|
+
"outlook.com",
|
|
36
|
+
"outlook.com.au",
|
|
37
|
+
"outlook.co.uk",
|
|
38
|
+
"outlook.fr",
|
|
39
|
+
"outlook.de",
|
|
40
|
+
"outlook.es",
|
|
41
|
+
"outlook.it",
|
|
42
|
+
"outlook.jp",
|
|
43
|
+
"hotmail.com",
|
|
44
|
+
"hotmail.co.uk",
|
|
45
|
+
"hotmail.com.au",
|
|
46
|
+
"hotmail.fr",
|
|
47
|
+
"hotmail.de",
|
|
48
|
+
"hotmail.it",
|
|
49
|
+
"hotmail.es",
|
|
50
|
+
"hotmail.ca",
|
|
51
|
+
"live.com",
|
|
52
|
+
"live.com.au",
|
|
53
|
+
"live.co.uk",
|
|
54
|
+
"live.fr",
|
|
55
|
+
"live.de",
|
|
56
|
+
"live.ca",
|
|
57
|
+
"msn.com",
|
|
58
|
+
"windowslive.com",
|
|
59
|
+
"passport.com",
|
|
60
|
+
],
|
|
61
|
+
lowercaseLocal: true,
|
|
62
|
+
subaddressSeparators: ["+"],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
// Yahoo historically uses a hyphen as its sub-address separator (its
|
|
66
|
+
// "disposable addresses" feature), not `+`.
|
|
67
|
+
id: "yahoo",
|
|
68
|
+
domains: [
|
|
69
|
+
"yahoo.com",
|
|
70
|
+
"yahoo.co.uk",
|
|
71
|
+
"yahoo.ie",
|
|
72
|
+
"yahoo.fr",
|
|
73
|
+
"yahoo.de",
|
|
74
|
+
"yahoo.es",
|
|
75
|
+
"yahoo.it",
|
|
76
|
+
"yahoo.ca",
|
|
77
|
+
"yahoo.in",
|
|
78
|
+
"yahoo.com.au",
|
|
79
|
+
"yahoo.com.br",
|
|
80
|
+
"yahoo.com.mx",
|
|
81
|
+
"yahoo.com.ar",
|
|
82
|
+
"yahoo.co.jp",
|
|
83
|
+
"ymail.com",
|
|
84
|
+
"rocketmail.com",
|
|
85
|
+
],
|
|
86
|
+
lowercaseLocal: true,
|
|
87
|
+
subaddressSeparators: ["-"],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
// Apple iCloud. me.com and mac.com forward to the same Apple ID, but we
|
|
91
|
+
// keep them distinct by default to avoid surprising collapses.
|
|
92
|
+
id: "icloud",
|
|
93
|
+
domains: ["icloud.com", "me.com", "mac.com"],
|
|
94
|
+
lowercaseLocal: true,
|
|
95
|
+
subaddressSeparators: ["+"],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
// Fastmail also supports subdomain addressing
|
|
99
|
+
// (user+tag@fastmail.com == tag@user.fastmail.com), which is not
|
|
100
|
+
// resolved here because it depends on the account's domain layout.
|
|
101
|
+
id: "fastmail",
|
|
102
|
+
domains: ["fastmail.com", "fastmail.fm"],
|
|
103
|
+
lowercaseLocal: true,
|
|
104
|
+
subaddressSeparators: ["+"],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "proton",
|
|
108
|
+
domains: ["protonmail.com", "protonmail.ch", "proton.me", "pm.me"],
|
|
109
|
+
lowercaseLocal: true,
|
|
110
|
+
subaddressSeparators: ["+"],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "yandex",
|
|
114
|
+
domains: [
|
|
115
|
+
"yandex.com",
|
|
116
|
+
"yandex.ru",
|
|
117
|
+
"ya.ru",
|
|
118
|
+
"yandex.by",
|
|
119
|
+
"yandex.kz",
|
|
120
|
+
"yandex.ua",
|
|
121
|
+
],
|
|
122
|
+
lowercaseLocal: true,
|
|
123
|
+
subaddressSeparators: ["+"],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: "zoho",
|
|
127
|
+
domains: ["zoho.com", "zohomail.com", "zoho.eu"],
|
|
128
|
+
lowercaseLocal: true,
|
|
129
|
+
subaddressSeparators: ["+"],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "mailfence",
|
|
133
|
+
domains: ["mailfence.com"],
|
|
134
|
+
lowercaseLocal: true,
|
|
135
|
+
subaddressSeparators: ["+"],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "runbox",
|
|
139
|
+
domains: ["runbox.com"],
|
|
140
|
+
lowercaseLocal: true,
|
|
141
|
+
subaddressSeparators: ["+"],
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
// Pobox is part of the Fastmail family.
|
|
145
|
+
id: "pobox",
|
|
146
|
+
domains: ["pobox.com"],
|
|
147
|
+
lowercaseLocal: true,
|
|
148
|
+
subaddressSeparators: ["+"],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: "tutanota",
|
|
152
|
+
domains: [
|
|
153
|
+
"tutanota.com",
|
|
154
|
+
"tutanota.de",
|
|
155
|
+
"tutamail.com",
|
|
156
|
+
"tuta.com",
|
|
157
|
+
"tuta.io",
|
|
158
|
+
"keemail.me",
|
|
159
|
+
],
|
|
160
|
+
lowercaseLocal: true,
|
|
161
|
+
subaddressSeparators: ["+"],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: "posteo",
|
|
165
|
+
domains: ["posteo.de", "posteo.net"],
|
|
166
|
+
lowercaseLocal: true,
|
|
167
|
+
subaddressSeparators: ["+"],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "mailbox",
|
|
171
|
+
domains: ["mailbox.org"],
|
|
172
|
+
lowercaseLocal: true,
|
|
173
|
+
subaddressSeparators: ["+"],
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
// AOL is case-insensitive but does not support `+` tagging.
|
|
177
|
+
id: "aol",
|
|
178
|
+
domains: ["aol.com", "aim.com"],
|
|
179
|
+
lowercaseLocal: true,
|
|
180
|
+
},
|
|
181
|
+
]);
|
|
182
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/providers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phasmid: provider-aware email normalization and canonicalization.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { normalizeEmail, isSameEmail } from "Phasmid";
|
|
7
|
+
*
|
|
8
|
+
* normalizeEmail("John.Doe+newsletter@googlemail.com"); // "johndoe@gmail.com"
|
|
9
|
+
* isSameEmail("a.b@gmail.com", "ab@gmail.com"); // true
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export { normalizeEmail, normalizeEmailDetailed, getEmailProvider, isSameEmail, } from "./src/normalize.js";
|
|
13
|
+
export { DEFAULT_PROVIDERS } from "./src/providers.js";
|
|
14
|
+
export type { ProviderRule, DefaultRule, LocalPartRules, NormalizeOptions, NormalizedEmail, } from "./src/types.js";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,GACX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,YAAY,EACX,YAAY,EACZ,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,eAAe,GACf,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { NormalizeOptions, NormalizedEmail } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize an email address and return the full structured result, including
|
|
4
|
+
* the matched provider, the stripped sub-address, and a validity flag.
|
|
5
|
+
*
|
|
6
|
+
* @throws {TypeError} if `email` is not a string.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeEmailDetailed(email: string, options?: NormalizeOptions): NormalizedEmail;
|
|
9
|
+
/**
|
|
10
|
+
* Normalize an email address to its canonical form.
|
|
11
|
+
*
|
|
12
|
+
* Applies the matching provider's rules (sub-address stripping, dot removal,
|
|
13
|
+
* case-folding, alias-domain collapsing) and returns the canonical string.
|
|
14
|
+
* Unknown domains get a conservative treatment: the domain is lowercased and
|
|
15
|
+
* the local part is left untouched.
|
|
16
|
+
*
|
|
17
|
+
* @throws {TypeError} if `email` is not a string.
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeEmail(email: string, options?: NormalizeOptions): string;
|
|
20
|
+
/**
|
|
21
|
+
* Return the id of the provider that handles the given address's domain, or
|
|
22
|
+
* `null` if no provider matches (or the input is not a valid address).
|
|
23
|
+
*/
|
|
24
|
+
export declare function getEmailProvider(email: string, options?: NormalizeOptions): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Returns `true` if two addresses normalize to the same canonical address,
|
|
27
|
+
* i.e. they deliver to the same mailbox under the configured rules.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isSameEmail(a: string, b: string, options?: NormalizeOptions): boolean;
|
|
30
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/normalize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEX,gBAAgB,EAChB,eAAe,EAEf,MAAM,YAAY,CAAC;AA0EpB;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC5B,eAAe,CAsDjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACxB,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC5B,MAAM,GAAG,IAAI,CAKf;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAC1B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAET"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ProviderRule } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in provider rules.
|
|
4
|
+
*
|
|
5
|
+
* These encode the well-documented, widely-relied-upon behaviors of major mail
|
|
6
|
+
* providers. They are deliberately conservative: domains are only collapsed
|
|
7
|
+
* where aliases truly deliver to the same mailbox (Gmail), and local parts are
|
|
8
|
+
* only lowercased for providers known to be case-insensitive.
|
|
9
|
+
*
|
|
10
|
+
* Sources cross-checked while compiling this list:
|
|
11
|
+
* - Wikipedia, "Email address" (sub-addressing section).
|
|
12
|
+
* - aaronbassett's "Email sub addressing for different providers" gist.
|
|
13
|
+
* - validator.js `normalizeEmail` provider conventions.
|
|
14
|
+
* - Fastmail / Microsoft Learn / Proton provider documentation.
|
|
15
|
+
*
|
|
16
|
+
* Consumers can extend or override any of these via
|
|
17
|
+
* {@link NormalizeOptions.providers}.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_PROVIDERS: readonly ProviderRule[];
|
|
20
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,YAAY,EAmKnD,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The set of transformations that can be applied to the local part of an
|
|
3
|
+
* address. Both {@link ProviderRule} and {@link DefaultRule} share these
|
|
4
|
+
* fields so the engine can treat a matched provider and a fallback rule
|
|
5
|
+
* uniformly.
|
|
6
|
+
*/
|
|
7
|
+
export interface LocalPartRules {
|
|
8
|
+
/**
|
|
9
|
+
* Lowercase the local part. Most consumer providers treat the local part
|
|
10
|
+
* case-insensitively, so this is enabled for the built-in providers. The
|
|
11
|
+
* email spec (RFC 5321) technically allows case-sensitive local parts, so
|
|
12
|
+
* it is left disabled for unknown domains by default.
|
|
13
|
+
*/
|
|
14
|
+
lowercaseLocal?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Remove all dots (`.`) from the local part. This is Gmail's behavior:
|
|
17
|
+
* `john.doe@gmail.com` and `johndoe@gmail.com` are the same mailbox.
|
|
18
|
+
*/
|
|
19
|
+
removeDots?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Characters that begin a "sub-address" (also called plus-addressing or
|
|
22
|
+
* tagging). Everything from the first occurrence of any separator to the
|
|
23
|
+
* end of the local part is stripped. Gmail/Outlook/etc. use `"+"`; Yahoo
|
|
24
|
+
* historically uses `"-"`.
|
|
25
|
+
*
|
|
26
|
+
* A separator at index 0 is ignored, because stripping it would leave an
|
|
27
|
+
* empty local part.
|
|
28
|
+
*/
|
|
29
|
+
subaddressSeparators?: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A rule describing how a specific email provider's addresses should be
|
|
33
|
+
* canonicalized.
|
|
34
|
+
*/
|
|
35
|
+
export interface ProviderRule extends LocalPartRules {
|
|
36
|
+
/** Stable identifier for the provider, e.g. `"gmail"`. */
|
|
37
|
+
id: string;
|
|
38
|
+
/**
|
|
39
|
+
* The domains this rule applies to. Matched case-insensitively. The first
|
|
40
|
+
* provider registered for a domain wins, and user-supplied providers
|
|
41
|
+
* override the built-ins.
|
|
42
|
+
*/
|
|
43
|
+
domains: string[];
|
|
44
|
+
/**
|
|
45
|
+
* Collapse every matched domain to this single canonical domain. Used for
|
|
46
|
+
* provider aliases that deliver to the same mailbox, e.g. `googlemail.com`
|
|
47
|
+
* -> `gmail.com`.
|
|
48
|
+
*/
|
|
49
|
+
canonicalDomain?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The fallback rule applied to domains that do not match any provider. It is
|
|
53
|
+
* the same as a {@link ProviderRule} minus the identity fields, and it cannot
|
|
54
|
+
* rewrite the domain.
|
|
55
|
+
*/
|
|
56
|
+
export type DefaultRule = LocalPartRules;
|
|
57
|
+
/**
|
|
58
|
+
* Options accepted by the normalization functions.
|
|
59
|
+
*/
|
|
60
|
+
export interface NormalizeOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Additional provider rules, or overrides for the built-in providers.
|
|
63
|
+
* Matched by domain; entries here take precedence over the built-ins.
|
|
64
|
+
*/
|
|
65
|
+
providers?: ProviderRule[];
|
|
66
|
+
/**
|
|
67
|
+
* Ignore the built-in provider list entirely and use only the providers
|
|
68
|
+
* supplied in {@link NormalizeOptions.providers}. Defaults to `false`.
|
|
69
|
+
*/
|
|
70
|
+
replaceDefaultProviders?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Rule applied to domains that match no provider. Defaults to a
|
|
73
|
+
* conservative rule that only lowercases the domain and leaves the local
|
|
74
|
+
* part untouched.
|
|
75
|
+
*/
|
|
76
|
+
defaultRule?: DefaultRule;
|
|
77
|
+
/**
|
|
78
|
+
* Lowercase the domain. Domains are case-insensitive per RFC 1035, so this
|
|
79
|
+
* defaults to `true`. Disabling it is rarely useful but available.
|
|
80
|
+
*/
|
|
81
|
+
lowercaseDomain?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The structured result of normalizing an address.
|
|
85
|
+
*/
|
|
86
|
+
export interface NormalizedEmail {
|
|
87
|
+
/** The fully normalized address, `${local}@${domain}`. */
|
|
88
|
+
normalized: string;
|
|
89
|
+
/** The normalized local part (before the `@`). */
|
|
90
|
+
local: string;
|
|
91
|
+
/** The normalized domain (after the `@`). */
|
|
92
|
+
domain: string;
|
|
93
|
+
/** The id of the provider that matched, or `null` if none did. */
|
|
94
|
+
providerId: string | null;
|
|
95
|
+
/** The sub-address ("tag") that was stripped, or `null` if there was none. */
|
|
96
|
+
subaddress: string | null;
|
|
97
|
+
/** Whether the input looks like a syntactically valid address. */
|
|
98
|
+
valid: boolean;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAa,SAAQ,cAAc;IACnD,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IAEX;;;;OAIG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAE3B;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8EAA8E;IAC9E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kEAAkE;IAClE,KAAK,EAAE,OAAO,CAAC;CACf"}
|