@rudderjs/mail 1.0.4 → 1.1.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/doctor.d.ts +2 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +85 -0
- package/dist/doctor.js.map +1 -0
- package/package.json +9 -4
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":""}
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Doctor checks contributed by @rudderjs/mail.
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import net from 'node:net';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { registerDoctorCheck } from '@rudderjs/console';
|
|
6
|
+
function readFileSafe(rel) {
|
|
7
|
+
try {
|
|
8
|
+
return fs.readFileSync(path.join(process.cwd(), rel), 'utf-8');
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
// Pull SMTP host/port from .env hints or config/mail.ts. We deliberately
|
|
15
|
+
// don't import the user's config — the doctor fast-path stays boot-free
|
|
16
|
+
// and the user's config might pull peer modules that aren't installed.
|
|
17
|
+
function inferSmtp() {
|
|
18
|
+
const envHost = process.env['MAIL_HOST'] ?? process.env['SMTP_HOST'];
|
|
19
|
+
const envPort = process.env['MAIL_PORT'] ?? process.env['SMTP_PORT'];
|
|
20
|
+
if (envHost) {
|
|
21
|
+
const out = { host: envHost };
|
|
22
|
+
if (envPort) {
|
|
23
|
+
const p = Number(envPort);
|
|
24
|
+
if (!Number.isNaN(p))
|
|
25
|
+
out.port = p;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
const text = readFileSafe('config/mail.ts') ?? readFileSafe('config/mail.js') ?? '';
|
|
30
|
+
const hostLit = /MAIL_HOST['"]?\s*,\s*['"]([^'"]+)['"]/.exec(text)?.[1]
|
|
31
|
+
?? /host\s*:\s*['"]([^'"]+)['"]/.exec(text)?.[1];
|
|
32
|
+
const portLit = /MAIL_PORT['"]?\s*,\s*['"]?(\d+)/.exec(text)?.[1]
|
|
33
|
+
?? /port\s*:\s*(\d+)/.exec(text)?.[1];
|
|
34
|
+
if (!hostLit)
|
|
35
|
+
return null;
|
|
36
|
+
const out = { host: hostLit };
|
|
37
|
+
if (portLit)
|
|
38
|
+
out.port = Number(portLit);
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
registerDoctorCheck({
|
|
42
|
+
id: 'mail:smtp-connect',
|
|
43
|
+
category: 'runtime',
|
|
44
|
+
title: 'Mail SMTP host',
|
|
45
|
+
needsBoot: true,
|
|
46
|
+
run() {
|
|
47
|
+
const hint = inferSmtp();
|
|
48
|
+
if (!hint || !hint.host) {
|
|
49
|
+
return Promise.resolve({ status: 'ok', message: 'no SMTP host configured — skip' });
|
|
50
|
+
}
|
|
51
|
+
// Skip the local sink that nodemailer uses for tests / preview mode
|
|
52
|
+
if (/^(127\.0\.0\.1|localhost|0\.0\.0\.0)$/.test(hint.host) && (hint.port ?? 587) > 1024 && (hint.port ?? 587) < 2000) {
|
|
53
|
+
// Likely a local mailpit / mailhog / preview — still try, just don't be loud
|
|
54
|
+
}
|
|
55
|
+
const host = hint.host;
|
|
56
|
+
const port = hint.port ?? 587;
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const t0 = performance.now();
|
|
59
|
+
const socket = new net.Socket();
|
|
60
|
+
socket.setTimeout(2000);
|
|
61
|
+
socket.once('connect', () => {
|
|
62
|
+
const ms = Math.round(performance.now() - t0);
|
|
63
|
+
socket.destroy();
|
|
64
|
+
resolve({ status: 'ok', message: `${host}:${port} reachable in ${ms}ms` });
|
|
65
|
+
});
|
|
66
|
+
socket.once('timeout', () => {
|
|
67
|
+
socket.destroy();
|
|
68
|
+
resolve({
|
|
69
|
+
status: 'warn',
|
|
70
|
+
message: `${host}:${port} timed out after 2s`,
|
|
71
|
+
fix: `Verify the SMTP host is reachable from this machine (firewall, VPN, or wrong credentials)`,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
socket.once('error', (err) => {
|
|
75
|
+
resolve({
|
|
76
|
+
status: 'error',
|
|
77
|
+
message: `${host}:${port} ${err.code ?? err.message}`,
|
|
78
|
+
fix: `Verify MAIL_HOST/MAIL_PORT in .env. ${err.code === 'ENOTFOUND' ? 'DNS lookup failed.' : err.code === 'ECONNREFUSED' ? 'Nothing listening on that port.' : ''}`,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
socket.connect(port, host);
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rudderjs/mail",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"rudderjs": {
|
|
5
5
|
"provider": "MailProvider",
|
|
6
6
|
"stage": "feature"
|
|
@@ -25,10 +25,15 @@
|
|
|
25
25
|
".": {
|
|
26
26
|
"import": "./dist/index.js",
|
|
27
27
|
"types": "./dist/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./doctor": {
|
|
30
|
+
"import": "./dist/doctor.js",
|
|
31
|
+
"types": "./dist/doctor.d.ts"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"dependencies": {
|
|
31
|
-
"@rudderjs/
|
|
35
|
+
"@rudderjs/console": "^1.1.0",
|
|
36
|
+
"@rudderjs/core": "^1.1.7"
|
|
32
37
|
},
|
|
33
38
|
"optionalDependencies": {
|
|
34
39
|
"nodemailer": "^6.9.0"
|
|
@@ -36,7 +41,7 @@
|
|
|
36
41
|
"devDependencies": {
|
|
37
42
|
"@types/node": "^20.0.0",
|
|
38
43
|
"typescript": "^5.4.0",
|
|
39
|
-
"@rudderjs/queue": "4.1.
|
|
44
|
+
"@rudderjs/queue": "4.1.5"
|
|
40
45
|
},
|
|
41
46
|
"author": "Suleiman Shahbari",
|
|
42
47
|
"scripts": {
|
|
@@ -44,7 +49,7 @@
|
|
|
44
49
|
"dev": "tsc -p tsconfig.build.json --watch",
|
|
45
50
|
"typecheck": "tsc --noEmit",
|
|
46
51
|
"lint": "eslint src",
|
|
47
|
-
"test": "tsc -p tsconfig.test.json && node --experimental-test-module-mocks --test
|
|
52
|
+
"test": "tsc -p tsconfig.test.json && cd dist-test && node --experimental-test-module-mocks --test",
|
|
48
53
|
"clean": "rm -rf dist"
|
|
49
54
|
}
|
|
50
55
|
}
|