@konfeature/ap-email-guessr 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/package.json +9 -40
  2. package/src/i18n/translation.json +17 -0
  3. package/src/index.d.ts.map +1 -0
  4. package/src/index.js.map +1 -0
  5. package/src/lib/actions/find-email.d.ts.map +1 -0
  6. package/{dist/src → src}/lib/actions/find-email.js +35 -31
  7. package/src/lib/actions/find-email.js.map +1 -0
  8. package/src/lib/actions/generate-emails.d.ts.map +1 -0
  9. package/{dist/src → src}/lib/actions/generate-emails.js +13 -9
  10. package/src/lib/actions/generate-emails.js.map +1 -0
  11. package/src/lib/common/dns.d.ts.map +1 -0
  12. package/src/lib/common/dns.js +40 -0
  13. package/src/lib/common/dns.js.map +1 -0
  14. package/src/lib/common/find-email.d.ts.map +1 -0
  15. package/src/lib/common/find-email.js +82 -0
  16. package/src/lib/common/find-email.js.map +1 -0
  17. package/src/lib/common/find-person.d.ts.map +1 -0
  18. package/src/lib/common/find-person.js +98 -0
  19. package/src/lib/common/find-person.js.map +1 -0
  20. package/src/lib/common/http.d.ts.map +1 -0
  21. package/{dist/src → src}/lib/common/http.js +5 -7
  22. package/src/lib/common/http.js.map +1 -0
  23. package/src/lib/common/mx-fingerprint.d.ts.map +1 -0
  24. package/{dist/src → src}/lib/common/mx-fingerprint.js +4 -3
  25. package/src/lib/common/mx-fingerprint.js.map +1 -0
  26. package/src/lib/common/patterns.d.ts.map +1 -0
  27. package/{dist/src → src}/lib/common/patterns.js +6 -5
  28. package/src/lib/common/patterns.js.map +1 -0
  29. package/src/lib/common/providers/o365.d.ts.map +1 -0
  30. package/{dist/src → src}/lib/common/providers/o365.js +81 -73
  31. package/src/lib/common/providers/o365.js.map +1 -0
  32. package/src/lib/common/verifier.d.ts.map +1 -0
  33. package/src/lib/common/verifier.js.map +1 -0
  34. package/src/lib/common/verifiers/no2bounce-verifier.d.ts.map +1 -0
  35. package/src/lib/common/verifiers/no2bounce-verifier.js +135 -0
  36. package/src/lib/common/verifiers/no2bounce-verifier.js.map +1 -0
  37. package/src/lib/common/verifiers/o365-verifier.d.ts.map +1 -0
  38. package/src/lib/common/verifiers/o365-verifier.js +33 -0
  39. package/src/lib/common/verifiers/o365-verifier.js.map +1 -0
  40. package/README.md +0 -128
  41. package/dist/src/lib/common/dns.js +0 -37
  42. package/dist/src/lib/common/find-email.js +0 -78
  43. package/dist/src/lib/common/find-person.js +0 -102
  44. package/dist/src/lib/common/verifiers/no2bounce-verifier.js +0 -123
  45. package/dist/src/lib/common/verifiers/o365-verifier.js +0 -30
  46. /package/{dist/src → src}/index.d.ts +0 -0
  47. /package/{dist/src → src}/index.js +0 -0
  48. /package/{dist/src → src}/lib/actions/find-email.d.ts +0 -0
  49. /package/{dist/src → src}/lib/actions/generate-emails.d.ts +0 -0
  50. /package/{dist/src → src}/lib/common/dns.d.ts +0 -0
  51. /package/{dist/src → src}/lib/common/find-email.d.ts +0 -0
  52. /package/{dist/src → src}/lib/common/find-person.d.ts +0 -0
  53. /package/{dist/src → src}/lib/common/http.d.ts +0 -0
  54. /package/{dist/src → src}/lib/common/mx-fingerprint.d.ts +0 -0
  55. /package/{dist/src → src}/lib/common/patterns.d.ts +0 -0
  56. /package/{dist/src → src}/lib/common/providers/o365.d.ts +0 -0
  57. /package/{dist/src → src}/lib/common/verifier.d.ts +0 -0
  58. /package/{dist/src → src}/lib/common/verifier.js +0 -0
  59. /package/{dist/src → src}/lib/common/verifiers/no2bounce-verifier.d.ts +0 -0
  60. /package/{dist/src → src}/lib/common/verifiers/o365-verifier.d.ts +0 -0
