mailintel 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,569 @@
1
+ // src/dns.ts
2
+ var RESOLVERS = {
3
+ cloudflare: "https://cloudflare-dns.com/dns-query",
4
+ google: "https://dns.google/resolve"
5
+ };
6
+ async function lookupMx(domain, options = {}) {
7
+ const resolver = options.resolver ?? "cloudflare";
8
+ const timeout = options.timeout ?? 5e3;
9
+ const fetchFn = options.fetch ?? globalThis.fetch;
10
+ const url = `${RESOLVERS[resolver]}?name=${encodeURIComponent(domain)}&type=MX`;
11
+ const controller = new AbortController();
12
+ const timer = setTimeout(() => controller.abort(), timeout);
13
+ try {
14
+ const response = await fetchFn(url, {
15
+ headers: { Accept: "application/dns-json" },
16
+ signal: controller.signal
17
+ });
18
+ if (!response.ok) {
19
+ return { records: [], raw: {} };
20
+ }
21
+ const data = await response.json();
22
+ const records = (data.Answer ?? []).filter((r) => r.type === 15).map((r) => {
23
+ const parts = r.data.split(" ");
24
+ return {
25
+ priority: parseInt(parts[0], 10),
26
+ exchange: parts[1]?.replace(/\.$/, "") ?? ""
27
+ };
28
+ }).sort((a, b) => a.priority - b.priority);
29
+ return { records, raw: data };
30
+ } catch {
31
+ return { records: [], raw: {} };
32
+ } finally {
33
+ clearTimeout(timer);
34
+ }
35
+ }
36
+
37
+ // src/ispdb.ts
38
+ var ISPDB_URL = "https://autoconfig.thunderbird.net/v1.1";
39
+ async function lookupIspdb(domain, options = {}) {
40
+ const timeout = options.timeout ?? 5e3;
41
+ const fetchFn = options.fetch ?? globalThis.fetch;
42
+ const url = `${ISPDB_URL}/${encodeURIComponent(domain)}`;
43
+ const controller = new AbortController();
44
+ const timer = setTimeout(() => controller.abort(), timeout);
45
+ try {
46
+ const response = await fetchFn(url, { signal: controller.signal });
47
+ if (!response.ok) {
48
+ return { connection: null, raw: null };
49
+ }
50
+ const xml = await response.text();
51
+ const connection = parseIspdbXml(xml);
52
+ return { connection, raw: xml };
53
+ } catch {
54
+ return { connection: null, raw: null };
55
+ } finally {
56
+ clearTimeout(timer);
57
+ }
58
+ }
59
+ function parseIspdbXml(xml) {
60
+ const imapMatch = xml.match(/<incomingServer type="imap">([\s\S]*?)<\/incomingServer>/);
61
+ const smtpMatch = xml.match(/<outgoingServer type="smtp">([\s\S]*?)<\/outgoingServer>/);
62
+ if (!imapMatch || !smtpMatch) return null;
63
+ const imapBlock = imapMatch[1];
64
+ const smtpBlock = smtpMatch[1];
65
+ const imapHost = imapBlock.match(/<hostname>(.*?)<\/hostname>/)?.[1];
66
+ const imapPort = imapBlock.match(/<port>(.*?)<\/port>/)?.[1];
67
+ const imapSocket = imapBlock.match(/<socketType>(.*?)<\/socketType>/)?.[1];
68
+ const smtpHost = smtpBlock.match(/<hostname>(.*?)<\/hostname>/)?.[1];
69
+ const smtpPort = smtpBlock.match(/<port>(.*?)<\/port>/)?.[1];
70
+ const smtpSocket = smtpBlock.match(/<socketType>(.*?)<\/socketType>/)?.[1];
71
+ const username = xml.match(/<username>(.*?)<\/username>/)?.[1] ?? "%EMAILADDRESS%";
72
+ if (!imapHost || !imapPort || !smtpHost || !smtpPort) return null;
73
+ return {
74
+ imap: {
75
+ host: imapHost,
76
+ port: parseInt(imapPort, 10),
77
+ secure: imapSocket === "SSL"
78
+ },
79
+ smtp: {
80
+ host: smtpHost,
81
+ port: parseInt(smtpPort, 10),
82
+ secure: smtpSocket === "SSL" || smtpSocket === "STARTTLS"
83
+ },
84
+ username
85
+ };
86
+ }
87
+
88
+ // src/data/domains.ts
89
+ var KNOWN_DOMAINS = {
90
+ // Google
91
+ "gmail.com": "google",
92
+ "googlemail.com": "google",
93
+ // Microsoft
94
+ "outlook.com": "microsoft",
95
+ "hotmail.com": "microsoft",
96
+ "live.com": "microsoft",
97
+ "msn.com": "microsoft",
98
+ "hotmail.co.uk": "microsoft",
99
+ "hotmail.fr": "microsoft",
100
+ "outlook.co.uk": "microsoft",
101
+ // Yahoo
102
+ "yahoo.com": "yahoo",
103
+ "yahoo.co.uk": "yahoo",
104
+ "yahoo.fr": "yahoo",
105
+ "yahoo.de": "yahoo",
106
+ "yahoo.co.jp": "yahoo",
107
+ "ymail.com": "yahoo",
108
+ "rocketmail.com": "yahoo",
109
+ // Zoho
110
+ "zoho.com": "zoho",
111
+ "zohomail.com": "zoho",
112
+ "zoho.eu": "zoho",
113
+ "zoho.in": "zoho",
114
+ "zoho.com.au": "zoho",
115
+ "zoho.jp": "zoho",
116
+ // iCloud
117
+ "icloud.com": "icloud",
118
+ "me.com": "icloud",
119
+ "mac.com": "icloud",
120
+ // Fastmail
121
+ "fastmail.com": "fastmail",
122
+ "fastmail.fm": "fastmail",
123
+ // Proton
124
+ "protonmail.com": "protonmail",
125
+ "proton.me": "protonmail",
126
+ "pm.me": "protonmail",
127
+ // Others
128
+ "aol.com": "aol",
129
+ "yandex.com": "yandex",
130
+ "yandex.ru": "yandex",
131
+ "ya.ru": "yandex",
132
+ "mail.ru": "mailru",
133
+ "gmx.com": "gmx",
134
+ "gmx.de": "gmx",
135
+ "gmx.net": "gmx",
136
+ "web.de": "webde",
137
+ "tutanota.com": "tutanota",
138
+ "tuta.io": "tutanota",
139
+ "hey.com": "hey",
140
+ "mail.com": "mailcom"
141
+ };
142
+
143
+ // src/data/mx.ts
144
+ var KNOWN_MX = {
145
+ // Google
146
+ "google.com": "google",
147
+ "googlemail.com": "google",
148
+ // Microsoft
149
+ "outlook.com": "microsoft",
150
+ "microsoft.com": "microsoft",
151
+ "pphosted.com": "microsoft",
152
+ // Zoho
153
+ "zoho.com": "zoho",
154
+ "zoho.eu": "zoho",
155
+ "zoho.in": "zoho",
156
+ "zoho.com.au": "zoho",
157
+ "zoho.jp": "zoho",
158
+ // Yahoo
159
+ "yahoodns.net": "yahoo",
160
+ // Apple
161
+ "icloud.com": "icloud",
162
+ "apple.com": "icloud",
163
+ // Hosting providers
164
+ "secureserver.net": "godaddy",
165
+ "titan.email": "titan",
166
+ "hostinger.com": "hostinger",
167
+ "ovh.net": "ovh",
168
+ "ionos.com": "ionos",
169
+ "emailsrvr.com": "rackspace",
170
+ "dreamhost.com": "dreamhost",
171
+ "awsapps.com": "amazon_workmail",
172
+ // Email-focused providers
173
+ "fastmail.com": "fastmail",
174
+ "protonmail.ch": "protonmail",
175
+ "yandex.net": "yandex",
176
+ "yandex.ru": "yandex",
177
+ "migadu.com": "migadu",
178
+ "improvmx.com": "improvmx",
179
+ "forwardemail.net": "forwardemail",
180
+ // Sending-only (no IMAP)
181
+ "mailgun.org": "mailgun",
182
+ "sendgrid.net": "sendgrid"
183
+ };
184
+
185
+ // src/data/providers.ts
186
+ var KNOWN_PROVIDERS = {
187
+ google: {
188
+ imap: { host: "imap.gmail.com", port: 993, secure: true },
189
+ smtp: { host: "smtp.gmail.com", port: 465, secure: true },
190
+ username: "%EMAILADDRESS%"
191
+ },
192
+ microsoft: {
193
+ imap: { host: "outlook.office365.com", port: 993, secure: true },
194
+ smtp: { host: "smtp-mail.outlook.com", port: 587, secure: false },
195
+ username: "%EMAILADDRESS%"
196
+ },
197
+ zoho: {
198
+ imap: { host: "imappro.zoho.com", port: 993, secure: true },
199
+ smtp: { host: "smtppro.zoho.com", port: 465, secure: true },
200
+ username: "%EMAILADDRESS%"
201
+ },
202
+ yahoo: {
203
+ imap: { host: "imap.mail.yahoo.com", port: 993, secure: true },
204
+ smtp: { host: "smtp.mail.yahoo.com", port: 465, secure: true },
205
+ username: "%EMAILADDRESS%"
206
+ },
207
+ icloud: {
208
+ imap: { host: "imap.mail.me.com", port: 993, secure: true },
209
+ smtp: { host: "smtp.mail.me.com", port: 587, secure: false },
210
+ username: "%EMAILADDRESS%"
211
+ },
212
+ fastmail: {
213
+ imap: { host: "imap.fastmail.com", port: 993, secure: true },
214
+ smtp: { host: "smtp.fastmail.com", port: 465, secure: true },
215
+ username: "%EMAILADDRESS%"
216
+ },
217
+ protonmail: {
218
+ imap: { host: "127.0.0.1", port: 1143, secure: false },
219
+ smtp: { host: "127.0.0.1", port: 1025, secure: false },
220
+ username: "%EMAILADDRESS%"
221
+ },
222
+ godaddy: {
223
+ imap: { host: "imap.secureserver.net", port: 993, secure: true },
224
+ smtp: { host: "smtpout.secureserver.net", port: 465, secure: true },
225
+ username: "%EMAILADDRESS%"
226
+ },
227
+ titan: {
228
+ imap: { host: "imap.titan.email", port: 993, secure: true },
229
+ smtp: { host: "smtp.titan.email", port: 465, secure: true },
230
+ username: "%EMAILADDRESS%"
231
+ },
232
+ ovh: {
233
+ imap: { host: "ssl0.ovh.net", port: 993, secure: true },
234
+ smtp: { host: "ssl0.ovh.net", port: 465, secure: true },
235
+ username: "%EMAILADDRESS%"
236
+ },
237
+ ionos: {
238
+ imap: { host: "imap.ionos.com", port: 993, secure: true },
239
+ smtp: { host: "smtp.ionos.com", port: 465, secure: true },
240
+ username: "%EMAILADDRESS%"
241
+ },
242
+ hostinger: {
243
+ imap: { host: "imap.hostinger.com", port: 993, secure: true },
244
+ smtp: { host: "smtp.hostinger.com", port: 465, secure: true },
245
+ username: "%EMAILADDRESS%"
246
+ },
247
+ yandex: {
248
+ imap: { host: "imap.yandex.com", port: 993, secure: true },
249
+ smtp: { host: "smtp.yandex.com", port: 465, secure: true },
250
+ username: "%EMAILADDRESS%"
251
+ },
252
+ aol: {
253
+ imap: { host: "imap.aol.com", port: 993, secure: true },
254
+ smtp: { host: "smtp.aol.com", port: 465, secure: true },
255
+ username: "%EMAILADDRESS%"
256
+ },
257
+ rackspace: {
258
+ imap: { host: "secure.emailsrvr.com", port: 993, secure: true },
259
+ smtp: { host: "secure.emailsrvr.com", port: 465, secure: true },
260
+ username: "%EMAILADDRESS%"
261
+ },
262
+ dreamhost: {
263
+ imap: { host: "imap.dreamhost.com", port: 993, secure: true },
264
+ smtp: { host: "smtp.dreamhost.com", port: 465, secure: true },
265
+ username: "%EMAILADDRESS%"
266
+ }
267
+ };
268
+ var REGIONAL_PROVIDERS = {
269
+ zoho: {
270
+ "zoho.eu": { imapHost: "imappro.zoho.eu", smtpHost: "smtppro.zoho.eu" },
271
+ "zoho.in": { imapHost: "imappro.zoho.in", smtpHost: "smtppro.zoho.in" },
272
+ "zoho.com.au": { imapHost: "imappro.zoho.com.au", smtpHost: "smtppro.zoho.com.au" },
273
+ "zoho.jp": { imapHost: "imappro.zoho.jp", smtpHost: "smtppro.zoho.jp" }
274
+ }
275
+ };
276
+
277
+ // src/data/free.ts
278
+ var FREE_DOMAINS = /* @__PURE__ */ new Set([
279
+ "gmail.com",
280
+ "googlemail.com",
281
+ "outlook.com",
282
+ "hotmail.com",
283
+ "live.com",
284
+ "msn.com",
285
+ "hotmail.co.uk",
286
+ "hotmail.fr",
287
+ "yahoo.com",
288
+ "yahoo.co.uk",
289
+ "yahoo.fr",
290
+ "yahoo.de",
291
+ "ymail.com",
292
+ "icloud.com",
293
+ "me.com",
294
+ "mac.com",
295
+ "protonmail.com",
296
+ "proton.me",
297
+ "pm.me",
298
+ "aol.com",
299
+ "yandex.com",
300
+ "yandex.ru",
301
+ "ya.ru",
302
+ "mail.ru",
303
+ "gmx.com",
304
+ "gmx.de",
305
+ "gmx.net",
306
+ "web.de",
307
+ "zoho.com",
308
+ "tutanota.com",
309
+ "tuta.io",
310
+ "mail.com"
311
+ ]);
312
+
313
+ // src/mailintel.ts
314
+ function resolveUsername(template, email, domain) {
315
+ return template.replace("%EMAILADDRESS%", email).replace("%EMAILLOCALPART%", email.split("@")[0] ?? "").replace("%EMAILDOMAIN%", domain);
316
+ }
317
+ function resolveConnection(raw, email, domain) {
318
+ return {
319
+ imap: raw.imap,
320
+ smtp: raw.smtp,
321
+ username: email ? resolveUsername(raw.username, email, domain) : raw.username,
322
+ usernameTemplate: raw.username
323
+ };
324
+ }
325
+ async function mailintelCore(input, options, cache, cacheTtl) {
326
+ const atIndex = input.lastIndexOf("@");
327
+ const isDomainOnly = atIndex === -1;
328
+ const email = isDomainOnly ? "" : input;
329
+ const domain = isDomainOnly ? input.toLowerCase() : input.slice(atIndex + 1).toLowerCase();
330
+ if (!domain) {
331
+ return emptyResult(email, "");
332
+ }
333
+ if (cache) {
334
+ const cached = cache.get(domain);
335
+ if (cached) {
336
+ return { ...cached, email };
337
+ }
338
+ }
339
+ if (options.providers?.[domain]) {
340
+ const override = options.providers[domain];
341
+ const result2 = {
342
+ email,
343
+ domain,
344
+ provider: override.provider,
345
+ mx: null,
346
+ type: FREE_DOMAINS.has(domain) ? "free" : "business",
347
+ isFree: FREE_DOMAINS.has(domain),
348
+ hasMx: false,
349
+ connection: resolveConnection(
350
+ { imap: override.imap, smtp: override.smtp, username: override.username ?? "%EMAILADDRESS%" },
351
+ email,
352
+ domain
353
+ ),
354
+ confidence: "high",
355
+ source: "override",
356
+ raw: { mx: null, dns: null, ispdb: null }
357
+ };
358
+ cache?.set(domain, result2, cacheTtl);
359
+ return result2;
360
+ }
361
+ const knownProvider = KNOWN_DOMAINS[domain];
362
+ if (knownProvider) {
363
+ const connection2 = KNOWN_PROVIDERS[knownProvider] ?? null;
364
+ const result2 = {
365
+ email,
366
+ domain,
367
+ provider: knownProvider,
368
+ mx: null,
369
+ type: FREE_DOMAINS.has(domain) ? "free" : "business",
370
+ isFree: FREE_DOMAINS.has(domain),
371
+ hasMx: false,
372
+ connection: connection2 ? resolveConnection(connection2, email, domain) : null,
373
+ confidence: "high",
374
+ source: "known-domain",
375
+ raw: { mx: null, dns: null, ispdb: null }
376
+ };
377
+ cache?.set(domain, result2, cacheTtl);
378
+ return result2;
379
+ }
380
+ if (options.mxLookup === false) {
381
+ const result2 = emptyResult(email, domain);
382
+ cache?.set(domain, result2, cacheTtl);
383
+ return result2;
384
+ }
385
+ const resolver = options.mxLookup === "google" ? "google" : "cloudflare";
386
+ const { records: mxRecords, raw: dnsRaw } = await lookupMx(domain, {
387
+ resolver,
388
+ timeout: options.timeout,
389
+ fetch: options.fetch
390
+ });
391
+ if (mxRecords.length === 0) {
392
+ const result2 = {
393
+ email,
394
+ domain,
395
+ provider: null,
396
+ mx: null,
397
+ type: "unknown",
398
+ isFree: false,
399
+ hasMx: false,
400
+ connection: null,
401
+ confidence: "low",
402
+ source: null,
403
+ raw: { mx: [], dns: dnsRaw, ispdb: null }
404
+ };
405
+ cache?.set(domain, result2, cacheTtl);
406
+ return result2;
407
+ }
408
+ const primaryMx = mxRecords[0].exchange;
409
+ if (options.mxOverrides) {
410
+ for (const [suffix, override] of Object.entries(options.mxOverrides)) {
411
+ if (primaryMx === suffix || primaryMx.endsWith("." + suffix)) {
412
+ const result2 = {
413
+ email,
414
+ domain,
415
+ provider: override.provider,
416
+ mx: primaryMx,
417
+ type: FREE_DOMAINS.has(domain) ? "free" : "business",
418
+ isFree: FREE_DOMAINS.has(domain),
419
+ hasMx: true,
420
+ connection: resolveConnection(
421
+ { imap: override.imap, smtp: override.smtp, username: override.username ?? "%EMAILADDRESS%" },
422
+ email,
423
+ domain
424
+ ),
425
+ confidence: "high",
426
+ source: "mx-lookup",
427
+ raw: { mx: mxRecords, dns: dnsRaw, ispdb: null }
428
+ };
429
+ cache?.set(domain, result2, cacheTtl);
430
+ return result2;
431
+ }
432
+ }
433
+ }
434
+ let mxProvider = null;
435
+ let matchedMxSuffix = null;
436
+ for (const [suffix, provider] of Object.entries(KNOWN_MX)) {
437
+ if (primaryMx === suffix || primaryMx.endsWith("." + suffix)) {
438
+ mxProvider = provider;
439
+ matchedMxSuffix = suffix;
440
+ break;
441
+ }
442
+ }
443
+ if (mxProvider) {
444
+ let connection2 = KNOWN_PROVIDERS[mxProvider] ?? null;
445
+ let ispdbRaw2 = null;
446
+ let confidence = connection2 ? "high" : "low";
447
+ if (connection2 && matchedMxSuffix) {
448
+ const regional = REGIONAL_PROVIDERS[mxProvider];
449
+ if (regional) {
450
+ for (const [regionSuffix, regionConfig] of Object.entries(regional)) {
451
+ if (matchedMxSuffix === regionSuffix || matchedMxSuffix.endsWith("." + regionSuffix)) {
452
+ connection2 = {
453
+ ...connection2,
454
+ imap: { ...connection2.imap, host: regionConfig.imapHost },
455
+ smtp: { ...connection2.smtp, host: regionConfig.smtpHost }
456
+ };
457
+ break;
458
+ }
459
+ }
460
+ }
461
+ }
462
+ if (!connection2 && options.ispdb !== false) {
463
+ const ispdbResult = await lookupIspdb(domain, {
464
+ timeout: options.timeout,
465
+ fetch: options.fetch
466
+ });
467
+ connection2 = ispdbResult.connection;
468
+ ispdbRaw2 = ispdbResult.raw;
469
+ if (connection2) {
470
+ confidence = "medium";
471
+ }
472
+ }
473
+ const result2 = {
474
+ email,
475
+ domain,
476
+ provider: mxProvider,
477
+ mx: primaryMx,
478
+ type: FREE_DOMAINS.has(domain) ? "free" : "business",
479
+ isFree: FREE_DOMAINS.has(domain),
480
+ hasMx: true,
481
+ connection: connection2 ? resolveConnection(connection2, email, domain) : null,
482
+ confidence,
483
+ source: "mx-lookup",
484
+ raw: { mx: mxRecords, dns: dnsRaw, ispdb: ispdbRaw2 }
485
+ };
486
+ cache?.set(domain, result2, cacheTtl);
487
+ return result2;
488
+ }
489
+ let connection = null;
490
+ let ispdbRaw = null;
491
+ if (options.ispdb !== false) {
492
+ const ispdbResult = await lookupIspdb(domain, {
493
+ timeout: options.timeout,
494
+ fetch: options.fetch
495
+ });
496
+ connection = ispdbResult.connection;
497
+ ispdbRaw = ispdbResult.raw;
498
+ }
499
+ const result = {
500
+ email,
501
+ domain,
502
+ provider: null,
503
+ mx: primaryMx,
504
+ type: FREE_DOMAINS.has(domain) ? "free" : "business",
505
+ isFree: FREE_DOMAINS.has(domain),
506
+ hasMx: true,
507
+ connection: connection ? resolveConnection(connection, email, domain) : null,
508
+ confidence: connection ? "medium" : "low",
509
+ source: connection ? "mx-lookup" : null,
510
+ raw: { mx: mxRecords, dns: dnsRaw, ispdb: ispdbRaw }
511
+ };
512
+ cache?.set(domain, result, cacheTtl);
513
+ return result;
514
+ }
515
+ function emptyResult(email, domain) {
516
+ return {
517
+ email,
518
+ domain,
519
+ provider: null,
520
+ mx: null,
521
+ type: "unknown",
522
+ isFree: false,
523
+ hasMx: false,
524
+ connection: null,
525
+ confidence: "low",
526
+ source: null,
527
+ raw: { mx: null, dns: null, ispdb: null }
528
+ };
529
+ }
530
+
531
+ // src/cache.ts
532
+ var Cache = class {
533
+ store = /* @__PURE__ */ new Map();
534
+ get(key) {
535
+ const entry = this.store.get(key);
536
+ if (!entry) return null;
537
+ if (Date.now() > entry.expires) {
538
+ this.store.delete(key);
539
+ return null;
540
+ }
541
+ return entry.value;
542
+ }
543
+ set(key, value, ttl) {
544
+ this.store.set(key, { value, expires: Date.now() + ttl });
545
+ }
546
+ clear() {
547
+ this.store.clear();
548
+ }
549
+ };
550
+
551
+ // src/factory.ts
552
+ function createMailintel(options = {}) {
553
+ const cache = options.cache !== false ? new Cache() : null;
554
+ const cacheTtl = options.cacheTtl ?? 30 * 60 * 1e3;
555
+ async function mailintel2(input, callOptions) {
556
+ const mergedOptions = { ...options, ...callOptions };
557
+ if (Array.isArray(input)) {
558
+ return Promise.all(input.map((email) => mailintelCore(email, mergedOptions, cache, cacheTtl)));
559
+ }
560
+ return mailintelCore(input, mergedOptions, cache, cacheTtl);
561
+ }
562
+ mailintel2.clearCache = () => cache?.clear();
563
+ return mailintel2;
564
+ }
565
+
566
+ // src/index.ts
567
+ var mailintel = createMailintel();
568
+
569
+ export { createMailintel, mailintel, mailintelCore };
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "mailintel",
3
+ "version": "0.2.0",
4
+ "description": "Email domain intelligence. Takes any email address, resolves the provider, returns IMAP/SMTP connection settings. Supports custom domains via MX lookups.",
5
+ "author": "Ahmed Atef <ahmed@atef.dev>",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "bin": {
24
+ "mailintel": "dist/cli.js"
25
+ },
26
+ "sideEffects": false,
27
+ "engines": {
28
+ "node": ">=18"
29
+ },
30
+ "scripts": {
31
+ "build": "tsup",
32
+ "test": "vitest run",
33
+ "test:watch": "vitest",
34
+ "prepublishOnly": "npm run build && npm run test"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^20.0.0",
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.4.0",
40
+ "vitest": "^2.0.0"
41
+ },
42
+ "keywords": [
43
+ "email",
44
+ "smtp",
45
+ "imap",
46
+ "provider",
47
+ "mx",
48
+ "autoconfig",
49
+ "email-settings",
50
+ "mail-server",
51
+ "dns",
52
+ "mx-lookup"
53
+ ],
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/AhmedAtef07/mailintel.git"
57
+ },
58
+ "bugs": {
59
+ "url": "https://github.com/AhmedAtef07/mailintel/issues"
60
+ },
61
+ "homepage": "https://github.com/AhmedAtef07/mailintel#readme"
62
+ }