@softure-ai/mailing 0.1.7 → 0.1.8
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/CHANGELOG.md +15 -0
- package/README.md +25 -7
- package/dist/cli/run.d.ts +3 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +95 -10
- package/dist/cli/run.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/server/dns.d.ts +48 -1
- package/dist/server/dns.d.ts.map +1 -1
- package/dist/server/dns.js +124 -15
- package/dist/server/dns.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/module.json +1 -1
- package/package.json +1 -1
- package/src/cli/run.ts +103 -11
- package/src/index.ts +1 -1
- package/src/server/dns.ts +174 -16
- package/src/server/index.ts +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ Newest first. Each version lists what changed for an app that uses `@softure-ai/
|
|
|
4
4
|
production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
|
|
5
5
|
"Definition of done"). Versions before the first one below are described in their GitHub Releases (`mailing@x.y.z`).
|
|
6
6
|
|
|
7
|
+
## 0.1.8
|
|
8
|
+
|
|
9
|
+
- `checkSenderDns` takes `expectDmarc: { policy, subdomainPolicy, adkim, aspf }`: a DMARC record weaker than it (a
|
|
10
|
+
lower policy, relaxed or absent alignment where strict is required, `pct` under 100) fails with the new finding
|
|
11
|
+
`weak`. Without the option nothing changes.
|
|
12
|
+
- `replyTo` checks that the reply domain accepts mail: MX records that are not a null MX (finding `null-mx`) and at
|
|
13
|
+
most one SPF record.
|
|
14
|
+
- `returnPath: [{ host, targetDomain? }]` checks return-path hosts: a CNAME (to the target domain, else finding
|
|
15
|
+
`unexpected-target`) or MX records. New `resendReturnPath(domain)` gives Resend's `send.` and `rsend.` hosts.
|
|
16
|
+
- `SenderDnsReport` has two new keys, `replyTo` (`null` when not asked) and `returnPath` (`[]` when not asked); new
|
|
17
|
+
resolver options `resolveMx` and `resolveCname`.
|
|
18
|
+
- `softure-mail dns`: `--dmarc-policy`, `--dmarc-sp`, `--dmarc-adkim`, `--dmarc-aspf`, `--reply-to`,
|
|
19
|
+
`--return-path`, `--resend-return-path`; without `--domain` it also checks the configured `replyTo`. New output
|
|
20
|
+
lines `REPLY` and `PATH`.
|
|
21
|
+
|
|
7
22
|
## 0.1.7
|
|
8
23
|
|
|
9
24
|
- A failed send keeps the provider's HTTP status: `SendMailResult` failures and `deliverOnce` outcomes carry
|
package/README.md
CHANGED
|
@@ -45,7 +45,8 @@ FIRE ran deployment-specific scripts.
|
|
|
45
45
|
in `/next`) sends a mail at most once per scope and recipient through the delivery ledger.
|
|
46
46
|
- **Campaigns.** `sendCampaign`, `planCampaign` and the content file parser in `/server`; the
|
|
47
47
|
`softure-mail campaign` command sends a campaign from a content file.
|
|
48
|
-
- **Sender DNS.** `checkSenderDns(domain)` and `softure-mail dns` report SPF, DKIM and DMARC
|
|
48
|
+
- **Sender DNS.** `checkSenderDns(domain)` and `softure-mail dns` report SPF, DKIM and DMARC, hold DMARC to a
|
|
49
|
+
required minimum, and check the reply-to domain's MX and the provider's return-path hosts.
|
|
49
50
|
- The `MailProvider` contract and `resend()`, the first adapter.
|
|
50
51
|
- `@softure-ai/mailing/testing`: `fakeMailProvider()` and `readMailOutbox(file)`.
|
|
51
52
|
|
|
@@ -192,15 +193,32 @@ softure-mail campaign launch.md --recipients recipients.txt # sends
|
|
|
192
193
|
### Sender DNS check: `softure-mail dns`
|
|
193
194
|
|
|
194
195
|
```bash
|
|
195
|
-
softure-mail dns # the domain of `from` in the config
|
|
196
|
+
softure-mail dns # the domain of `from` (and replyTo) in the config
|
|
196
197
|
softure-mail dns --domain mail.example.com --spf-host send.mail.example.com
|
|
198
|
+
softure-mail dns --spf-host send.mail.example.com --resend-return-path \
|
|
199
|
+
--dmarc-policy reject --dmarc-sp reject --dmarc-adkim s --dmarc-aspf s
|
|
197
200
|
```
|
|
198
201
|
|
|
199
|
-
It
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
It reports each check as `pass`, `warn` or `fail`, exiting 1 on any `fail`:
|
|
203
|
+
|
|
204
|
+
- **SPF**: one `v=spf1` record on the domain or each `--spf-host`; `+all` warns. Resend publishes SPF on
|
|
205
|
+
`send.<domain>`.
|
|
206
|
+
- **DKIM**: a non-empty `p=` at `<selector>._domainkey.<domain>`; selector `resend` unless `--dkim-selector` is given.
|
|
207
|
+
- **DMARC**: `_dmarc.<domain>` or a parent domain's record; `p=none` warns: it only reports. With a required minimum
|
|
208
|
+
(`expectDmarc: { policy, subdomainPolicy, adkim, aspf }`, or the `--dmarc-*` flags) a weaker record fails as
|
|
209
|
+
`weak`: `p=quarantine` where `reject` is required, `adkim=r` (or no `adkim`) where `s` is required, `pct` under 100
|
|
210
|
+
when a policy is required. A stricter record passes, so adding `rua=` or tightening a tag never turns it red. For
|
|
211
|
+
an inherited record the domain's policy is `sp`, else `p`.
|
|
212
|
+
- **REPLY** (when `replyTo` is configured and `--domain` is not given, or with `--reply-to`; `replyTo` option of the
|
|
213
|
+
function): the reply domain must have MX records that are not a null MX (`0 .`, "accepts no mail") and at most one
|
|
214
|
+
SPF record. Without it replies bounce while every sender check is green.
|
|
215
|
+
- **PATH** (`returnPath: [{ host, targetDomain? }]`, `--return-path <host>`, `--resend-return-path`): each host must
|
|
216
|
+
be a CNAME (to `targetDomain` or under it, when set) or have MX records. `resendReturnPath(domain)` (the flag) gives
|
|
217
|
+
Resend's `send.<domain>` and `rsend.<domain>` with target `rmta.net`; a domain Resend set up with MX records on
|
|
218
|
+
`send` and no `rsend` checks `--return-path send.<domain>` alone.
|
|
219
|
+
|
|
220
|
+
It cannot see whether the provider signs with the published key. The function takes `resolveTxt`, `resolveMx` and
|
|
221
|
+
`resolveCname` for tests; by default it asks the system resolver.
|
|
204
222
|
|
|
205
223
|
## 2. Installation
|
|
206
224
|
|
package/dist/cli/run.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type SoftureConfig } from "@softure-ai/core";
|
|
2
2
|
import { type DatabaseHandle } from "@softure-ai/db";
|
|
3
|
-
import { type ResolveTxt } from "../server/dns.js";
|
|
3
|
+
import { type ResolveCname, type ResolveMx, type ResolveTxt } from "../server/dns.js";
|
|
4
4
|
import { type Env } from "../server/unsubscribe-link.js";
|
|
5
5
|
export interface CliOutput {
|
|
6
6
|
readonly log: (line: string) => void;
|
|
@@ -17,6 +17,8 @@ export interface RunMailCliOptions {
|
|
|
17
17
|
/** Opens the campaign's database connection. Default: the config's `database.handle`, else `createDatabase(url, { max: 1 })`. */
|
|
18
18
|
readonly openDatabase?: (url: string) => Promise<DatabaseHandle>;
|
|
19
19
|
readonly resolveTxt?: ResolveTxt;
|
|
20
|
+
readonly resolveMx?: ResolveMx;
|
|
21
|
+
readonly resolveCname?: ResolveCname;
|
|
20
22
|
readonly sleep?: (ms: number) => Promise<void>;
|
|
21
23
|
readonly env?: Env;
|
|
22
24
|
}
|
package/dist/cli/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAWA,OAAO,EAAe,KAAK,aAAa,EAA8B,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIhG,OAAO,
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAWA,OAAO,EAAe,KAAK,aAAa,EAA8B,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIhG,OAAO,EAAkI,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAuB,MAAM,kBAAkB,CAAC;AAE3O,OAAO,EAAiF,KAAK,GAAG,EAAE,MAAM,+BAA+B,CAAC;AAExI,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC5B,iIAAiI;IACjI,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,eAAO,MAAM,UAAU,QAgCa,CAAC;AAgCrC,yGAAyG;AACzG,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB5E"}
|
package/dist/cli/run.js
CHANGED
|
@@ -13,7 +13,7 @@ import { systemClock } from "@softure-ai/core";
|
|
|
13
13
|
import { openCommandDatabase } from "@softure-ai/db";
|
|
14
14
|
import { parseCampaignFile, parseRecipientList } from "../server/campaign-file.js";
|
|
15
15
|
import { planCampaign, sendCampaign } from "../server/campaigns.js";
|
|
16
|
-
import { checkSenderDns, getSenderDomain } from "../server/dns.js";
|
|
16
|
+
import { checkSenderDns, getSenderDomain, resendReturnPath } from "../server/dns.js";
|
|
17
17
|
import { getMailingOptions } from "../server/options.js";
|
|
18
18
|
import { MIN_UNSUBSCRIBE_SECRET_LENGTH, readUnsubscribeSecrets, UNSUBSCRIBE_SECRET_ENV } from "../server/unsubscribe-link.js";
|
|
19
19
|
export const EXIT_OK = 0;
|
|
@@ -24,6 +24,8 @@ export const DEFAULT_PAUSE_MS = 500;
|
|
|
24
24
|
export const MAIL_USAGE = `Usage:
|
|
25
25
|
softure-mail campaign <content-file> --recipients <file> [--dry-run] [--pause-ms <ms>] [--resend-uncertain]
|
|
26
26
|
softure-mail dns [--domain <domain>] [--dkim-selector <name>]... [--spf-host <host>]...
|
|
27
|
+
[--dmarc-policy <p>] [--dmarc-sp <p>] [--dmarc-adkim <a>] [--dmarc-aspf <a>]
|
|
28
|
+
[--reply-to <address>] [--return-path <host>]... [--resend-return-path]
|
|
27
29
|
|
|
28
30
|
campaign Sends the campaign in <content-file> (frontmatter id, kind, subject, optional html,
|
|
29
31
|
then the text body) to every address in the recipients file (one per line), at most
|
|
@@ -39,6 +41,15 @@ dns Checks SPF, DKIM and DMARC for the sender domain (default: the domain
|
|
|
39
41
|
--dkim-selector <name> DKIM selector to look up (default resend; repeatable)
|
|
40
42
|
--spf-host <host> where SPF is published (default the domain; repeatable;
|
|
41
43
|
Resend publishes it on send.<domain>)
|
|
44
|
+
--dmarc-policy <p> require at least this DMARC policy (quarantine or reject)
|
|
45
|
+
and pct=100; a weaker record fails
|
|
46
|
+
--dmarc-sp <p> require at least this subdomain policy (sp, else p)
|
|
47
|
+
--dmarc-adkim <a> require this DKIM alignment (r or s; absent counts as r)
|
|
48
|
+
--dmarc-aspf <a> require this SPF alignment (r or s; absent counts as r)
|
|
49
|
+
--reply-to <address> check that this address's domain accepts mail (MX, one SPF)
|
|
50
|
+
(default: replyTo of the config, when --domain is not given)
|
|
51
|
+
--return-path <host> a return-path host that must be a CNAME or have MX (repeatable)
|
|
52
|
+
--resend-return-path check Resend's send.<domain> and rsend.<domain> CNAMEs
|
|
42
53
|
|
|
43
54
|
Options for both:
|
|
44
55
|
--config <file> the app's softure.config file (bin only)
|
|
@@ -47,6 +58,9 @@ const consoleOutput = {
|
|
|
47
58
|
log: (line) => console.log(line),
|
|
48
59
|
error: (line) => console.error(line),
|
|
49
60
|
};
|
|
61
|
+
const DMARC_POLICIES = ["quarantine", "reject"];
|
|
62
|
+
const DMARC_ALIGNMENTS = ["r", "s"];
|
|
63
|
+
const DNS_ONLY_OPTIONS = ["domain", "dkim-selector", "spf-host", "dmarc-policy", "dmarc-sp", "dmarc-adkim", "dmarc-aspf", "reply-to", "return-path", "resend-return-path"];
|
|
50
64
|
/** Runs the command and returns the process exit code: 0 done, 1 failed or incomplete, 2 usage error. */
|
|
51
65
|
export async function runMailCli(options) {
|
|
52
66
|
const output = options.output ?? consoleOutput;
|
|
@@ -90,9 +104,21 @@ function parseCommand(argv) {
|
|
|
90
104
|
return `dns does not take --${misplaced.join(", --")}`;
|
|
91
105
|
if (positionals.length > 0)
|
|
92
106
|
return `dns takes no file, got "${positionals.join(" ")}"`;
|
|
93
|
-
|
|
107
|
+
const expectDmarc = parseDmarcExpectation(values);
|
|
108
|
+
if (typeof expectDmarc === "string")
|
|
109
|
+
return expectDmarc;
|
|
110
|
+
return {
|
|
111
|
+
kind: "dns",
|
|
112
|
+
domain: values.domain,
|
|
113
|
+
dkimSelectors: values["dkim-selector"],
|
|
114
|
+
spfHosts: values["spf-host"],
|
|
115
|
+
expectDmarc,
|
|
116
|
+
replyTo: values["reply-to"],
|
|
117
|
+
returnPathHosts: values["return-path"] ?? [],
|
|
118
|
+
resendReturnPath: values["resend-return-path"] === true,
|
|
119
|
+
};
|
|
94
120
|
}
|
|
95
|
-
const misplaced =
|
|
121
|
+
const misplaced = DNS_ONLY_OPTIONS.filter((option) => values[option] !== undefined);
|
|
96
122
|
if (misplaced.length > 0)
|
|
97
123
|
return `campaign does not take --${misplaced.join(", --")}`;
|
|
98
124
|
const [contentFile, ...extra] = positionals;
|
|
@@ -118,42 +144,101 @@ function parseCommandArgs(args) {
|
|
|
118
144
|
domain: { type: "string" },
|
|
119
145
|
"dkim-selector": { type: "string", multiple: true },
|
|
120
146
|
"spf-host": { type: "string", multiple: true },
|
|
147
|
+
"dmarc-policy": { type: "string" },
|
|
148
|
+
"dmarc-sp": { type: "string" },
|
|
149
|
+
"dmarc-adkim": { type: "string" },
|
|
150
|
+
"dmarc-aspf": { type: "string" },
|
|
151
|
+
"reply-to": { type: "string" },
|
|
152
|
+
"return-path": { type: "string", multiple: true },
|
|
153
|
+
"resend-return-path": { type: "boolean" },
|
|
121
154
|
help: { type: "boolean" },
|
|
122
155
|
},
|
|
123
156
|
strict: true,
|
|
124
157
|
allowPositionals: true,
|
|
125
158
|
});
|
|
126
159
|
}
|
|
160
|
+
/** One choice of a fixed list, case-insensitive; `undefined` when the option was not given. */
|
|
161
|
+
function pickChoice(values, option, allowed) {
|
|
162
|
+
const given = values[option];
|
|
163
|
+
if (given === undefined)
|
|
164
|
+
return { value: undefined };
|
|
165
|
+
const found = allowed.find((candidate) => candidate === given.trim().toLowerCase());
|
|
166
|
+
return found === undefined ? `--${option} expects ${allowed.join(" or ")}, got "${given}"` : { value: found };
|
|
167
|
+
}
|
|
168
|
+
function parseDmarcExpectation(values) {
|
|
169
|
+
const policy = pickChoice(values, "dmarc-policy", DMARC_POLICIES);
|
|
170
|
+
if (typeof policy === "string")
|
|
171
|
+
return policy;
|
|
172
|
+
const subdomainPolicy = pickChoice(values, "dmarc-sp", DMARC_POLICIES);
|
|
173
|
+
if (typeof subdomainPolicy === "string")
|
|
174
|
+
return subdomainPolicy;
|
|
175
|
+
const adkim = pickChoice(values, "dmarc-adkim", DMARC_ALIGNMENTS);
|
|
176
|
+
if (typeof adkim === "string")
|
|
177
|
+
return adkim;
|
|
178
|
+
const aspf = pickChoice(values, "dmarc-aspf", DMARC_ALIGNMENTS);
|
|
179
|
+
if (typeof aspf === "string")
|
|
180
|
+
return aspf;
|
|
181
|
+
const expectation = {
|
|
182
|
+
...(policy.value === undefined ? {} : { policy: policy.value }),
|
|
183
|
+
...(subdomainPolicy.value === undefined ? {} : { subdomainPolicy: subdomainPolicy.value }),
|
|
184
|
+
...(adkim.value === undefined ? {} : { adkim: adkim.value }),
|
|
185
|
+
...(aspf.value === undefined ? {} : { aspf: aspf.value }),
|
|
186
|
+
};
|
|
187
|
+
return Object.keys(expectation).length === 0 ? undefined : expectation;
|
|
188
|
+
}
|
|
127
189
|
async function runDns(command, options, output) {
|
|
128
190
|
let domain = command.domain;
|
|
191
|
+
let replyTo = command.replyTo;
|
|
129
192
|
if (domain === undefined) {
|
|
130
193
|
if (options.config === undefined) {
|
|
131
194
|
output.error("softure-mail dns: pass --domain <domain>, or run it with the app's config to check the sender's domain");
|
|
132
195
|
return EXIT_FAILED;
|
|
133
196
|
}
|
|
134
|
-
|
|
197
|
+
const mailing = getMailingOptions(options.config);
|
|
198
|
+
domain = getSenderDomain(mailing.from);
|
|
199
|
+
replyTo ??= mailing.replyTo;
|
|
135
200
|
}
|
|
201
|
+
const returnPath = [...(command.resendReturnPath ? resendReturnPath(domain) : []), ...command.returnPathHosts.map((host) => ({ host }))];
|
|
136
202
|
const report = await checkSenderDns(domain, {
|
|
137
203
|
...(command.dkimSelectors === undefined ? {} : { dkimSelectors: command.dkimSelectors }),
|
|
138
204
|
...(command.spfHosts === undefined ? {} : { spfHosts: command.spfHosts }),
|
|
205
|
+
...(command.expectDmarc === undefined ? {} : { expectDmarc: command.expectDmarc }),
|
|
206
|
+
...(replyTo === undefined ? {} : { replyTo }),
|
|
207
|
+
returnPath,
|
|
139
208
|
...(options.resolveTxt === undefined ? {} : { resolveTxt: options.resolveTxt }),
|
|
209
|
+
...(options.resolveMx === undefined ? {} : { resolveMx: options.resolveMx }),
|
|
210
|
+
...(options.resolveCname === undefined ? {} : { resolveCname: options.resolveCname }),
|
|
140
211
|
});
|
|
141
|
-
const
|
|
212
|
+
const authentication = [
|
|
142
213
|
["SPF", report.spf],
|
|
143
214
|
["DKIM", report.dkim],
|
|
144
215
|
["DMARC", report.dmarc],
|
|
145
216
|
];
|
|
217
|
+
const reply = report.replyTo === null ? [] : [["REPLY", report.replyTo]];
|
|
218
|
+
const paths = report.returnPath.map((check) => ["PATH", check]);
|
|
146
219
|
output.log(`sender domain ${report.domain}`);
|
|
147
|
-
for (const [name, check] of
|
|
148
|
-
const line = `${name.padEnd(6)}${check.status.padEnd(6)}${check.finding
|
|
220
|
+
for (const [name, check] of [...authentication, ...reply, ...paths]) {
|
|
221
|
+
const line = `${name.padEnd(6)}${check.status.padEnd(6)}${`${check.finding} `.padEnd(15)}${check.host}${check.record === null ? "" : ` ${check.record}`}`;
|
|
149
222
|
if (check.status === "fail")
|
|
150
223
|
output.error(line);
|
|
151
224
|
else
|
|
152
225
|
output.log(line);
|
|
153
226
|
}
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
227
|
+
const countFailed = (checks) => checks.filter(([, check]) => check.status === "fail").length;
|
|
228
|
+
const failedAuthentication = countFailed(authentication);
|
|
229
|
+
const failedReply = countFailed(reply);
|
|
230
|
+
const failedPaths = countFailed(paths);
|
|
231
|
+
if (failedAuthentication + failedReply + failedPaths === 0) {
|
|
232
|
+
output.log("receivers can authenticate mail from this domain");
|
|
233
|
+
return EXIT_OK;
|
|
234
|
+
}
|
|
235
|
+
if (failedAuthentication > 0)
|
|
236
|
+
output.log(`${String(failedAuthentication)} check(s) failed: list mail from this domain will land in spam or be refused`);
|
|
237
|
+
if (failedReply > 0)
|
|
238
|
+
output.log("the reply-to domain does not accept mail: replies will bounce");
|
|
239
|
+
if (failedPaths > 0)
|
|
240
|
+
output.log(`${String(failedPaths)} return-path host(s) failed: the provider cannot use them for bounces`);
|
|
241
|
+
return EXIT_FAILED;
|
|
157
242
|
}
|
|
158
243
|
async function runCampaign(command, options, output) {
|
|
159
244
|
const cwd = options.cwd ?? process.cwd();
|
package/dist/cli/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
package/dist/server/dns.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type DnsCheckStatus = "pass" | "warn" | "fail";
|
|
2
|
-
export type DnsFinding = "found" | "missing" | "multiple" | "permissive" | "revoked" | "monitor-only" | "inherited" | "lookup-failed";
|
|
2
|
+
export type DnsFinding = "found" | "missing" | "multiple" | "permissive" | "revoked" | "monitor-only" | "inherited" | "weak" | "null-mx" | "unexpected-target" | "lookup-failed";
|
|
3
3
|
export interface DnsCheck {
|
|
4
4
|
readonly status: DnsCheckStatus;
|
|
5
5
|
readonly finding: DnsFinding;
|
|
@@ -13,8 +13,37 @@ export interface SenderDnsReport {
|
|
|
13
13
|
readonly spf: DnsCheck;
|
|
14
14
|
readonly dkim: DnsCheck;
|
|
15
15
|
readonly dmarc: DnsCheck;
|
|
16
|
+
/** The reply-to domain's MX, when `replyTo` was given. */
|
|
17
|
+
readonly replyTo: DnsCheck | null;
|
|
18
|
+
/** One check per `returnPath` host, in the order given. */
|
|
19
|
+
readonly returnPath: readonly DnsCheck[];
|
|
16
20
|
}
|
|
17
21
|
export type ResolveTxt = (hostname: string) => Promise<string[][]>;
|
|
22
|
+
export interface MxRecord {
|
|
23
|
+
readonly exchange: string;
|
|
24
|
+
readonly priority: number;
|
|
25
|
+
}
|
|
26
|
+
export type ResolveMx = (hostname: string) => Promise<MxRecord[]>;
|
|
27
|
+
export type ResolveCname = (hostname: string) => Promise<string[]>;
|
|
28
|
+
export type DmarcPolicy = "quarantine" | "reject";
|
|
29
|
+
export type DmarcAlignment = "r" | "s";
|
|
30
|
+
/** The least a DMARC record must carry; a weaker one fails as `weak`. Absent tags count as their defaults. */
|
|
31
|
+
export interface DmarcExpectation {
|
|
32
|
+
/** The policy for the checked domain: `p`, or `sp ?? p` of a parent's record. Also requires `pct` 100. */
|
|
33
|
+
readonly policy?: DmarcPolicy;
|
|
34
|
+
/** The policy for subdomains: `sp ?? p`. */
|
|
35
|
+
readonly subdomainPolicy?: DmarcPolicy;
|
|
36
|
+
/** `adkim`; absent means relaxed (`r`). */
|
|
37
|
+
readonly adkim?: DmarcAlignment;
|
|
38
|
+
/** `aspf`; absent means relaxed (`r`). */
|
|
39
|
+
readonly aspf?: DmarcAlignment;
|
|
40
|
+
}
|
|
41
|
+
/** A host the provider uses for MAIL FROM or bounces. */
|
|
42
|
+
export interface ReturnPathHost {
|
|
43
|
+
readonly host: string;
|
|
44
|
+
/** When set, a CNAME must point at this domain or under it (`rmta.net` accepts `send.forge.rmta.net`). */
|
|
45
|
+
readonly targetDomain?: string;
|
|
46
|
+
}
|
|
18
47
|
export interface CheckSenderDnsOptions {
|
|
19
48
|
/** DKIM selectors to look up under `_domainkey`. Default `["resend"]`, the Resend selector. */
|
|
20
49
|
readonly dkimSelectors?: readonly string[];
|
|
@@ -23,9 +52,27 @@ export interface CheckSenderDnsOptions {
|
|
|
23
52
|
* return path); DMARC accepts that in relaxed alignment.
|
|
24
53
|
*/
|
|
25
54
|
readonly spfHosts?: readonly string[];
|
|
55
|
+
/** Turns a DMARC record weaker than this into a `fail` (e.g. `{ policy: "reject", adkim: "s", aspf: "s" }`). */
|
|
56
|
+
readonly expectDmarc?: DmarcExpectation;
|
|
57
|
+
/**
|
|
58
|
+
* Where replies go (an address, `Name <address>` or a domain): its domain must have MX records and at most one
|
|
59
|
+
* SPF record, or replies bounce while the sender checks pass.
|
|
60
|
+
*/
|
|
61
|
+
readonly replyTo?: string;
|
|
62
|
+
/** Hosts that must resolve as a CNAME or with MX records; `resendReturnPath(domain)` gives Resend's. */
|
|
63
|
+
readonly returnPath?: readonly ReturnPathHost[];
|
|
26
64
|
readonly resolveTxt?: ResolveTxt;
|
|
65
|
+
readonly resolveMx?: ResolveMx;
|
|
66
|
+
readonly resolveCname?: ResolveCname;
|
|
27
67
|
}
|
|
28
68
|
export declare const DEFAULT_DKIM_SELECTORS: readonly string[];
|
|
69
|
+
/** Domain of the CNAME targets Resend publishes for its return-path hosts. */
|
|
70
|
+
export declare const RESEND_RETURN_PATH_DOMAIN = "rmta.net";
|
|
71
|
+
/**
|
|
72
|
+
* Resend's return-path hosts: `send.<domain>` (MAIL FROM) and `rsend.<domain>`, CNAMEs to `*.rmta.net`. Domains
|
|
73
|
+
* set up before Resend published `rsend` have MX records on `send` and no `rsend`: check `send` alone there.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resendReturnPath(domain: string): ReturnPathHost[];
|
|
29
76
|
/** Reads the SPF, DKIM and DMARC records of `domain`. Never throws: a failed lookup is a finding. */
|
|
30
77
|
export declare function checkSenderDns(domain: string, options?: CheckSenderDnsOptions): Promise<SenderDnsReport>;
|
|
31
78
|
/** The domain part of a sender (`Plan <hello@mail.example.com>` gives `mail.example.com`). */
|
package/dist/server/dns.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dns.d.ts","sourceRoot":"","sources":["../../src/server/dns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dns.d.ts","sourceRoot":"","sources":["../../src/server/dns.ts"],"names":[],"mappings":"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"}
|
package/dist/server/dns.js
CHANGED
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
// The sender domain's DNS, as receivers check it: SPF (RFC 7208), DKIM (RFC 6376) and DMARC
|
|
2
|
-
// (RFC 7489). Without all three, list mail lands in spam or is refused outright.
|
|
3
|
-
//
|
|
4
|
-
|
|
2
|
+
// (RFC 7489). Without all three, list mail lands in spam or is refused outright. On request it also
|
|
3
|
+
// holds DMARC to a required minimum, checks that the reply-to domain accepts mail (MX) and that the
|
|
4
|
+
// provider's return-path hosts resolve. The check only reads public records; it cannot see whether
|
|
5
|
+
// the provider signs with the published key.
|
|
6
|
+
import { resolveCname as resolveCnameRecords, resolveMx as resolveMxRecords, resolveTxt as resolveTxtRecords } from "node:dns/promises";
|
|
5
7
|
export const DEFAULT_DKIM_SELECTORS = ["resend"];
|
|
8
|
+
/** Domain of the CNAME targets Resend publishes for its return-path hosts. */
|
|
9
|
+
export const RESEND_RETURN_PATH_DOMAIN = "rmta.net";
|
|
10
|
+
/**
|
|
11
|
+
* Resend's return-path hosts: `send.<domain>` (MAIL FROM) and `rsend.<domain>`, CNAMEs to `*.rmta.net`. Domains
|
|
12
|
+
* set up before Resend published `rsend` have MX records on `send` and no `rsend`: check `send` alone there.
|
|
13
|
+
*/
|
|
14
|
+
export function resendReturnPath(domain) {
|
|
15
|
+
const name = normalizeHost(domain);
|
|
16
|
+
return [
|
|
17
|
+
{ host: `send.${name}`, targetDomain: RESEND_RETURN_PATH_DOMAIN },
|
|
18
|
+
{ host: `rsend.${name}`, targetDomain: RESEND_RETURN_PATH_DOMAIN },
|
|
19
|
+
];
|
|
20
|
+
}
|
|
6
21
|
/** Reads the SPF, DKIM and DMARC records of `domain`. Never throws: a failed lookup is a finding. */
|
|
7
22
|
export async function checkSenderDns(domain, options = {}) {
|
|
8
|
-
const name = domain
|
|
23
|
+
const name = normalizeHost(domain);
|
|
9
24
|
const resolveTxt = options.resolveTxt ?? resolveTxtRecords;
|
|
10
25
|
const lookup = (host) => lookupTxt(resolveTxt, host);
|
|
11
|
-
const
|
|
26
|
+
const lookupMx = (host) => lookupRecords(options.resolveMx ?? resolveMxRecords, host);
|
|
27
|
+
const lookupCname = (host) => lookupRecords(options.resolveCname ?? resolveCnameRecords, host);
|
|
28
|
+
const [spf, dkim, dmarc, replyTo, returnPath] = await Promise.all([
|
|
12
29
|
checkSpf(lookup, options.spfHosts ?? [name]),
|
|
13
30
|
checkDkim(lookup, (options.dkimSelectors ?? DEFAULT_DKIM_SELECTORS).map((selector) => `${selector}._domainkey.${name}`)),
|
|
14
|
-
checkDmarc(lookup, name),
|
|
31
|
+
checkDmarc(lookup, name, options.expectDmarc),
|
|
32
|
+
options.replyTo === undefined ? null : checkReplyPath(lookup, lookupMx, normalizeHost(getSenderDomain(options.replyTo))),
|
|
33
|
+
Promise.all((options.returnPath ?? []).map((path) => checkReturnPath(lookupCname, lookupMx, path))),
|
|
15
34
|
]);
|
|
16
|
-
return { domain: name, spf, dkim, dmarc };
|
|
35
|
+
return { domain: name, spf, dkim, dmarc, replyTo, returnPath };
|
|
17
36
|
}
|
|
18
37
|
/** The domain part of a sender (`Plan <hello@mail.example.com>` gives `mail.example.com`). */
|
|
19
38
|
export function getSenderDomain(from) {
|
|
@@ -24,11 +43,13 @@ export function getSenderDomain(from) {
|
|
|
24
43
|
const address = open !== -1 && close > open ? from.slice(open + 1, close) : from;
|
|
25
44
|
return address.slice(address.lastIndexOf("@") + 1).trim().toLowerCase();
|
|
26
45
|
}
|
|
46
|
+
function normalizeHost(host) {
|
|
47
|
+
return host.trim().toLowerCase().replace(/\.$/, "");
|
|
48
|
+
}
|
|
27
49
|
const NO_RECORD_CODES = new Set(["ENOTFOUND", "ENODATA", "NXDOMAIN"]);
|
|
28
|
-
async function
|
|
50
|
+
async function lookupRecords(resolve, host) {
|
|
29
51
|
try {
|
|
30
|
-
|
|
31
|
-
const records = (await resolveTxt(host)).map((chunks) => chunks.join(""));
|
|
52
|
+
const records = await resolve(host);
|
|
32
53
|
return records.length === 0 ? { kind: "none" } : { kind: "records", records };
|
|
33
54
|
}
|
|
34
55
|
catch (error) {
|
|
@@ -36,6 +57,13 @@ async function lookupTxt(resolveTxt, host) {
|
|
|
36
57
|
return typeof code === "string" && NO_RECORD_CODES.has(code) ? { kind: "none" } : { kind: "error" };
|
|
37
58
|
}
|
|
38
59
|
}
|
|
60
|
+
async function lookupTxt(resolveTxt, host) {
|
|
61
|
+
// A TXT record may arrive in 255-byte chunks; they form one string.
|
|
62
|
+
return lookupRecords(async (name) => (await resolveTxt(name)).map((chunks) => chunks.join("")), host);
|
|
63
|
+
}
|
|
64
|
+
function isSpfRecord(record) {
|
|
65
|
+
return /^v=spf1(\s|$)/i.test(record.trim());
|
|
66
|
+
}
|
|
39
67
|
function startsWithTag(record, tag) {
|
|
40
68
|
return record.trim().toLowerCase().startsWith(tag);
|
|
41
69
|
}
|
|
@@ -48,7 +76,7 @@ async function checkSpf(lookup, hosts) {
|
|
|
48
76
|
lookupFailed ??= host;
|
|
49
77
|
continue;
|
|
50
78
|
}
|
|
51
|
-
const records = answer.kind === "records" ? answer.records.filter(
|
|
79
|
+
const records = answer.kind === "records" ? answer.records.filter(isSpfRecord) : [];
|
|
52
80
|
if (records.length > 1)
|
|
53
81
|
return { status: "fail", finding: "multiple", host, record: null };
|
|
54
82
|
const record = records[0];
|
|
@@ -83,9 +111,10 @@ async function checkDkim(lookup, hosts) {
|
|
|
83
111
|
}
|
|
84
112
|
/**
|
|
85
113
|
* `_dmarc.<domain>`, or the nearest parent's record (the organisational domain's policy, with
|
|
86
|
-
* `sp=` for subdomains when it is set). `p=none` only reports; it protects nothing.
|
|
114
|
+
* `sp=` for subdomains when it is set). `p=none` only reports; it protects nothing. With an
|
|
115
|
+
* expectation, a record weaker than it fails as `weak`.
|
|
87
116
|
*/
|
|
88
|
-
async function checkDmarc(lookup, domain) {
|
|
117
|
+
async function checkDmarc(lookup, domain, expected) {
|
|
89
118
|
const labels = domain.split(".");
|
|
90
119
|
const first = `_dmarc.${domain}`;
|
|
91
120
|
for (let index = 0; index <= labels.length - 2; index += 1) {
|
|
@@ -102,12 +131,92 @@ async function checkDmarc(lookup, domain) {
|
|
|
102
131
|
if (record === undefined)
|
|
103
132
|
continue;
|
|
104
133
|
const inherited = host !== first;
|
|
105
|
-
const
|
|
106
|
-
const policy = (inherited ? (
|
|
134
|
+
const tags = readDmarcTags(record);
|
|
135
|
+
const policy = (inherited ? (tags.get("sp") ?? tags.get("p")) : tags.get("p")) ?? "none";
|
|
136
|
+
if (expected !== undefined && !meetsDmarcExpectation(tags, policy, expected))
|
|
137
|
+
return { status: "fail", finding: "weak", host, record };
|
|
107
138
|
if (policy === "none")
|
|
108
139
|
return { status: "warn", finding: "monitor-only", host, record };
|
|
109
140
|
return inherited ? { status: "pass", finding: "inherited", host, record } : { status: "pass", finding: "found", host, record };
|
|
110
141
|
}
|
|
111
142
|
return { status: "fail", finding: "missing", host: first, record: null };
|
|
112
143
|
}
|
|
144
|
+
/** `tag=value` pairs of a DMARC record, names and values lower-cased; the first occurrence wins. */
|
|
145
|
+
function readDmarcTags(record) {
|
|
146
|
+
const tags = new Map();
|
|
147
|
+
for (const part of record.split(";")) {
|
|
148
|
+
const separator = part.indexOf("=");
|
|
149
|
+
if (separator === -1)
|
|
150
|
+
continue;
|
|
151
|
+
const name = part.slice(0, separator).trim().toLowerCase();
|
|
152
|
+
if (!tags.has(name))
|
|
153
|
+
tags.set(name, part.slice(separator + 1).trim().toLowerCase());
|
|
154
|
+
}
|
|
155
|
+
return tags;
|
|
156
|
+
}
|
|
157
|
+
const POLICY_RANK = { none: 0, quarantine: 1, reject: 2 };
|
|
158
|
+
/** An unknown policy value counts as `none`, as receivers treat an invalid `p=`. */
|
|
159
|
+
function rankPolicy(policy) {
|
|
160
|
+
return (policy === undefined ? undefined : POLICY_RANK[policy]) ?? 0;
|
|
161
|
+
}
|
|
162
|
+
function meetsAlignment(actual, expected) {
|
|
163
|
+
return expected !== "s" || actual === "s";
|
|
164
|
+
}
|
|
165
|
+
function meetsDmarcExpectation(tags, policy, expected) {
|
|
166
|
+
if (expected.policy !== undefined) {
|
|
167
|
+
if (rankPolicy(policy) < rankPolicy(expected.policy))
|
|
168
|
+
return false;
|
|
169
|
+
const percent = tags.get("pct");
|
|
170
|
+
if (percent !== undefined && Number(percent) !== 100)
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
if (expected.subdomainPolicy !== undefined && rankPolicy(tags.get("sp") ?? tags.get("p")) < rankPolicy(expected.subdomainPolicy))
|
|
174
|
+
return false;
|
|
175
|
+
return meetsAlignment(tags.get("adkim"), expected.adkim) && meetsAlignment(tags.get("aspf"), expected.aspf);
|
|
176
|
+
}
|
|
177
|
+
function formatMx(records) {
|
|
178
|
+
return [...records]
|
|
179
|
+
.sort((left, right) => left.priority - right.priority)
|
|
180
|
+
.map((record) => `${String(record.priority)} ${normalizeHost(record.exchange) || "."}`)
|
|
181
|
+
.join(", ");
|
|
182
|
+
}
|
|
183
|
+
/** A null MX (RFC 7505: one record, exchange `.`) says the domain accepts no mail. Node reports it as `""`. */
|
|
184
|
+
function isNullMx(records) {
|
|
185
|
+
return records.length === 1 && normalizeHost(records[0]?.exchange ?? "") === "";
|
|
186
|
+
}
|
|
187
|
+
/** The reply-to domain must accept mail (MX, not a null MX) and publish at most one SPF record. */
|
|
188
|
+
async function checkReplyPath(lookup, lookupMx, host) {
|
|
189
|
+
const mx = await lookupMx(host);
|
|
190
|
+
if (mx.kind === "error")
|
|
191
|
+
return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
192
|
+
if (mx.kind === "none")
|
|
193
|
+
return { status: "fail", finding: "missing", host, record: null };
|
|
194
|
+
if (isNullMx(mx.records))
|
|
195
|
+
return { status: "fail", finding: "null-mx", host, record: formatMx(mx.records) };
|
|
196
|
+
const txt = await lookup(host);
|
|
197
|
+
if (txt.kind === "error")
|
|
198
|
+
return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
199
|
+
if (txt.kind === "records" && txt.records.filter(isSpfRecord).length > 1)
|
|
200
|
+
return { status: "fail", finding: "multiple", host, record: null };
|
|
201
|
+
return { status: "pass", finding: "found", host, record: formatMx(mx.records) };
|
|
202
|
+
}
|
|
203
|
+
/** A CNAME (to `targetDomain` or under it, when set), else MX records. Strings, not patterns: the domain is input. */
|
|
204
|
+
async function checkReturnPath(lookupCname, lookupMx, path) {
|
|
205
|
+
const host = normalizeHost(path.host);
|
|
206
|
+
const cname = await lookupCname(host);
|
|
207
|
+
if (cname.kind === "error")
|
|
208
|
+
return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
209
|
+
if (cname.kind === "records") {
|
|
210
|
+
const target = normalizeHost(cname.records[0] ?? "");
|
|
211
|
+
const expected = path.targetDomain === undefined ? null : normalizeHost(path.targetDomain);
|
|
212
|
+
const matches = expected === null || target === expected || target.endsWith(`.${expected}`);
|
|
213
|
+
return matches ? { status: "pass", finding: "found", host, record: target } : { status: "fail", finding: "unexpected-target", host, record: target };
|
|
214
|
+
}
|
|
215
|
+
const mx = await lookupMx(host);
|
|
216
|
+
if (mx.kind === "error")
|
|
217
|
+
return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
218
|
+
if (mx.kind === "none" || isNullMx(mx.records))
|
|
219
|
+
return { status: "fail", finding: "missing", host, record: null };
|
|
220
|
+
return { status: "pass", finding: "found", host, record: formatMx(mx.records) };
|
|
221
|
+
}
|
|
113
222
|
//# sourceMappingURL=dns.js.map
|
package/dist/server/dns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dns.js","sourceRoot":"","sources":["../../src/server/dns.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dns.js","sourceRoot":"","sources":["../../src/server/dns.ts"],"names":[],"mappings":"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"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { getCampaignProblems, parseCampaignFile, parseRecipientList, type CampaignContent, type CampaignFile, type CampaignFileResult } from "./campaign-file.js";
|
|
2
2
|
export { getCampaignContentHash, planCampaign, registerCampaign, sendCampaign, type CampaignErrorCode, type CampaignHalt, type CampaignPlan, type CampaignSummary, type SendCampaignOptions, } from "./campaigns.js";
|
|
3
3
|
export { DEFAULT_MAX_ATTEMPTS, DEFAULT_STALE_CLAIM_MS, DEFAULT_UNCERTAIN_CLAIM_MS, deliverOnce, type DeliverOptions, type Delivery, type DeliveryContext, type DeliveryOutcome, type HaltingErrorCode, } from "./deliveries.js";
|
|
4
|
-
export { checkSenderDns, DEFAULT_DKIM_SELECTORS, getSenderDomain, type CheckSenderDnsOptions, type DnsCheck, type DnsCheckStatus, type DnsFinding, type ResolveTxt, type SenderDnsReport, } from "./dns.js";
|
|
4
|
+
export { checkSenderDns, DEFAULT_DKIM_SELECTORS, getSenderDomain, RESEND_RETURN_PATH_DOMAIN, resendReturnPath, type CheckSenderDnsOptions, type DmarcAlignment, type DmarcExpectation, type DmarcPolicy, type DnsCheck, type DnsCheckStatus, type DnsFinding, type MxRecord, type ResolveCname, type ResolveMx, type ResolveTxt, type ReturnPathHost, type SenderDnsReport, } from "./dns.js";
|
|
5
5
|
export { checkMailingTables } from "./health.js";
|
|
6
6
|
export { addHtmlFooter, addTextFooter, getListUnsubscribeHeaders, SIGNATURE_SEPARATOR } from "./list-mail.js";
|
|
7
7
|
export { getMailingModule, getMailingOptions, getMailingRoutes, type MailingRoutes } from "./options.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClK,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC9G,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACzG,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC3H,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,6BAA6B,EAC7B,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClK,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,yBAAyB,EACzB,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC9G,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACzG,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC3H,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,6BAA6B,EAC7B,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export { getCampaignProblems, parseCampaignFile, parseRecipientList } from "./campaign-file.js";
|
|
4
4
|
export { getCampaignContentHash, planCampaign, registerCampaign, sendCampaign, } from "./campaigns.js";
|
|
5
5
|
export { DEFAULT_MAX_ATTEMPTS, DEFAULT_STALE_CLAIM_MS, DEFAULT_UNCERTAIN_CLAIM_MS, deliverOnce, } from "./deliveries.js";
|
|
6
|
-
export { checkSenderDns, DEFAULT_DKIM_SELECTORS, getSenderDomain, } from "./dns.js";
|
|
6
|
+
export { checkSenderDns, DEFAULT_DKIM_SELECTORS, getSenderDomain, RESEND_RETURN_PATH_DOMAIN, resendReturnPath, } from "./dns.js";
|
|
7
7
|
export { checkMailingTables } from "./health.js";
|
|
8
8
|
export { addHtmlFooter, addTextFooter, getListUnsubscribeHeaders, SIGNATURE_SEPARATOR } from "./list-mail.js";
|
|
9
9
|
export { getMailingModule, getMailingOptions, getMailingRoutes } from "./options.js";
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,wFAAwF;AACxF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAoE,MAAM,oBAAoB,CAAC;AAClK,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,YAAY,GAMb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,WAAW,GAMZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,wFAAwF;AACxF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAoE,MAAM,oBAAoB,CAAC;AAClK,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,YAAY,GAMb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,WAAW,GAMZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,yBAAyB,EACzB,gBAAgB,GAcjB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC9G,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAsB,MAAM,cAAc,CAAC;AACzG,OAAO,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AAC3H,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,6BAA6B,EAC7B,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,GAOvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAuC,MAAM,oBAAoB,CAAC"}
|
package/module.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softure-ai/mailing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "SOFTURE AI mailing module: sendMail over a provider adapter (Resend first) with plain-text and HTML bodies, sender and reply-to from config, idempotency keys, a timeout and a typed result; signed one-click unsubscribe (RFC 8058) with a suppression list for list mail; an exactly-once delivery ledger, campaigns sent from a content file by the softure-mail command, and a sender DNS check; a fake provider for tests.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/cli/run.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { openCommandDatabase, type CommandDatabase, type DatabaseHandle } from "
|
|
|
14
14
|
import { parseCampaignFile, parseRecipientList, type CampaignContent } from "../server/campaign-file.js";
|
|
15
15
|
import { planCampaign, sendCampaign, type CampaignSummary } from "../server/campaigns.js";
|
|
16
16
|
import type { DeliveryContext, HaltingErrorCode } from "../server/deliveries.js";
|
|
17
|
-
import { checkSenderDns, getSenderDomain, type DnsCheck, type ResolveTxt } from "../server/dns.js";
|
|
17
|
+
import { checkSenderDns, getSenderDomain, resendReturnPath, type DmarcAlignment, type DmarcExpectation, type DmarcPolicy, type DnsCheck, type ResolveCname, type ResolveMx, type ResolveTxt, type ReturnPathHost } from "../server/dns.js";
|
|
18
18
|
import { getMailingOptions } from "../server/options.js";
|
|
19
19
|
import { MIN_UNSUBSCRIBE_SECRET_LENGTH, readUnsubscribeSecrets, UNSUBSCRIBE_SECRET_ENV, type Env } from "../server/unsubscribe-link.js";
|
|
20
20
|
|
|
@@ -34,6 +34,8 @@ export interface RunMailCliOptions {
|
|
|
34
34
|
/** Opens the campaign's database connection. Default: the config's `database.handle`, else `createDatabase(url, { max: 1 })`. */
|
|
35
35
|
readonly openDatabase?: (url: string) => Promise<DatabaseHandle>;
|
|
36
36
|
readonly resolveTxt?: ResolveTxt;
|
|
37
|
+
readonly resolveMx?: ResolveMx;
|
|
38
|
+
readonly resolveCname?: ResolveCname;
|
|
37
39
|
readonly sleep?: (ms: number) => Promise<void>;
|
|
38
40
|
readonly env?: Env;
|
|
39
41
|
}
|
|
@@ -48,6 +50,8 @@ export const DEFAULT_PAUSE_MS = 500;
|
|
|
48
50
|
export const MAIL_USAGE = `Usage:
|
|
49
51
|
softure-mail campaign <content-file> --recipients <file> [--dry-run] [--pause-ms <ms>] [--resend-uncertain]
|
|
50
52
|
softure-mail dns [--domain <domain>] [--dkim-selector <name>]... [--spf-host <host>]...
|
|
53
|
+
[--dmarc-policy <p>] [--dmarc-sp <p>] [--dmarc-adkim <a>] [--dmarc-aspf <a>]
|
|
54
|
+
[--reply-to <address>] [--return-path <host>]... [--resend-return-path]
|
|
51
55
|
|
|
52
56
|
campaign Sends the campaign in <content-file> (frontmatter id, kind, subject, optional html,
|
|
53
57
|
then the text body) to every address in the recipients file (one per line), at most
|
|
@@ -63,6 +67,15 @@ dns Checks SPF, DKIM and DMARC for the sender domain (default: the domain
|
|
|
63
67
|
--dkim-selector <name> DKIM selector to look up (default resend; repeatable)
|
|
64
68
|
--spf-host <host> where SPF is published (default the domain; repeatable;
|
|
65
69
|
Resend publishes it on send.<domain>)
|
|
70
|
+
--dmarc-policy <p> require at least this DMARC policy (quarantine or reject)
|
|
71
|
+
and pct=100; a weaker record fails
|
|
72
|
+
--dmarc-sp <p> require at least this subdomain policy (sp, else p)
|
|
73
|
+
--dmarc-adkim <a> require this DKIM alignment (r or s; absent counts as r)
|
|
74
|
+
--dmarc-aspf <a> require this SPF alignment (r or s; absent counts as r)
|
|
75
|
+
--reply-to <address> check that this address's domain accepts mail (MX, one SPF)
|
|
76
|
+
(default: replyTo of the config, when --domain is not given)
|
|
77
|
+
--return-path <host> a return-path host that must be a CNAME or have MX (repeatable)
|
|
78
|
+
--resend-return-path check Resend's send.<domain> and rsend.<domain> CNAMEs
|
|
66
79
|
|
|
67
80
|
Options for both:
|
|
68
81
|
--config <file> the app's softure.config file (bin only)
|
|
@@ -83,7 +96,20 @@ type Command =
|
|
|
83
96
|
readonly pauseMs: number;
|
|
84
97
|
readonly resendUncertain: boolean;
|
|
85
98
|
}
|
|
86
|
-
| {
|
|
99
|
+
| {
|
|
100
|
+
readonly kind: "dns";
|
|
101
|
+
readonly domain: string | undefined;
|
|
102
|
+
readonly dkimSelectors: readonly string[] | undefined;
|
|
103
|
+
readonly spfHosts: readonly string[] | undefined;
|
|
104
|
+
readonly expectDmarc: DmarcExpectation | undefined;
|
|
105
|
+
readonly replyTo: string | undefined;
|
|
106
|
+
readonly returnPathHosts: readonly string[];
|
|
107
|
+
readonly resendReturnPath: boolean;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const DMARC_POLICIES: readonly DmarcPolicy[] = ["quarantine", "reject"];
|
|
111
|
+
const DMARC_ALIGNMENTS: readonly DmarcAlignment[] = ["r", "s"];
|
|
112
|
+
const DNS_ONLY_OPTIONS = ["domain", "dkim-selector", "spf-host", "dmarc-policy", "dmarc-sp", "dmarc-adkim", "dmarc-aspf", "reply-to", "return-path", "resend-return-path"] as const;
|
|
87
113
|
|
|
88
114
|
/** Runs the command and returns the process exit code: 0 done, 1 failed or incomplete, 2 usage error. */
|
|
89
115
|
export async function runMailCli(options: RunMailCliOptions): Promise<number> {
|
|
@@ -124,10 +150,21 @@ function parseCommand(argv: readonly string[]): Command | string {
|
|
|
124
150
|
const misplaced = (["recipients", "dry-run", "pause-ms", "resend-uncertain"] as const).filter((option) => values[option] !== undefined);
|
|
125
151
|
if (misplaced.length > 0) return `dns does not take --${misplaced.join(", --")}`;
|
|
126
152
|
if (positionals.length > 0) return `dns takes no file, got "${positionals.join(" ")}"`;
|
|
127
|
-
|
|
153
|
+
const expectDmarc = parseDmarcExpectation(values);
|
|
154
|
+
if (typeof expectDmarc === "string") return expectDmarc;
|
|
155
|
+
return {
|
|
156
|
+
kind: "dns",
|
|
157
|
+
domain: values.domain,
|
|
158
|
+
dkimSelectors: values["dkim-selector"],
|
|
159
|
+
spfHosts: values["spf-host"],
|
|
160
|
+
expectDmarc,
|
|
161
|
+
replyTo: values["reply-to"],
|
|
162
|
+
returnPathHosts: values["return-path"] ?? [],
|
|
163
|
+
resendReturnPath: values["resend-return-path"] === true,
|
|
164
|
+
};
|
|
128
165
|
}
|
|
129
166
|
|
|
130
|
-
const misplaced =
|
|
167
|
+
const misplaced = DNS_ONLY_OPTIONS.filter((option) => values[option] !== undefined);
|
|
131
168
|
if (misplaced.length > 0) return `campaign does not take --${misplaced.join(", --")}`;
|
|
132
169
|
const [contentFile, ...extra] = positionals;
|
|
133
170
|
if (contentFile === undefined) return "campaign needs a content file";
|
|
@@ -149,6 +186,13 @@ function parseCommandArgs(args: readonly string[]) {
|
|
|
149
186
|
domain: { type: "string" },
|
|
150
187
|
"dkim-selector": { type: "string", multiple: true },
|
|
151
188
|
"spf-host": { type: "string", multiple: true },
|
|
189
|
+
"dmarc-policy": { type: "string" },
|
|
190
|
+
"dmarc-sp": { type: "string" },
|
|
191
|
+
"dmarc-adkim": { type: "string" },
|
|
192
|
+
"dmarc-aspf": { type: "string" },
|
|
193
|
+
"reply-to": { type: "string" },
|
|
194
|
+
"return-path": { type: "string", multiple: true },
|
|
195
|
+
"resend-return-path": { type: "boolean" },
|
|
152
196
|
help: { type: "boolean" },
|
|
153
197
|
},
|
|
154
198
|
strict: true,
|
|
@@ -156,34 +200,82 @@ function parseCommandArgs(args: readonly string[]) {
|
|
|
156
200
|
});
|
|
157
201
|
}
|
|
158
202
|
|
|
203
|
+
type ParsedValues = ReturnType<typeof parseCommandArgs>["values"];
|
|
204
|
+
|
|
205
|
+
/** One choice of a fixed list, case-insensitive; `undefined` when the option was not given. */
|
|
206
|
+
function pickChoice<T extends string>(values: ParsedValues, option: "dmarc-policy" | "dmarc-sp" | "dmarc-adkim" | "dmarc-aspf", allowed: readonly T[]): { readonly value: T | undefined } | string {
|
|
207
|
+
const given = values[option];
|
|
208
|
+
if (given === undefined) return { value: undefined };
|
|
209
|
+
const found = allowed.find((candidate) => candidate === given.trim().toLowerCase());
|
|
210
|
+
return found === undefined ? `--${option} expects ${allowed.join(" or ")}, got "${given}"` : { value: found };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function parseDmarcExpectation(values: ParsedValues): DmarcExpectation | undefined | string {
|
|
214
|
+
const policy = pickChoice(values, "dmarc-policy", DMARC_POLICIES);
|
|
215
|
+
if (typeof policy === "string") return policy;
|
|
216
|
+
const subdomainPolicy = pickChoice(values, "dmarc-sp", DMARC_POLICIES);
|
|
217
|
+
if (typeof subdomainPolicy === "string") return subdomainPolicy;
|
|
218
|
+
const adkim = pickChoice(values, "dmarc-adkim", DMARC_ALIGNMENTS);
|
|
219
|
+
if (typeof adkim === "string") return adkim;
|
|
220
|
+
const aspf = pickChoice(values, "dmarc-aspf", DMARC_ALIGNMENTS);
|
|
221
|
+
if (typeof aspf === "string") return aspf;
|
|
222
|
+
const expectation: DmarcExpectation = {
|
|
223
|
+
...(policy.value === undefined ? {} : { policy: policy.value }),
|
|
224
|
+
...(subdomainPolicy.value === undefined ? {} : { subdomainPolicy: subdomainPolicy.value }),
|
|
225
|
+
...(adkim.value === undefined ? {} : { adkim: adkim.value }),
|
|
226
|
+
...(aspf.value === undefined ? {} : { aspf: aspf.value }),
|
|
227
|
+
};
|
|
228
|
+
return Object.keys(expectation).length === 0 ? undefined : expectation;
|
|
229
|
+
}
|
|
230
|
+
|
|
159
231
|
async function runDns(command: Extract<Command, { kind: "dns" }>, options: RunMailCliOptions, output: CliOutput): Promise<number> {
|
|
160
232
|
let domain = command.domain;
|
|
233
|
+
let replyTo = command.replyTo;
|
|
161
234
|
if (domain === undefined) {
|
|
162
235
|
if (options.config === undefined) {
|
|
163
236
|
output.error("softure-mail dns: pass --domain <domain>, or run it with the app's config to check the sender's domain");
|
|
164
237
|
return EXIT_FAILED;
|
|
165
238
|
}
|
|
166
|
-
|
|
239
|
+
const mailing = getMailingOptions(options.config);
|
|
240
|
+
domain = getSenderDomain(mailing.from);
|
|
241
|
+
replyTo ??= mailing.replyTo;
|
|
167
242
|
}
|
|
243
|
+
const returnPath: ReturnPathHost[] = [...(command.resendReturnPath ? resendReturnPath(domain) : []), ...command.returnPathHosts.map((host) => ({ host }))];
|
|
168
244
|
const report = await checkSenderDns(domain, {
|
|
169
245
|
...(command.dkimSelectors === undefined ? {} : { dkimSelectors: command.dkimSelectors }),
|
|
170
246
|
...(command.spfHosts === undefined ? {} : { spfHosts: command.spfHosts }),
|
|
247
|
+
...(command.expectDmarc === undefined ? {} : { expectDmarc: command.expectDmarc }),
|
|
248
|
+
...(replyTo === undefined ? {} : { replyTo }),
|
|
249
|
+
returnPath,
|
|
171
250
|
...(options.resolveTxt === undefined ? {} : { resolveTxt: options.resolveTxt }),
|
|
251
|
+
...(options.resolveMx === undefined ? {} : { resolveMx: options.resolveMx }),
|
|
252
|
+
...(options.resolveCname === undefined ? {} : { resolveCname: options.resolveCname }),
|
|
172
253
|
});
|
|
173
|
-
const
|
|
254
|
+
const authentication: [string, DnsCheck][] = [
|
|
174
255
|
["SPF", report.spf],
|
|
175
256
|
["DKIM", report.dkim],
|
|
176
257
|
["DMARC", report.dmarc],
|
|
177
258
|
];
|
|
259
|
+
const reply: [string, DnsCheck][] = report.replyTo === null ? [] : [["REPLY", report.replyTo]];
|
|
260
|
+
const paths: [string, DnsCheck][] = report.returnPath.map((check) => ["PATH", check]);
|
|
178
261
|
output.log(`sender domain ${report.domain}`);
|
|
179
|
-
for (const [name, check] of
|
|
180
|
-
const line = `${name.padEnd(6)}${check.status.padEnd(6)}${check.finding
|
|
262
|
+
for (const [name, check] of [...authentication, ...reply, ...paths]) {
|
|
263
|
+
const line = `${name.padEnd(6)}${check.status.padEnd(6)}${`${check.finding} `.padEnd(15)}${check.host}${check.record === null ? "" : ` ${check.record}`}`;
|
|
181
264
|
if (check.status === "fail") output.error(line);
|
|
182
265
|
else output.log(line);
|
|
183
266
|
}
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
267
|
+
const countFailed = (checks: readonly [string, DnsCheck][]) => checks.filter(([, check]) => check.status === "fail").length;
|
|
268
|
+
const failedAuthentication = countFailed(authentication);
|
|
269
|
+
const failedReply = countFailed(reply);
|
|
270
|
+
const failedPaths = countFailed(paths);
|
|
271
|
+
if (failedAuthentication + failedReply + failedPaths === 0) {
|
|
272
|
+
output.log("receivers can authenticate mail from this domain");
|
|
273
|
+
return EXIT_OK;
|
|
274
|
+
}
|
|
275
|
+
if (failedAuthentication > 0) output.log(`${String(failedAuthentication)} check(s) failed: list mail from this domain will land in spam or be refused`);
|
|
276
|
+
if (failedReply > 0) output.log("the reply-to domain does not accept mail: replies will bounce");
|
|
277
|
+
if (failedPaths > 0) output.log(`${String(failedPaths)} return-path host(s) failed: the provider cannot use them for bounces`);
|
|
278
|
+
return EXIT_FAILED;
|
|
187
279
|
}
|
|
188
280
|
|
|
189
281
|
async function runCampaign(command: Extract<Command, { kind: "campaign" }>, options: RunMailCliOptions, output: CliOutput): Promise<number> {
|
package/src/index.ts
CHANGED
package/src/server/dns.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// The sender domain's DNS, as receivers check it: SPF (RFC 7208), DKIM (RFC 6376) and DMARC
|
|
2
|
-
// (RFC 7489). Without all three, list mail lands in spam or is refused outright.
|
|
3
|
-
//
|
|
4
|
-
|
|
2
|
+
// (RFC 7489). Without all three, list mail lands in spam or is refused outright. On request it also
|
|
3
|
+
// holds DMARC to a required minimum, checks that the reply-to domain accepts mail (MX) and that the
|
|
4
|
+
// provider's return-path hosts resolve. The check only reads public records; it cannot see whether
|
|
5
|
+
// the provider signs with the published key.
|
|
6
|
+
import { resolveCname as resolveCnameRecords, resolveMx as resolveMxRecords, resolveTxt as resolveTxtRecords } from "node:dns/promises";
|
|
5
7
|
|
|
6
8
|
export type DnsCheckStatus = "pass" | "warn" | "fail";
|
|
7
9
|
|
|
@@ -13,6 +15,9 @@ export type DnsFinding =
|
|
|
13
15
|
| "revoked"
|
|
14
16
|
| "monitor-only"
|
|
15
17
|
| "inherited"
|
|
18
|
+
| "weak"
|
|
19
|
+
| "null-mx"
|
|
20
|
+
| "unexpected-target"
|
|
16
21
|
| "lookup-failed";
|
|
17
22
|
|
|
18
23
|
export interface DnsCheck {
|
|
@@ -29,9 +34,41 @@ export interface SenderDnsReport {
|
|
|
29
34
|
readonly spf: DnsCheck;
|
|
30
35
|
readonly dkim: DnsCheck;
|
|
31
36
|
readonly dmarc: DnsCheck;
|
|
37
|
+
/** The reply-to domain's MX, when `replyTo` was given. */
|
|
38
|
+
readonly replyTo: DnsCheck | null;
|
|
39
|
+
/** One check per `returnPath` host, in the order given. */
|
|
40
|
+
readonly returnPath: readonly DnsCheck[];
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
export type ResolveTxt = (hostname: string) => Promise<string[][]>;
|
|
44
|
+
export interface MxRecord {
|
|
45
|
+
readonly exchange: string;
|
|
46
|
+
readonly priority: number;
|
|
47
|
+
}
|
|
48
|
+
export type ResolveMx = (hostname: string) => Promise<MxRecord[]>;
|
|
49
|
+
export type ResolveCname = (hostname: string) => Promise<string[]>;
|
|
50
|
+
|
|
51
|
+
export type DmarcPolicy = "quarantine" | "reject";
|
|
52
|
+
export type DmarcAlignment = "r" | "s";
|
|
53
|
+
|
|
54
|
+
/** The least a DMARC record must carry; a weaker one fails as `weak`. Absent tags count as their defaults. */
|
|
55
|
+
export interface DmarcExpectation {
|
|
56
|
+
/** The policy for the checked domain: `p`, or `sp ?? p` of a parent's record. Also requires `pct` 100. */
|
|
57
|
+
readonly policy?: DmarcPolicy;
|
|
58
|
+
/** The policy for subdomains: `sp ?? p`. */
|
|
59
|
+
readonly subdomainPolicy?: DmarcPolicy;
|
|
60
|
+
/** `adkim`; absent means relaxed (`r`). */
|
|
61
|
+
readonly adkim?: DmarcAlignment;
|
|
62
|
+
/** `aspf`; absent means relaxed (`r`). */
|
|
63
|
+
readonly aspf?: DmarcAlignment;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** A host the provider uses for MAIL FROM or bounces. */
|
|
67
|
+
export interface ReturnPathHost {
|
|
68
|
+
readonly host: string;
|
|
69
|
+
/** When set, a CNAME must point at this domain or under it (`rmta.net` accepts `send.forge.rmta.net`). */
|
|
70
|
+
readonly targetDomain?: string;
|
|
71
|
+
}
|
|
35
72
|
|
|
36
73
|
export interface CheckSenderDnsOptions {
|
|
37
74
|
/** DKIM selectors to look up under `_domainkey`. Default `["resend"]`, the Resend selector. */
|
|
@@ -41,22 +78,52 @@ export interface CheckSenderDnsOptions {
|
|
|
41
78
|
* return path); DMARC accepts that in relaxed alignment.
|
|
42
79
|
*/
|
|
43
80
|
readonly spfHosts?: readonly string[];
|
|
81
|
+
/** Turns a DMARC record weaker than this into a `fail` (e.g. `{ policy: "reject", adkim: "s", aspf: "s" }`). */
|
|
82
|
+
readonly expectDmarc?: DmarcExpectation;
|
|
83
|
+
/**
|
|
84
|
+
* Where replies go (an address, `Name <address>` or a domain): its domain must have MX records and at most one
|
|
85
|
+
* SPF record, or replies bounce while the sender checks pass.
|
|
86
|
+
*/
|
|
87
|
+
readonly replyTo?: string;
|
|
88
|
+
/** Hosts that must resolve as a CNAME or with MX records; `resendReturnPath(domain)` gives Resend's. */
|
|
89
|
+
readonly returnPath?: readonly ReturnPathHost[];
|
|
44
90
|
readonly resolveTxt?: ResolveTxt;
|
|
91
|
+
readonly resolveMx?: ResolveMx;
|
|
92
|
+
readonly resolveCname?: ResolveCname;
|
|
45
93
|
}
|
|
46
94
|
|
|
47
95
|
export const DEFAULT_DKIM_SELECTORS: readonly string[] = ["resend"];
|
|
48
96
|
|
|
97
|
+
/** Domain of the CNAME targets Resend publishes for its return-path hosts. */
|
|
98
|
+
export const RESEND_RETURN_PATH_DOMAIN = "rmta.net";
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Resend's return-path hosts: `send.<domain>` (MAIL FROM) and `rsend.<domain>`, CNAMEs to `*.rmta.net`. Domains
|
|
102
|
+
* set up before Resend published `rsend` have MX records on `send` and no `rsend`: check `send` alone there.
|
|
103
|
+
*/
|
|
104
|
+
export function resendReturnPath(domain: string): ReturnPathHost[] {
|
|
105
|
+
const name = normalizeHost(domain);
|
|
106
|
+
return [
|
|
107
|
+
{ host: `send.${name}`, targetDomain: RESEND_RETURN_PATH_DOMAIN },
|
|
108
|
+
{ host: `rsend.${name}`, targetDomain: RESEND_RETURN_PATH_DOMAIN },
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
|
|
49
112
|
/** Reads the SPF, DKIM and DMARC records of `domain`. Never throws: a failed lookup is a finding. */
|
|
50
113
|
export async function checkSenderDns(domain: string, options: CheckSenderDnsOptions = {}): Promise<SenderDnsReport> {
|
|
51
|
-
const name = domain
|
|
114
|
+
const name = normalizeHost(domain);
|
|
52
115
|
const resolveTxt = options.resolveTxt ?? resolveTxtRecords;
|
|
53
116
|
const lookup = (host: string) => lookupTxt(resolveTxt, host);
|
|
54
|
-
const
|
|
117
|
+
const lookupMx = (host: string) => lookupRecords(options.resolveMx ?? resolveMxRecords, host);
|
|
118
|
+
const lookupCname = (host: string) => lookupRecords(options.resolveCname ?? resolveCnameRecords, host);
|
|
119
|
+
const [spf, dkim, dmarc, replyTo, returnPath] = await Promise.all([
|
|
55
120
|
checkSpf(lookup, options.spfHosts ?? [name]),
|
|
56
121
|
checkDkim(lookup, (options.dkimSelectors ?? DEFAULT_DKIM_SELECTORS).map((selector) => `${selector}._domainkey.${name}`)),
|
|
57
|
-
checkDmarc(lookup, name),
|
|
122
|
+
checkDmarc(lookup, name, options.expectDmarc),
|
|
123
|
+
options.replyTo === undefined ? null : checkReplyPath(lookup, lookupMx, normalizeHost(getSenderDomain(options.replyTo))),
|
|
124
|
+
Promise.all((options.returnPath ?? []).map((path) => checkReturnPath(lookupCname, lookupMx, path))),
|
|
58
125
|
]);
|
|
59
|
-
return { domain: name, spf, dkim, dmarc };
|
|
126
|
+
return { domain: name, spf, dkim, dmarc, replyTo, returnPath };
|
|
60
127
|
}
|
|
61
128
|
|
|
62
129
|
/** The domain part of a sender (`Plan <hello@mail.example.com>` gives `mail.example.com`). */
|
|
@@ -69,15 +136,21 @@ export function getSenderDomain(from: string): string {
|
|
|
69
136
|
return address.slice(address.lastIndexOf("@") + 1).trim().toLowerCase();
|
|
70
137
|
}
|
|
71
138
|
|
|
139
|
+
function normalizeHost(host: string): string {
|
|
140
|
+
return host.trim().toLowerCase().replace(/\.$/, "");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
type Answer<T> = { readonly kind: "records"; readonly records: T[] } | { readonly kind: "none" } | { readonly kind: "error" };
|
|
144
|
+
type TxtAnswer = Answer<string>;
|
|
72
145
|
type Lookup = (host: string) => Promise<TxtAnswer>;
|
|
73
|
-
type
|
|
146
|
+
type MxLookup = (host: string) => Promise<Answer<MxRecord>>;
|
|
147
|
+
type CnameLookup = (host: string) => Promise<Answer<string>>;
|
|
74
148
|
|
|
75
149
|
const NO_RECORD_CODES = new Set(["ENOTFOUND", "ENODATA", "NXDOMAIN"]);
|
|
76
150
|
|
|
77
|
-
async function
|
|
151
|
+
async function lookupRecords<T>(resolve: (host: string) => Promise<T[]>, host: string): Promise<Answer<T>> {
|
|
78
152
|
try {
|
|
79
|
-
|
|
80
|
-
const records = (await resolveTxt(host)).map((chunks) => chunks.join(""));
|
|
153
|
+
const records = await resolve(host);
|
|
81
154
|
return records.length === 0 ? { kind: "none" } : { kind: "records", records };
|
|
82
155
|
} catch (error) {
|
|
83
156
|
const code = (error as { code?: unknown } | null)?.code;
|
|
@@ -85,6 +158,15 @@ async function lookupTxt(resolveTxt: ResolveTxt, host: string): Promise<TxtAnswe
|
|
|
85
158
|
}
|
|
86
159
|
}
|
|
87
160
|
|
|
161
|
+
async function lookupTxt(resolveTxt: ResolveTxt, host: string): Promise<TxtAnswer> {
|
|
162
|
+
// A TXT record may arrive in 255-byte chunks; they form one string.
|
|
163
|
+
return lookupRecords(async (name) => (await resolveTxt(name)).map((chunks) => chunks.join("")), host);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function isSpfRecord(record: string): boolean {
|
|
167
|
+
return /^v=spf1(\s|$)/i.test(record.trim());
|
|
168
|
+
}
|
|
169
|
+
|
|
88
170
|
function startsWithTag(record: string, tag: string): boolean {
|
|
89
171
|
return record.trim().toLowerCase().startsWith(tag);
|
|
90
172
|
}
|
|
@@ -98,7 +180,7 @@ async function checkSpf(lookup: Lookup, hosts: readonly string[]): Promise<DnsCh
|
|
|
98
180
|
lookupFailed ??= host;
|
|
99
181
|
continue;
|
|
100
182
|
}
|
|
101
|
-
const records = answer.kind === "records" ? answer.records.filter(
|
|
183
|
+
const records = answer.kind === "records" ? answer.records.filter(isSpfRecord) : [];
|
|
102
184
|
if (records.length > 1) return { status: "fail", finding: "multiple", host, record: null };
|
|
103
185
|
const record = records[0];
|
|
104
186
|
if (record === undefined) continue;
|
|
@@ -129,9 +211,10 @@ async function checkDkim(lookup: Lookup, hosts: readonly string[]): Promise<DnsC
|
|
|
129
211
|
|
|
130
212
|
/**
|
|
131
213
|
* `_dmarc.<domain>`, or the nearest parent's record (the organisational domain's policy, with
|
|
132
|
-
* `sp=` for subdomains when it is set). `p=none` only reports; it protects nothing.
|
|
214
|
+
* `sp=` for subdomains when it is set). `p=none` only reports; it protects nothing. With an
|
|
215
|
+
* expectation, a record weaker than it fails as `weak`.
|
|
133
216
|
*/
|
|
134
|
-
async function checkDmarc(lookup: Lookup, domain: string): Promise<DnsCheck> {
|
|
217
|
+
async function checkDmarc(lookup: Lookup, domain: string, expected: DmarcExpectation | undefined): Promise<DnsCheck> {
|
|
135
218
|
const labels = domain.split(".");
|
|
136
219
|
const first = `_dmarc.${domain}`;
|
|
137
220
|
for (let index = 0; index <= labels.length - 2; index += 1) {
|
|
@@ -144,10 +227,85 @@ async function checkDmarc(lookup: Lookup, domain: string): Promise<DnsCheck> {
|
|
|
144
227
|
const record = records[0];
|
|
145
228
|
if (record === undefined) continue;
|
|
146
229
|
const inherited = host !== first;
|
|
147
|
-
const
|
|
148
|
-
const policy = (inherited ? (
|
|
230
|
+
const tags = readDmarcTags(record);
|
|
231
|
+
const policy = (inherited ? (tags.get("sp") ?? tags.get("p")) : tags.get("p")) ?? "none";
|
|
232
|
+
if (expected !== undefined && !meetsDmarcExpectation(tags, policy, expected)) return { status: "fail", finding: "weak", host, record };
|
|
149
233
|
if (policy === "none") return { status: "warn", finding: "monitor-only", host, record };
|
|
150
234
|
return inherited ? { status: "pass", finding: "inherited", host, record } : { status: "pass", finding: "found", host, record };
|
|
151
235
|
}
|
|
152
236
|
return { status: "fail", finding: "missing", host: first, record: null };
|
|
153
237
|
}
|
|
238
|
+
|
|
239
|
+
/** `tag=value` pairs of a DMARC record, names and values lower-cased; the first occurrence wins. */
|
|
240
|
+
function readDmarcTags(record: string): Map<string, string> {
|
|
241
|
+
const tags = new Map<string, string>();
|
|
242
|
+
for (const part of record.split(";")) {
|
|
243
|
+
const separator = part.indexOf("=");
|
|
244
|
+
if (separator === -1) continue;
|
|
245
|
+
const name = part.slice(0, separator).trim().toLowerCase();
|
|
246
|
+
if (!tags.has(name)) tags.set(name, part.slice(separator + 1).trim().toLowerCase());
|
|
247
|
+
}
|
|
248
|
+
return tags;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const POLICY_RANK: Readonly<Record<string, number>> = { none: 0, quarantine: 1, reject: 2 };
|
|
252
|
+
|
|
253
|
+
/** An unknown policy value counts as `none`, as receivers treat an invalid `p=`. */
|
|
254
|
+
function rankPolicy(policy: string | undefined): number {
|
|
255
|
+
return (policy === undefined ? undefined : POLICY_RANK[policy]) ?? 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function meetsAlignment(actual: string | undefined, expected: DmarcAlignment | undefined): boolean {
|
|
259
|
+
return expected !== "s" || actual === "s";
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function meetsDmarcExpectation(tags: ReadonlyMap<string, string>, policy: string, expected: DmarcExpectation): boolean {
|
|
263
|
+
if (expected.policy !== undefined) {
|
|
264
|
+
if (rankPolicy(policy) < rankPolicy(expected.policy)) return false;
|
|
265
|
+
const percent = tags.get("pct");
|
|
266
|
+
if (percent !== undefined && Number(percent) !== 100) return false;
|
|
267
|
+
}
|
|
268
|
+
if (expected.subdomainPolicy !== undefined && rankPolicy(tags.get("sp") ?? tags.get("p")) < rankPolicy(expected.subdomainPolicy)) return false;
|
|
269
|
+
return meetsAlignment(tags.get("adkim"), expected.adkim) && meetsAlignment(tags.get("aspf"), expected.aspf);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function formatMx(records: readonly MxRecord[]): string {
|
|
273
|
+
return [...records]
|
|
274
|
+
.sort((left, right) => left.priority - right.priority)
|
|
275
|
+
.map((record) => `${String(record.priority)} ${normalizeHost(record.exchange) || "."}`)
|
|
276
|
+
.join(", ");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** A null MX (RFC 7505: one record, exchange `.`) says the domain accepts no mail. Node reports it as `""`. */
|
|
280
|
+
function isNullMx(records: readonly MxRecord[]): boolean {
|
|
281
|
+
return records.length === 1 && normalizeHost(records[0]?.exchange ?? "") === "";
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** The reply-to domain must accept mail (MX, not a null MX) and publish at most one SPF record. */
|
|
285
|
+
async function checkReplyPath(lookup: Lookup, lookupMx: MxLookup, host: string): Promise<DnsCheck> {
|
|
286
|
+
const mx = await lookupMx(host);
|
|
287
|
+
if (mx.kind === "error") return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
288
|
+
if (mx.kind === "none") return { status: "fail", finding: "missing", host, record: null };
|
|
289
|
+
if (isNullMx(mx.records)) return { status: "fail", finding: "null-mx", host, record: formatMx(mx.records) };
|
|
290
|
+
const txt = await lookup(host);
|
|
291
|
+
if (txt.kind === "error") return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
292
|
+
if (txt.kind === "records" && txt.records.filter(isSpfRecord).length > 1) return { status: "fail", finding: "multiple", host, record: null };
|
|
293
|
+
return { status: "pass", finding: "found", host, record: formatMx(mx.records) };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** A CNAME (to `targetDomain` or under it, when set), else MX records. Strings, not patterns: the domain is input. */
|
|
297
|
+
async function checkReturnPath(lookupCname: CnameLookup, lookupMx: MxLookup, path: ReturnPathHost): Promise<DnsCheck> {
|
|
298
|
+
const host = normalizeHost(path.host);
|
|
299
|
+
const cname = await lookupCname(host);
|
|
300
|
+
if (cname.kind === "error") return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
301
|
+
if (cname.kind === "records") {
|
|
302
|
+
const target = normalizeHost(cname.records[0] ?? "");
|
|
303
|
+
const expected = path.targetDomain === undefined ? null : normalizeHost(path.targetDomain);
|
|
304
|
+
const matches = expected === null || target === expected || target.endsWith(`.${expected}`);
|
|
305
|
+
return matches ? { status: "pass", finding: "found", host, record: target } : { status: "fail", finding: "unexpected-target", host, record: target };
|
|
306
|
+
}
|
|
307
|
+
const mx = await lookupMx(host);
|
|
308
|
+
if (mx.kind === "error") return { status: "fail", finding: "lookup-failed", host, record: null };
|
|
309
|
+
if (mx.kind === "none" || isNullMx(mx.records)) return { status: "fail", finding: "missing", host, record: null };
|
|
310
|
+
return { status: "pass", finding: "found", host, record: formatMx(mx.records) };
|
|
311
|
+
}
|
package/src/server/index.ts
CHANGED
|
@@ -27,11 +27,20 @@ export {
|
|
|
27
27
|
checkSenderDns,
|
|
28
28
|
DEFAULT_DKIM_SELECTORS,
|
|
29
29
|
getSenderDomain,
|
|
30
|
+
RESEND_RETURN_PATH_DOMAIN,
|
|
31
|
+
resendReturnPath,
|
|
30
32
|
type CheckSenderDnsOptions,
|
|
33
|
+
type DmarcAlignment,
|
|
34
|
+
type DmarcExpectation,
|
|
35
|
+
type DmarcPolicy,
|
|
31
36
|
type DnsCheck,
|
|
32
37
|
type DnsCheckStatus,
|
|
33
38
|
type DnsFinding,
|
|
39
|
+
type MxRecord,
|
|
40
|
+
type ResolveCname,
|
|
41
|
+
type ResolveMx,
|
|
34
42
|
type ResolveTxt,
|
|
43
|
+
type ReturnPathHost,
|
|
35
44
|
type SenderDnsReport,
|
|
36
45
|
} from "./dns.js";
|
|
37
46
|
export { checkMailingTables } from "./health.js";
|