@@ -25,6 +25,7 @@ exports.isMicrosoftConsumerDomain = isMicrosoftConsumerDomain;
25
25
  exports.interpretIfExists = interpretIfExists;
26
26
  exports.getUserRealm = getUserRealm;
27
27
  exports.checkO365Account = checkO365Account;
28
+ const tslib_1 = require("tslib");
28
29
  const http_1 = require("../http");
29
30
  exports.O365_UNCHECKED = {
30
31
  checked: false,
@@ -76,55 +77,60 @@ function interpretIfExists(code) {
76
77
  return null;
77
78
  }
78
79
  /** Classify a domain's Microsoft namespace. Returns null on any failure. */
79
- async function getUserRealm(domain, timeoutMs) {
80
- const login = encodeURIComponent(`probe@${domain}`);
81
- try {
82
- const res = await (0, http_1.httpRequest)({
83
- url: `https://login.microsoftonline.com/getuserrealm.srf?login=${login}&json=1`,
84
- method: "GET",
85
- timeoutMs,
86
- });
87
- if (res.status !== 200) {
80
+ function getUserRealm(domain, timeoutMs) {
81
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
82
+ const login = encodeURIComponent(`probe@${domain}`);
83
+ try {
84
+ const res = yield (0, http_1.httpRequest)({
85
+ url: `https://login.microsoftonline.com/getuserrealm.srf?login=${login}&json=1`,
86
+ method: "GET",
87
+ timeoutMs,
88
+ });
89
+ if (res.status !== 200) {
90
+ return null;
91
+ }
92
+ const data = JSON.parse(res.body);
93
+ const ns = data.NameSpaceType;
94
+ if (ns === "Managed" || ns === "Federated" || ns === "Unknown") {
95
+ return ns;
96
+ }
88
97
  return null;
89
98
  }
90
- const data = JSON.parse(res.body);
91
- const ns = data.NameSpaceType;
92
- if (ns === "Managed" || ns === "Federated" || ns === "Unknown") {
93
- return ns;
99
+ catch (_a) {
100
+ return null;
94
101
  }
95
- return null;
96
- }
97
- catch {
98
- return null;
99
- }
102
+ });
100
103
  }
101
104
  /** Query GetCredentialType for a single address. Returns null code on failure. */
102
- async function probeCredentialType(email, timeoutMs) {
103
- try {
104
- const res = await (0, http_1.httpRequest)({
105
- url: "https://login.microsoftonline.com/common/GetCredentialType?mkt=en-US",
106
- method: "POST",
107
- headers: { "Content-Type": "application/json; charset=UTF-8" },
108
- body: JSON.stringify({
109
- Username: email,
110
- isOtherIdpSupported: true,
111
- }),
112
- timeoutMs,
113
- });
114
- if (res.status !== 200) {
105
+ function probeCredentialType(email, timeoutMs) {
106
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
107
+ var _a;
108
+ try {
109
+ const res = yield (0, http_1.httpRequest)({
110
+ url: "https://login.microsoftonline.com/common/GetCredentialType?mkt=en-US",
111
+ method: "POST",
112
+ headers: { "Content-Type": "application/json; charset=UTF-8" },
113
+ body: JSON.stringify({
114
+ Username: email,
115
+ isOtherIdpSupported: true,
116
+ }),
117
+ timeoutMs,
118
+ });
119
+ if (res.status !== 200) {
120
+ return { ifExistsResult: null, throttled: false };
121
+ }
122
+ const data = JSON.parse(res.body);
123
+ return {
124
+ ifExistsResult: typeof data.IfExistsResult === "number"
125
+ ? data.IfExistsResult
126
+ : null,
127
+ throttled: ((_a = data.ThrottleStatus) !== null && _a !== void 0 ? _a : 0) !== 0,
128
+ };
129
+ }
130
+ catch (_b) {
115
131
  return { ifExistsResult: null, throttled: false };
116
132
  }
117
- const data = JSON.parse(res.body);
118
- return {
119
- ifExistsResult: typeof data.IfExistsResult === "number"
120
- ? data.IfExistsResult
121
- : null,
122
- throttled: (data.ThrottleStatus ?? 0) !== 0,
123
- };
124
- }
125
- catch {
126
- return { ifExistsResult: null, throttled: false };
127
- }
133
+ });
128
134
  }
129
135
  /**
130
136
  * Run the account-existence check for one email, given a pre-resolved namespace
@@ -132,40 +138,42 @@ async function probeCredentialType(email, timeoutMs) {
132
138
  * be Microsoft-backed (Managed namespace, Microsoft MX, or a consumer domain);
133
139
  * otherwise GetCredentialType returns noise for unrelated domains.
134
140
  */
135
- async function checkO365Account(email, namespace, applicable, timeoutMs) {
136
- if (!applicable) {
137
- return { ...exports.O365_UNCHECKED, namespace, reason: "not_microsoft_domain" };
138
- }
139
- const probe = await probeCredentialType(email, timeoutMs);
140
- if (probe.throttled) {
141
+ function checkO365Account(email, namespace, applicable, timeoutMs) {
142
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
143
+ if (!applicable) {
144
+ return Object.assign(Object.assign({}, exports.O365_UNCHECKED), { namespace, reason: "not_microsoft_domain" });
145
+ }
146
+ const probe = yield probeCredentialType(email, timeoutMs);
147
+ if (probe.throttled) {
148
+ return {
149
+ checked: false,
150
+ exists: null,
151
+ namespace,
152
+ ifExistsResult: probe.ifExistsResult,
153
+ reason: "throttled",
154
+ };
155
+ }
156
+ if (probe.ifExistsResult === null) {
157
+ return {
158
+ checked: false,
159
+ exists: null,
160
+ namespace,
161
+ ifExistsResult: null,
162
+ reason: "no_result",
163
+ };
164
+ }
165
+ const exists = interpretIfExists(probe.ifExistsResult);
141
166
  return {
142
- checked: false,
143
- exists: null,
167
+ checked: exists !== null,
168
+ exists,
144
169
  namespace,
145
170
  ifExistsResult: probe.ifExistsResult,
146
- reason: "throttled",
147
- };
148
- }
149
- if (probe.ifExistsResult === null) {
150
- return {
151
- checked: false,
152
- exists: null,
153
- namespace,
154
- ifExistsResult: null,
155
- reason: "no_result",
171
+ reason: exists === true
172
+ ? "account_exists"
173
+ : exists === false
174
+ ? "account_not_found"
175
+ : "inconclusive",
156
176
  };
157
- }
158
- const exists = interpretIfExists(probe.ifExistsResult);
159
- return {
160
- checked: exists !== null,
161
- exists,
162
- namespace,
163
- ifExistsResult: probe.ifExistsResult,
164
- reason: exists === true
165
- ? "account_exists"
166
- : exists === false
167
- ? "account_not_found"
168
- : "inconclusive",
169
- };
177
+ });
170
178
  }
171
179
  //# sourceMappingURL=o365.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"o365.js","sourceRoot":"","sources":["../../../../../src/lib/common/providers/o365.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../../../src/lib/common/verifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;IACvB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACjD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../../../src/lib/common/verifier.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no2bounce-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lib/common/verifiers/no2bounce-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAiB,aAAa,EAAE,MAAM,aAAa,CAAC;AAI1E,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD,UAAU,UAAU;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACrB;AAKD,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,GAAG,aAAa,CAiBzD;AAaD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,QAAQ,CAiF3E"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ /**
3
+ * Verifier adapter for the no2bounce API (wire format confirmed against the
4
+ * live API).
5
+ *
6
+ * Async flow: POST a 1-email batch to get a `trackingId` (under `data`), then
7
+ * GET-poll `?trackingId=` until the *top-level* `overallStatus` is "Completed".
8
+ * For a single email the top-level count fields are that email's verdict.
9
+ * Billing is 1 credit per email (`creditDebited`), with no refund on undeliverable.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.decodeSingle = decodeSingle;
13
+ exports.createNo2BounceVerifier = createNo2BounceVerifier;
14
+ const tslib_1 = require("tslib");
15
+ const http_1 = require("../http");
16
+ const ENDPOINT = "https://connect.no2bounce.com/v2/n2b_validate_bulk";
17
+ // no2bounce risk-scores accept-all domains per address: "Deliverable/AcceptAll"
18
+ // is a predicted hit, "UnDeliverable/AcceptAll" a predicted miss, and
19
+ // "Risky/AcceptAll" genuinely uncertain (so we stop on it).
20
+ function decodeSingle(r) {
21
+ var _a, _b, _c, _d, _e;
22
+ if (((_a = r.Deliverable) !== null && _a !== void 0 ? _a : 0) >= 1) {
23
+ return { verdict: "valid", catchAll: false };
24
+ }
25
+ if (((_b = r["Deliverable/AcceptAll"]) !== null && _b !== void 0 ? _b : 0) >= 1) {
26
+ return { verdict: "valid", catchAll: true };
27
+ }
28
+ if (((_c = r["Risky/AcceptAll"]) !== null && _c !== void 0 ? _c : 0) >= 1) {
29
+ return { verdict: "catch_all", catchAll: true };
30
+ }
31
+ if (((_d = r.Undeliverable) !== null && _d !== void 0 ? _d : 0) >= 1) {
32
+ return { verdict: "invalid", catchAll: false };
33
+ }
34
+ if (((_e = r["UnDeliverable/AcceptAll"]) !== null && _e !== void 0 ? _e : 0) >= 1) {
35
+ return { verdict: "invalid", catchAll: true };
36
+ }
37
+ return { verdict: "unknown", catchAll: false };
38
+ }
39
+ function isComplete(r) {
40
+ var _a, _b;
41
+ return (String((_a = r.overallStatus) !== null && _a !== void 0 ? _a : "")
42
+ .toLowerCase()
43
+ .startsWith("complet") || ((_b = r.percent) !== null && _b !== void 0 ? _b : 0) >= 100);
44
+ }
45
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
46
+ function createNo2BounceVerifier(options) {
47
+ var _a, _b;
48
+ const pollIntervalMs = (_a = options.pollIntervalMs) !== null && _a !== void 0 ? _a : 2000;
49
+ const maxWaitMs = (_b = options.maxWaitMs) !== null && _b !== void 0 ? _b : 30000;
50
+ const authHeader = { apitoken: options.apitoken };
51
+ function submit(email) {
52
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
53
+ var _a, _b, _c;
54
+ const res = yield (0, http_1.httpRequest)({
55
+ url: ENDPOINT,
56
+ method: "POST",
57
+ headers: Object.assign(Object.assign({}, authHeader), { "Content-Type": "application/json" }),
58
+ body: JSON.stringify({ emailList: [email] }),
59
+ timeoutMs: options.timeoutMs,
60
+ });
61
+ if (res.status !== 200) {
62
+ throw new Error(`submit_${res.status}`);
63
+ }
64
+ const json = JSON.parse(res.body);
65
+ const id = (_b = (_a = json.data) === null || _a === void 0 ? void 0 : _a.trackingId) !== null && _b !== void 0 ? _b : (_c = json.data) === null || _c === void 0 ? void 0 : _c.taskId;
66
+ return id === undefined ? undefined : String(id);
67
+ });
68
+ }
69
+ function poll(trackingId) {
70
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
71
+ const url = `${ENDPOINT}?trackingId=${encodeURIComponent(trackingId)}`;
72
+ const deadline = Date.now() + maxWaitMs;
73
+ while (Date.now() < deadline) {
74
+ yield sleep(pollIntervalMs);
75
+ try {
76
+ const res = yield (0, http_1.httpRequest)({
77
+ url,
78
+ method: "GET",
79
+ headers: authHeader,
80
+ timeoutMs: options.timeoutMs,
81
+ });
82
+ if (res.status !== 200) {
83
+ continue;
84
+ }
85
+ const parsed = JSON.parse(res.body);
86
+ if (isComplete(parsed)) {
87
+ return parsed;
88
+ }
89
+ }
90
+ catch (_a) {
91
+ // Transient poll error; keep trying until the deadline.
92
+ }
93
+ }
94
+ return null;
95
+ });
96
+ }
97
+ return {
98
+ name: "no2bounce",
99
+ verify(email) {
100
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
101
+ var _a;
102
+ let trackingId;
103
+ try {
104
+ trackingId = yield submit(email);
105
+ }
106
+ catch (error) {
107
+ // Submission rejected → no credit charged.
108
+ return {
109
+ email,
110
+ verdict: "unknown",
111
+ creditsUsed: 0,
112
+ reason: error instanceof Error ? error.message : "submit_failed",
113
+ };
114
+ }
115
+ if (!trackingId) {
116
+ return { email, verdict: "unknown", creditsUsed: 0, reason: "no_tracking_id" };
117
+ }
118
+ const parsed = yield poll(trackingId);
119
+ if (!parsed) {
120
+ return { email, verdict: "unknown", creditsUsed: 1, reason: "poll_timeout" };
121
+ }
122
+ const { verdict, catchAll } = decodeSingle(parsed);
123
+ return {
124
+ email,
125
+ verdict,
126
+ catchAll,
127
+ creditsUsed: (_a = parsed.creditDebited) !== null && _a !== void 0 ? _a : 1,
128
+ reason: `n2b_${verdict}${catchAll ? "_acceptall" : ""}`,
129
+ raw: parsed,
130
+ };
131
+ });
132
+ },
133
+ };
134
+ }
135
+ //# sourceMappingURL=no2bounce-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no2bounce-verifier.js","sourceRoot":"","sources":["../../../../../src/lib/common/verifiers/no2bounce-verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"o365-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lib/common/verifiers/o365-verifier.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAE3D,wBAAgB,kBAAkB,CAC9B,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,OAAO,EACnB,SAAS,EAAE,MAAM,GAClB,QAAQ,CAyBV"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ /**
3
+ * Verifier adapter for the direct Microsoft 365 account check. Free (no
4
+ * credits): it asks Azure AD whether the account exists over HTTPS, so it never
5
+ * touches port 25 and never spends a no2bounce credit.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.createO365Verifier = createO365Verifier;
9
+ const tslib_1 = require("tslib");
10
+ const o365_1 = require("../providers/o365");
11
+ function createO365Verifier(namespace, applicable, timeoutMs) {
12
+ return {
13
+ name: "o365",
14
+ verify(email) {
15
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
16
+ const result = yield (0, o365_1.checkO365Account)(email, namespace, applicable, timeoutMs);
17
+ const verdict = result.exists === true
18
+ ? "valid"
19
+ : result.exists === false
20
+ ? "invalid"
21
+ : "unknown";
22
+ return {
23
+ email,
24
+ verdict,
25
+ creditsUsed: 0,
26
+ reason: result.reason,
27
+ raw: result,
28
+ };
29
+ });
30
+ },
31
+ };
32
+ }
33
+ //# sourceMappingURL=o365-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"o365-verifier.js","sourceRoot":"","sources":["../../../../../src/lib/common/verifiers/o365-verifier.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAKH,gDA6BC;;AAhCD,4CAAyE;AAGzE,SAAgB,kBAAkB,CAC9B,SAAwB,EACxB,UAAmB,EACnB,SAAiB;IAEjB,OAAO;QACH,IAAI,EAAE,MAAM;QACN,MAAM,CAAC,KAAa;;gBACtB,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAgB,EACjC,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,CACZ,CAAC;gBACF,MAAM,OAAO,GACT,MAAM,CAAC,MAAM,KAAK,IAAI;oBAClB,CAAC,CAAC,OAAO;oBACT,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK;wBACvB,CAAC,CAAC,SAAS;wBACX,CAAC,CAAC,SAAS,CAAC;gBACtB,OAAO;oBACH,KAAK;oBACL,OAAO;oBACP,WAAW,EAAE,CAAC;oBACd,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,GAAG,EAAE,MAAM;iBACd,CAAC;YACN,CAAC;SAAA;KACJ,CAAC;AACN,CAAC"}
package/README.md DELETED
@@ -1,128 +0,0 @@
1
- # ap-email-guessr
2
-
3
- An [Activepieces](https://www.activepieces.com) community piece that finds a person's email
4
- address from their name and company domain. It ships two actions:
5
-
6
- | Action | What it does |
7
- | --- | --- |
8
- | **Generate Email List** | Builds likely addresses from a first name, last name and domain, ordered by real-world corporate naming frequency (`john.doe@`, `jdoe@`, `john@`, ...). |
9
- | **Find Email** | Generates the candidates, then verifies them top-down — stopping at the first hit or on a catch-all domain — routing Microsoft domains through a free O365 check and everything else through [no2bounce](https://www.no2bounce.com). Returns the found address, a verdict and the credits spent. |
10
-
11
- ## Setup
12
-
13
- The piece auth is an optional **no2bounce API Token** (Settings → API in no2bounce). It is only
14
- needed to verify **non-Microsoft** domains; Microsoft-backed domains are verified for free via the
15
- O365 account check, so the token can be left empty if you only target those.
16
-
17
- ## Actions
18
-
19
- ### Generate Email List
20
-
21
- Inputs: `firstName`, `lastName`, `domain`, plus optional `patternSet` (`common` ≈ 10 patterns /
22
- `all` ≈ 20, default `all`) and `maxVariants` (hard cap).
23
-
24
- Output — candidates ordered most-likely first:
25
-
26
- ```json
27
- { "emails": ["john.doe@example.com", "jdoe@example.com", "john@example.com"], "count": 3 }
28
- ```
29
-
30
- Names are normalized (accents stripped, lowercased, non-alphanumerics removed) and the domain is
31
- cleaned of protocol/path/leading `@`.
32
-
33
- ### Find Email
34
-
35
- Inputs:
36
-
37
- - `firstName`, `lastName`, `domain` (required).
38
- - `patternSet` (optional, default `common`) — `common` checks only the ~10 highest-probability
39
- patterns; `all` considers the full ~20.
40
- - `maxChecks` (optional) — hard ceiling on how many candidates are verified before giving up. This
41
- is the per-person credit cap.
42
- - `useO365` (optional, default `true`) — verify Microsoft-backed domains with the free Azure AD
43
- account check instead of spending no2bounce credits.
44
- - `timeout` (optional, default `15`) — per-request timeout in seconds.
45
-
46
- Output:
47
-
48
- ```json
49
- {
50
- "found": true,
51
- "email": "jessie.han@cupshe.com",
52
- "status": "valid",
53
- "confidence": 0.9,
54
- "catchAll": false,
55
- "domain": "cupshe.com",
56
- "mxProvider": "microsoft",
57
- "verifier": "o365",
58
- "reason": "o365_valid",
59
- "creditsUsed": 0,
60
- "candidatesChecked": 1,
61
- "candidatesConsidered": 10,
62
- "attempts": [{ "email": "jessie.han@cupshe.com", "verdict": "valid", "reason": "account_exists" }]
63
- }
64
- ```
65
-
66
- ## How verification works
67
-
68
- **Routing.** Per domain the piece resolves MX and fingerprints the provider:
69
-
70
- - **Microsoft-backed** (Microsoft/consumer MX, or a `Managed` Azure AD realm on a domain that is
71
- *not* a known non-Microsoft mailbox host) → the **free O365 check** (`GetCredentialType`). No port
72
- 25, no credits. The "Managed realm on a Google/Zoho domain" case is deliberately excluded — that
73
- is a leftover tenant, not Microsoft mail, and trusting it produces false negatives.
74
- - **Everything else** → **no2bounce**. no2bounce is async: submit a 1-email batch to get a
75
- `trackingId` (under `data`), then poll `?trackingId=` until the top-level `overallStatus` is
76
- `Completed`. For a single email the top-level counts — `Deliverable`, `Undeliverable`,
77
- `Deliverable/AcceptAll`, `UnDeliverable/AcceptAll`, `Risky/AcceptAll` — are that email's verdict.
78
-
79
- **Credit minimization.** Candidates are verified in likelihood order and the search:
80
-
81
- 1. **uses no2bounce's per-address catch-all scoring** — on an accept-all domain a predicted-deliverable
82
- address counts as a hit (with reduced confidence), a predicted-undeliverable one is skipped, and a
83
- genuinely `Risky/AcceptAll` result stops the search;
84
- 2. **verifies non-Microsoft candidates in concurrent rounds of 5 and stops at the first round with a
85
- hit** (early-stop) — checking 5 at a time is faster than one-by-one, but since no2bounce bills per
86
- email with no refund a round is paid for in full once submitted (a hit at candidate #3 still costs
87
- the first round of 5), so the search stops as soon as a round yields a valid address or a catch-all
88
- rather than walking the whole list;
89
- 3. uses the **`common` pattern set** by default, capping the not-found tail at ~10 instead of ~20.
90
-
91
- no2bounce bills **1 credit per verified email**; the O365 path is **0 credits**. The actual spend is
92
- returned as `creditsUsed`.
93
-
94
- ## Verdicts
95
-
96
- | `status` | Meaning |
97
- | --- | --- |
98
- | `valid` | The mailbox exists (`found: true`, with `email`). |
99
- | `invalid` | No candidate verified, or null MX / no MX. |
100
- | `catch_all` | Domain accepts everything — the specific address can't be confirmed. |
101
- | `unknown` | Verification was inconclusive (e.g. no2bounce token missing, poll timeout, O365 throttled). |
102
-
103
- > **Note.** The no2bounce wire format above is confirmed against the live API (the published docs were
104
- > out of date). The O365 (`login.microsoftonline.com`) check and DNS use only Node built-ins; the only
105
- > external dependency is the no2bounce HTTP API.
106
-
107
- ## Build
108
-
109
- ```sh
110
- npm install # or: bun install
111
- npm run build # tsc -> dist/
112
- ```
113
-
114
- The compiled entry point is `dist/src/index.js` (referenced by `main` in `package.json`).
115
-
116
- ## Publish & install in self-hosted Activepieces
117
-
118
- 1. Set a unique package name in `package.json` if `ap-email-guessr` is taken on npm, then publish:
119
-
120
- ```sh
121
- npm publish --access public
122
- ```
123
-
124
- 2. In your self-hosted Activepieces instance, add the piece from npm
125
- (**Platform Admin → Pieces → Install**, or set `AP_DEV_PIECES` when developing) using the
126
- published package name and version.
127
-
128
- See the Activepieces docs for details: <https://www.activepieces.com/docs/build-pieces/building-pieces/piece-definition>
@@ -1,37 +0,0 @@
1
- "use strict";
2
- /**
3
- * Domain mail-routing resolution (DNS only, Node built-ins).
4
- *
5
- * Used by the verifier router to fingerprint the provider and detect domains
6
- * that cannot receive mail (no MX, or an explicit RFC 7505 null MX).
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.resolveMail = resolveMail;
10
- const node_dns_1 = require("node:dns");
11
- async function resolveMail(domain) {
12
- try {
13
- const records = await node_dns_1.promises.resolveMx(domain);
14
- const real = records.filter((record) => record.exchange && record.exchange !== ".");
15
- // Records exist but every exchange is empty/"." → explicit null MX.
16
- if (records.length > 0 && real.length === 0) {
17
- return { hosts: [], nullMx: true };
18
- }
19
- if (real.length > 0) {
20
- const hosts = real
21
- .sort((a, b) => a.priority - b.priority)
22
- .map((record) => record.exchange);
23
- return { hosts, nullMx: false };
24
- }
25
- }
26
- catch {
27
- // No MX records; fall back to the implicit-MX (A/AAAA) lookup below.
28
- }
29
- try {
30
- await node_dns_1.promises.lookup(domain);
31
- return { hosts: [domain], nullMx: false };
32
- }
33
- catch {
34
- return { hosts: [], nullMx: false };
35
- }
36
- }
37
- //# sourceMappingURL=dns.js.map
@@ -1,78 +0,0 @@
1
- "use strict";
2
- /**
3
- * Credit-minimizing email search (layers 1 + 2).
4
- *
5
- * Candidates arrive pre-ordered by likelihood and are verified top-down in
6
- * rounds of `batchSize` (1 = strictly sequential). Each completed round is read
7
- * back in candidate order, so the verdict is identical to checking one at a time:
8
- * - stop at the first `valid` hit (layer 2: early-stop), and
9
- * - stop immediately on a `catch_all` verdict, since a catch-all domain the
10
- * verifier can't score further can't disambiguate individual mailboxes —
11
- * continuing would just burn credits for no extra signal (layer 1).
12
- *
13
- * no2bounce bills per email with no refund, so a round is paid for the moment it
14
- * is submitted: `creditsUsed` counts every email in the rounds we started, even
15
- * when an early candidate in the final round is the hit. A larger `batchSize` is
16
- * thus faster (fewer submit/poll cycles) but coarser on credits. `maxChecks` is a
17
- * hard ceiling; a `valid` hit on an accept-all domain is reported with reduced
18
- * confidence and `catchAll: true`.
19
- */
20
- Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.findEmail = findEmail;
22
- const CONFIDENCE = {
23
- valid: 0.9,
24
- catch_all: 0.5,
25
- invalid: 0.05,
26
- unknown: 0.5,
27
- };
28
- function result(found, email, verdict, catchAll, attempts, creditsUsed) {
29
- // An accept-all "hit" is probabilistic, so trust it less than a clean one.
30
- const confidence = verdict === "valid" && catchAll ? 0.6 : CONFIDENCE[verdict];
31
- return {
32
- found,
33
- email,
34
- verdict,
35
- confidence,
36
- catchAll,
37
- candidatesChecked: attempts.length,
38
- creditsUsed,
39
- attempts,
40
- };
41
- }
42
- async function findEmail(candidates, verifier, options = {}) {
43
- const stopOnFirstHit = options.stopOnFirstHit ?? true;
44
- const batchSize = Math.max(1, options.batchSize ?? 1);
45
- const limit = Math.min(options.maxChecks ?? candidates.length, candidates.length);
46
- const attempts = [];
47
- let creditsUsed = 0;
48
- let firstValid = null;
49
- for (let start = 0; start < limit; start += batchSize) {
50
- const round = candidates.slice(start, Math.min(start + batchSize, limit));
51
- const outcomes = await Promise.all(round.map((email) => verifier.verify(email)));
52
- // The whole round is billed on submit (no2bounce charges per email with
53
- // no refund), so count every result before deciding the verdict.
54
- for (const outcome of outcomes) {
55
- attempts.push(outcome);
56
- creditsUsed += outcome.creditsUsed;
57
- }
58
- for (const outcome of outcomes) {
59
- if (outcome.verdict === "catch_all") {
60
- return result(false, null, "catch_all", true, attempts, creditsUsed);
61
- }
62
- if (outcome.verdict === "valid") {
63
- if (!firstValid) {
64
- firstValid = outcome;
65
- }
66
- if (stopOnFirstHit) {
67
- return result(true, outcome.email, "valid", outcome.catchAll ?? false, attempts, creditsUsed);
68
- }
69
- }
70
- }
71
- }
72
- if (firstValid) {
73
- return result(true, firstValid.email, "valid", firstValid.catchAll ?? false, attempts, creditsUsed);
74
- }
75
- const sawUnknown = attempts.some((a) => a.verdict === "unknown");
76
- return result(false, null, sawUnknown ? "unknown" : "invalid", attempts.some((a) => a.catchAll === true), attempts, creditsUsed);
77
- }
78
- //# sourceMappingURL=find-email.js.map