agent-inbox 0.2.4 → 0.2.5
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/CLAUDE.md +1 -92
- package/README.md +6 -73
- package/dist/federation/connection-manager.d.ts +0 -8
- package/dist/federation/connection-manager.d.ts.map +1 -1
- package/dist/federation/connection-manager.js +0 -12
- package/dist/federation/connection-manager.js.map +1 -1
- package/dist/federation/delivery-queue.d.ts +3 -11
- package/dist/federation/delivery-queue.d.ts.map +1 -1
- package/dist/federation/delivery-queue.js +8 -38
- package/dist/federation/delivery-queue.js.map +1 -1
- package/dist/index.d.ts +0 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -98
- package/dist/index.js.map +1 -1
- package/dist/jsonrpc/mail-push-types.d.ts +22 -2
- package/dist/jsonrpc/mail-push-types.d.ts.map +1 -1
- package/dist/jsonrpc/mail-push-types.js +18 -1
- package/dist/jsonrpc/mail-push-types.js.map +1 -1
- package/dist/jsonrpc/mail-push.d.ts +12 -1
- package/dist/jsonrpc/mail-push.d.ts.map +1 -1
- package/dist/jsonrpc/mail-push.js +13 -2
- package/dist/jsonrpc/mail-push.js.map +1 -1
- package/dist/jsonrpc/mail-server.d.ts.map +1 -1
- package/dist/jsonrpc/mail-server.js +42 -18
- package/dist/jsonrpc/mail-server.js.map +1 -1
- package/dist/router/message-router.d.ts +0 -15
- package/dist/router/message-router.d.ts.map +1 -1
- package/dist/router/message-router.js +3 -25
- package/dist/router/message-router.js.map +1 -1
- package/dist/storage/interface.d.ts +2 -9
- package/dist/storage/interface.d.ts.map +1 -1
- package/dist/storage/memory.d.ts +1 -4
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +6 -12
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/sqlite.d.ts +1 -6
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +6 -28
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types.d.ts +0 -79
- package/dist/types.d.ts.map +1 -1
- package/docs/DESIGN.md +0 -15
- package/package.json +3 -28
- package/rules/agent-inbox.md +0 -1
- package/src/federation/connection-manager.ts +0 -12
- package/src/federation/delivery-queue.ts +8 -38
- package/src/index.ts +0 -148
- package/src/jsonrpc/mail-push-types.ts +43 -2
- package/src/jsonrpc/mail-push.ts +34 -3
- package/src/jsonrpc/mail-server.ts +45 -26
- package/src/router/message-router.ts +4 -41
- package/src/storage/interface.ts +2 -11
- package/src/storage/memory.ts +8 -15
- package/src/storage/sqlite.ts +9 -36
- package/src/types.ts +0 -73
- package/test/load.test.ts +1 -1
- package/test/mail-push.test.ts +101 -1
- package/test/mail-server.test.ts +108 -0
- package/AGENTS.md +0 -18
- package/dist/federation/queue-store.d.ts +0 -42
- package/dist/federation/queue-store.d.ts.map +0 -1
- package/dist/federation/queue-store.js +0 -87
- package/dist/federation/queue-store.js.map +0 -1
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/mail/address-book.d.ts +0 -43
- package/dist/mail/address-book.d.ts.map +0 -1
- package/dist/mail/address-book.js +0 -95
- package/dist/mail/address-book.js.map +0 -1
- package/dist/mail/attachment-store.d.ts +0 -31
- package/dist/mail/attachment-store.d.ts.map +0 -1
- package/dist/mail/attachment-store.js +0 -74
- package/dist/mail/attachment-store.js.map +0 -1
- package/dist/mail/email-mapper.d.ts +0 -41
- package/dist/mail/email-mapper.d.ts.map +0 -1
- package/dist/mail/email-mapper.js +0 -216
- package/dist/mail/email-mapper.js.map +0 -1
- package/dist/mail/fs-attachment-store.d.ts +0 -38
- package/dist/mail/fs-attachment-store.d.ts.map +0 -1
- package/dist/mail/fs-attachment-store.js +0 -165
- package/dist/mail/fs-attachment-store.js.map +0 -1
- package/dist/mail/mail-gateway.d.ts +0 -114
- package/dist/mail/mail-gateway.d.ts.map +0 -1
- package/dist/mail/mail-gateway.js +0 -402
- package/dist/mail/mail-gateway.js.map +0 -1
- package/dist/mail/provider-transport.d.ts +0 -138
- package/dist/mail/provider-transport.d.ts.map +0 -1
- package/dist/mail/provider-transport.js +0 -434
- package/dist/mail/provider-transport.js.map +0 -1
- package/dist/mail/rate-limiter.d.ts +0 -20
- package/dist/mail/rate-limiter.d.ts.map +0 -1
- package/dist/mail/rate-limiter.js +0 -56
- package/dist/mail/rate-limiter.js.map +0 -1
- package/dist/mail/smtp-transport.d.ts +0 -141
- package/dist/mail/smtp-transport.d.ts.map +0 -1
- package/dist/mail/smtp-transport.js +0 -415
- package/dist/mail/smtp-transport.js.map +0 -1
- package/dist/mail/types.d.ts +0 -177
- package/dist/mail/types.d.ts.map +0 -1
- package/dist/mail/types.js +0 -11
- package/dist/mail/types.js.map +0 -1
- package/dist/router/destination.d.ts +0 -69
- package/dist/router/destination.d.ts.map +0 -1
- package/dist/router/destination.js +0 -106
- package/dist/router/destination.js.map +0 -1
- package/docs/MAIL-INTEROP-PLAN.md +0 -660
- package/renovate.json5 +0 -6
- package/src/federation/queue-store.ts +0 -124
- package/src/mail/address-book.ts +0 -111
- package/src/mail/attachment-store.ts +0 -90
- package/src/mail/email-mapper.ts +0 -288
- package/src/mail/fs-attachment-store.ts +0 -163
- package/src/mail/mail-gateway.ts +0 -505
- package/src/mail/provider-transport.ts +0 -577
- package/src/mail/rate-limiter.ts +0 -51
- package/src/mail/smtp-transport.ts +0 -589
- package/src/mail/types.ts +0 -221
- package/src/router/destination.ts +0 -140
- package/test/federation/delivery-queue-sqlite.test.ts +0 -158
- package/test/mail/address-book.test.ts +0 -111
- package/test/mail/attachment-store-contract.test.ts +0 -92
- package/test/mail/attachment-store.test.ts +0 -69
- package/test/mail/destination.test.ts +0 -115
- package/test/mail/dsn-parse.test.ts +0 -239
- package/test/mail/email-mapper.test.ts +0 -341
- package/test/mail/external-id.test.ts +0 -43
- package/test/mail/fs-attachment-store.test.ts +0 -134
- package/test/mail/full-flow-e2e.test.ts +0 -200
- package/test/mail/mail-gateway.test.ts +0 -419
- package/test/mail/mail-transport-contract.test.ts +0 -134
- package/test/mail/mock-mail.ts +0 -161
- package/test/mail/mock-postmark.ts +0 -66
- package/test/mail/provider-transport.test.ts +0 -381
- package/test/mail/rate-limiter.test.ts +0 -48
- package/test/mail/router-mail-integration.test.ts +0 -138
- package/test/mail/smtp-e2e.test.ts +0 -98
- package/test/mail/smtp-transport.test.ts +0 -138
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MailGateway — the only mail-aware component the rest of the system touches.
|
|
3
|
-
*
|
|
4
|
-
* Ingress: transport.onReceive → policy (size / allow-list / DMARC) → dedup →
|
|
5
|
-
* bounce-detect → map → commit via router.routeMessage (single ingestion path).
|
|
6
|
-
* The transport ACKs only after this resolves (commit-before-ACK); a throw
|
|
7
|
-
* NACKs so the sender retries.
|
|
8
|
-
*
|
|
9
|
-
* Egress: router calls send() for mail-class recipients. The message is rendered
|
|
10
|
-
* and attempted; transient failures are queued durably and retried; permanent
|
|
11
|
-
* failures (and inbound DSNs) converge on one config-gated bounce handler.
|
|
12
|
-
*
|
|
13
|
-
* See docs/MAIL-INTEROP-PLAN.md §7, §8.
|
|
14
|
-
*/
|
|
15
|
-
import { createHash } from "node:crypto";
|
|
16
|
-
import { parseAddress } from "../federation/address.js";
|
|
17
|
-
import { domainMatches } from "../router/destination.js";
|
|
18
|
-
import { DeliveryQueue } from "../federation/delivery-queue.js";
|
|
19
|
-
import { AddressBook } from "./address-book.js";
|
|
20
|
-
import { RateLimiter } from "./rate-limiter.js";
|
|
21
|
-
import { inboundMailToMessage, messageToOutboundMail, UnknownRecipientError, } from "./email-mapper.js";
|
|
22
|
-
/** Single queue bucket for outbound mail retries. */
|
|
23
|
-
const MAIL_QUEUE = "mail";
|
|
24
|
-
/** Thrown to NACK over-limit inbound so the sender backs off and retries. */
|
|
25
|
-
export class RateLimitedError extends Error {
|
|
26
|
-
scope;
|
|
27
|
-
constructor(scope) {
|
|
28
|
-
super(`Inbound rate limit exceeded (${scope})`);
|
|
29
|
-
this.scope = scope;
|
|
30
|
-
this.name = "RateLimitedError";
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export class MailGateway {
|
|
34
|
-
transport;
|
|
35
|
-
storage;
|
|
36
|
-
router;
|
|
37
|
-
events;
|
|
38
|
-
config;
|
|
39
|
-
addressBook;
|
|
40
|
-
mailDomains;
|
|
41
|
-
senderLimiter = null;
|
|
42
|
-
globalLimiter = null;
|
|
43
|
-
queue;
|
|
44
|
-
retryTimer;
|
|
45
|
-
retrying = false;
|
|
46
|
-
constructor(opts) {
|
|
47
|
-
this.transport = opts.transport;
|
|
48
|
-
this.storage = opts.storage;
|
|
49
|
-
this.router = opts.router;
|
|
50
|
-
this.events = opts.events;
|
|
51
|
-
this.config = opts.config;
|
|
52
|
-
this.addressBook = new AddressBook(opts.config.identity);
|
|
53
|
-
if (this.addressBook.conflicts.length > 0) {
|
|
54
|
-
this.events.emit("mail.config.conflict", {
|
|
55
|
-
kind: "address-mapping",
|
|
56
|
-
conflicts: this.addressBook.conflicts,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
this.mailDomains = [
|
|
60
|
-
...opts.config.identity.localDomains,
|
|
61
|
-
...(opts.config.routableDomains ?? []),
|
|
62
|
-
];
|
|
63
|
-
this.queue = new DeliveryQueue(opts.events, opts.config.queue, opts.queueStore ? { store: opts.queueStore } : undefined);
|
|
64
|
-
const rl = opts.config.rateLimit;
|
|
65
|
-
if (rl) {
|
|
66
|
-
const windowMs = rl.windowMs ?? 60_000;
|
|
67
|
-
if (rl.perSenderDomain && rl.perSenderDomain > 0) {
|
|
68
|
-
this.senderLimiter = new RateLimiter(windowMs, rl.perSenderDomain);
|
|
69
|
-
}
|
|
70
|
-
if (rl.global && rl.global > 0) {
|
|
71
|
-
this.globalLimiter = new RateLimiter(windowMs, rl.global);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
this.transport.onReceive((mail) => this.handleInbound(mail));
|
|
75
|
-
}
|
|
76
|
-
/** Start the underlying transport and the retry/TTL timers. */
|
|
77
|
-
async start(intervalMs = 30_000) {
|
|
78
|
-
await this.transport.start();
|
|
79
|
-
this.queue.startTicking();
|
|
80
|
-
this.retryTimer = setInterval(() => {
|
|
81
|
-
void this.processRetries();
|
|
82
|
-
}, intervalMs);
|
|
83
|
-
}
|
|
84
|
-
async stop() {
|
|
85
|
-
if (this.retryTimer)
|
|
86
|
-
clearInterval(this.retryTimer);
|
|
87
|
-
this.retryTimer = undefined;
|
|
88
|
-
this.queue.stopTicking();
|
|
89
|
-
await this.transport.stop();
|
|
90
|
-
}
|
|
91
|
-
// -- MailEgress ----------------------------------------------------------
|
|
92
|
-
/** True if this recipient's domain is one we route mail for. */
|
|
93
|
-
ownsRecipient(agentId) {
|
|
94
|
-
if (agentId.indexOf("@") === -1)
|
|
95
|
-
return false;
|
|
96
|
-
const addr = parseAddress(agentId);
|
|
97
|
-
return addr.system ? domainMatches(addr.system, this.mailDomains) : false;
|
|
98
|
-
}
|
|
99
|
-
/** Render and deliver the mail-class recipients of a message. */
|
|
100
|
-
async send(message) {
|
|
101
|
-
const mailRecipients = message.recipients.filter((r) => this.ownsRecipient(r.agent_id));
|
|
102
|
-
if (mailRecipients.length === 0)
|
|
103
|
-
return;
|
|
104
|
-
await this.attemptDelivery({ ...message, recipients: mailRecipients });
|
|
105
|
-
}
|
|
106
|
-
// -- Ingress -------------------------------------------------------------
|
|
107
|
-
/**
|
|
108
|
-
* Handle one inbound message. Resolves on ACK; throws on NACK (transient
|
|
109
|
-
* failure the sender should retry). Policy rejections ACK-and-drop so the
|
|
110
|
-
* sender does not retry forever.
|
|
111
|
-
*/
|
|
112
|
-
async handleInbound(mail) {
|
|
113
|
-
const cap = this.config.maxMessageBytes ?? this.transport.capabilities.maxMessageBytes;
|
|
114
|
-
if (mail.sizeBytes > cap) {
|
|
115
|
-
this.reject(mail, "size-exceeded");
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
// Rate limiting (abuse control) — applies to all inbound including bounces.
|
|
119
|
-
// Over-limit NACKs (throws) so legitimate senders back off and retry.
|
|
120
|
-
this.enforceRateLimits(mail);
|
|
121
|
-
// Bounces/DSNs correlate to a prior send rather than routing as new mail.
|
|
122
|
-
if (mail.bounce) {
|
|
123
|
-
await this.handleInboundBounce(mail);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
if (!this.senderAllowed(mail)) {
|
|
127
|
-
this.reject(mail, "sender-not-allowed");
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (this.config.rejectDmarcFail && mail.authResults?.dmarc === "fail") {
|
|
131
|
-
this.reject(mail, "dmarc-fail");
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const maxAtt = this.config.maxAttachments;
|
|
135
|
-
if (maxAtt !== undefined && (mail.attachments?.length ?? 0) > maxAtt) {
|
|
136
|
-
this.reject(mail, "too-many-attachments");
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const externalId = this.externalIdFor(mail);
|
|
140
|
-
if (this.storage.hasSeenExternalId(externalId)) {
|
|
141
|
-
this.events.emit("mail.duplicate", { externalId });
|
|
142
|
-
return; // already ingested — ACK without re-injecting
|
|
143
|
-
}
|
|
144
|
-
let mapped;
|
|
145
|
-
try {
|
|
146
|
-
mapped = inboundMailToMessage(mail, {
|
|
147
|
-
addressBook: this.addressBook,
|
|
148
|
-
defaultScope: this.config.defaultScope,
|
|
149
|
-
lookupInboxIdByRfcMessageId: (id) => this.storage.getMessageIdByExternalId(id),
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
catch (err) {
|
|
153
|
-
if (err instanceof UnknownRecipientError) {
|
|
154
|
-
this.reject(mail, "no-local-recipient");
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
throw err; // unexpected — NACK
|
|
158
|
-
}
|
|
159
|
-
// Single ingestion path: routeMessage stores, marks delivery, fires events.
|
|
160
|
-
// When the reply resolves to a known parent, inherit the parent's thread_tag
|
|
161
|
-
// (keeps threads consistent even for clients that send In-Reply-To without a
|
|
162
|
-
// full References chain). Fall back to our derived tag if the parent is gone.
|
|
163
|
-
const parentThreadTag = mapped.in_reply_to
|
|
164
|
-
? this.storage.getMessage(mapped.in_reply_to)?.thread_tag
|
|
165
|
-
: undefined;
|
|
166
|
-
const stored = await this.router.routeMessage({
|
|
167
|
-
from: mapped.sender_id,
|
|
168
|
-
to: mapped.recipients.map((r) => ({ agent_id: r.agent_id, kind: r.kind })),
|
|
169
|
-
payload: mapped.content,
|
|
170
|
-
scope: mapped.scope,
|
|
171
|
-
subject: mapped.subject,
|
|
172
|
-
threadTag: parentThreadTag ?? mapped.thread_tag,
|
|
173
|
-
inReplyTo: mapped.in_reply_to,
|
|
174
|
-
importance: mapped.importance,
|
|
175
|
-
metadata: mapped.metadata,
|
|
176
|
-
});
|
|
177
|
-
this.storage.recordExternalId(externalId, stored.id);
|
|
178
|
-
this.events.emit("mail.received", { messageId: stored.id, externalId });
|
|
179
|
-
}
|
|
180
|
-
// -- Egress delivery -----------------------------------------------------
|
|
181
|
-
/** Attempt delivery; classify the result and queue/bounce accordingly. */
|
|
182
|
-
async attemptDelivery(message, queuedId) {
|
|
183
|
-
const outbound = messageToOutboundMail(message, {
|
|
184
|
-
addressBook: this.addressBook,
|
|
185
|
-
messageIdDomain: this.config.messageIdDomain,
|
|
186
|
-
lookupRfcMessageId: (id) => this.storage.getMessage(id)?.metadata.rfcMessageId,
|
|
187
|
-
lookupReferences: (id) => this.storage.getMessage(id)?.metadata.rfcReferences,
|
|
188
|
-
});
|
|
189
|
-
let disposition;
|
|
190
|
-
let detail;
|
|
191
|
-
let code;
|
|
192
|
-
let remoteMessageId;
|
|
193
|
-
try {
|
|
194
|
-
const res = await this.transport.send(outbound);
|
|
195
|
-
disposition = res.disposition;
|
|
196
|
-
detail = res.detail;
|
|
197
|
-
code = res.code;
|
|
198
|
-
remoteMessageId = res.remoteMessageId;
|
|
199
|
-
}
|
|
200
|
-
catch (err) {
|
|
201
|
-
// Transport threw (e.g. not ready) — treat as transient, keep retrying.
|
|
202
|
-
disposition = "transient";
|
|
203
|
-
detail = err instanceof Error ? err.message : String(err);
|
|
204
|
-
}
|
|
205
|
-
if (disposition === "delivered") {
|
|
206
|
-
// Record our Message-ID so an inbound DSN or reply can correlate back.
|
|
207
|
-
this.storage.recordExternalId(outbound.headers.messageId, message.id);
|
|
208
|
-
// Also record the provider's id — some backends (Postmark) reference their
|
|
209
|
-
// own message id in bounce webhooks rather than the RFC Message-ID.
|
|
210
|
-
if (remoteMessageId) {
|
|
211
|
-
this.storage.recordExternalId(remoteMessageId, message.id);
|
|
212
|
-
}
|
|
213
|
-
this.markDelivered(message);
|
|
214
|
-
if (queuedId)
|
|
215
|
-
this.queue.removeEntry(MAIL_QUEUE, queuedId);
|
|
216
|
-
this.events.emit("mail.sent", { messageId: message.id, remoteMessageId });
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
if (disposition === "transient") {
|
|
220
|
-
if (queuedId) {
|
|
221
|
-
// recordAttempt returns false once retryMaxAttempts is exhausted (the
|
|
222
|
-
// entry is then removed). Bounce instead of silently dropping it.
|
|
223
|
-
const kept = this.queue.recordAttempt(MAIL_QUEUE, queuedId);
|
|
224
|
-
if (!kept) {
|
|
225
|
-
await this.bounce({
|
|
226
|
-
message,
|
|
227
|
-
recipient: outbound.to.map((t) => t.address).join(", "),
|
|
228
|
-
status: code ? String(code) : undefined,
|
|
229
|
-
diagnostic: detail ?? "retries exhausted",
|
|
230
|
-
action: "failed",
|
|
231
|
-
});
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
this.queue.enqueue(MAIL_QUEUE, message);
|
|
237
|
-
}
|
|
238
|
-
this.events.emit("mail.queued", { messageId: message.id, detail });
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
// permanent
|
|
242
|
-
if (queuedId)
|
|
243
|
-
this.queue.removeEntry(MAIL_QUEUE, queuedId);
|
|
244
|
-
await this.bounce({
|
|
245
|
-
message,
|
|
246
|
-
recipient: outbound.to.map((t) => t.address).join(", "),
|
|
247
|
-
status: code ? String(code) : undefined,
|
|
248
|
-
diagnostic: detail,
|
|
249
|
-
action: "failed",
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
/** Re-attempt all retryable queued mail. Call from a timer or deterministically. */
|
|
253
|
-
async processRetries() {
|
|
254
|
-
// Guard against overlapping ticks: a slow send must not be re-selected and
|
|
255
|
-
// re-sent by the next interval while it is still in flight.
|
|
256
|
-
if (this.retrying)
|
|
257
|
-
return;
|
|
258
|
-
this.retrying = true;
|
|
259
|
-
// Opportunistically reclaim idle rate-limiter keys (bounded memory).
|
|
260
|
-
this.senderLimiter?.prune();
|
|
261
|
-
this.globalLimiter?.prune();
|
|
262
|
-
try {
|
|
263
|
-
for (const entry of this.queue.getRetryable(MAIL_QUEUE)) {
|
|
264
|
-
await this.attemptDelivery(entry.message, entry.id);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
finally {
|
|
268
|
-
this.retrying = false;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
markDelivered(message) {
|
|
272
|
-
const stored = this.storage.getMessage(message.id);
|
|
273
|
-
if (!stored)
|
|
274
|
-
return;
|
|
275
|
-
const now = new Date().toISOString();
|
|
276
|
-
for (const r of stored.recipients) {
|
|
277
|
-
if (this.ownsRecipient(r.agent_id))
|
|
278
|
-
r.delivered_at = now;
|
|
279
|
-
}
|
|
280
|
-
this.storage.putMessage(stored);
|
|
281
|
-
}
|
|
282
|
-
// -- Bounce (shared by outbound permanent + inbound DSN) -----------------
|
|
283
|
-
async handleInboundBounce(mail) {
|
|
284
|
-
const b = mail.bounce;
|
|
285
|
-
await this.bounce({
|
|
286
|
-
originalMessageId: b.originalMessageId,
|
|
287
|
-
recipient: b.recipient,
|
|
288
|
-
status: b.status,
|
|
289
|
-
diagnostic: b.diagnostic,
|
|
290
|
-
action: b.action,
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
async bounce(opts) {
|
|
294
|
-
let original = opts.message;
|
|
295
|
-
if (!original && opts.originalMessageId) {
|
|
296
|
-
const inboxId = this.storage.getMessageIdByExternalId(opts.originalMessageId);
|
|
297
|
-
if (inboxId)
|
|
298
|
-
original = this.storage.getMessage(inboxId);
|
|
299
|
-
}
|
|
300
|
-
// A delayed DSN means the peer MTA is still retrying — surface, don't bounce.
|
|
301
|
-
if (opts.action === "delayed") {
|
|
302
|
-
this.events.emit("mail.queued", {
|
|
303
|
-
messageId: original?.id,
|
|
304
|
-
recipient: opts.recipient,
|
|
305
|
-
delayed: true,
|
|
306
|
-
});
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
// A positive DSN ("delivered") is informational only.
|
|
310
|
-
if (opts.action === "delivered")
|
|
311
|
-
return;
|
|
312
|
-
// Dedup: a replayed/spoofed DSN echoing a known message id must not
|
|
313
|
-
// repeatedly emit events or synthesize inbox notices (flood protection).
|
|
314
|
-
const bounceKey = `bounce:${original?.id ?? opts.originalMessageId ?? "?"}:${opts.recipient}`;
|
|
315
|
-
if (this.storage.hasSeenExternalId(bounceKey))
|
|
316
|
-
return;
|
|
317
|
-
this.storage.recordExternalId(bounceKey, original?.id ?? bounceKey);
|
|
318
|
-
if (this.config.bounce?.emitEvent !== false) {
|
|
319
|
-
this.events.emit("mail.bounced", {
|
|
320
|
-
messageId: original?.id,
|
|
321
|
-
recipient: opts.recipient,
|
|
322
|
-
status: opts.status,
|
|
323
|
-
diagnostic: opts.diagnostic,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
if (this.config.bounce?.synthesizeInboxMessage !== false && original) {
|
|
327
|
-
await this.synthesizeBounce(original, opts);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
/** Inject a bounce notification into the original sender's inbox. */
|
|
331
|
-
async synthesizeBounce(original, opts) {
|
|
332
|
-
const parts = [`Delivery to ${opts.recipient} failed`];
|
|
333
|
-
if (opts.status)
|
|
334
|
-
parts.push(`(${opts.status})`);
|
|
335
|
-
if (opts.diagnostic)
|
|
336
|
-
parts.push(`- ${opts.diagnostic}`);
|
|
337
|
-
await this.router.routeMessage({
|
|
338
|
-
from: "mailer-daemon",
|
|
339
|
-
to: [{ agent_id: original.sender_id, kind: "to" }],
|
|
340
|
-
subject: `Delivery failed: ${original.subject ?? "(no subject)"}`,
|
|
341
|
-
payload: { type: "text", text: parts.join(" ") },
|
|
342
|
-
inReplyTo: original.id,
|
|
343
|
-
importance: "high",
|
|
344
|
-
scope: original.scope,
|
|
345
|
-
metadata: {
|
|
346
|
-
bounce: {
|
|
347
|
-
recipient: opts.recipient,
|
|
348
|
-
status: opts.status,
|
|
349
|
-
diagnostic: opts.diagnostic,
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
// -- Helpers -------------------------------------------------------------
|
|
355
|
-
reject(mail, reason) {
|
|
356
|
-
this.events.emit("mail.rejected", {
|
|
357
|
-
reason,
|
|
358
|
-
from: mail.from.address,
|
|
359
|
-
to: mail.to.map((t) => t.address),
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
/** Throw RateLimitedError (→ NACK) when an inbound limiter is exceeded. */
|
|
363
|
-
enforceRateLimits(mail) {
|
|
364
|
-
if (this.globalLimiter && !this.globalLimiter.tryAcquire("*")) {
|
|
365
|
-
this.events.emit("mail.rate_limited", { scope: "global" });
|
|
366
|
-
throw new RateLimitedError("global");
|
|
367
|
-
}
|
|
368
|
-
if (this.senderLimiter) {
|
|
369
|
-
const from = mail.from.address || mail.envelopeFrom || "unknown";
|
|
370
|
-
const at = from.lastIndexOf("@");
|
|
371
|
-
const domain = at === -1 ? from : from.slice(at + 1).toLowerCase();
|
|
372
|
-
if (!this.senderLimiter.tryAcquire(domain)) {
|
|
373
|
-
this.events.emit("mail.rate_limited", { scope: "sender", domain });
|
|
374
|
-
throw new RateLimitedError(`sender:${domain}`);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
senderAllowed(mail) {
|
|
379
|
-
const allow = this.config.allowedSenderDomains;
|
|
380
|
-
if (!allow || allow.length === 0)
|
|
381
|
-
return true;
|
|
382
|
-
const at = mail.from.address.lastIndexOf("@");
|
|
383
|
-
if (at === -1)
|
|
384
|
-
return false;
|
|
385
|
-
return domainMatches(mail.from.address.slice(at + 1), allow);
|
|
386
|
-
}
|
|
387
|
-
/** Dedup key: RFC Message-ID when present, else a synthetic content hash. */
|
|
388
|
-
externalIdFor(mail) {
|
|
389
|
-
if (mail.headers.messageId)
|
|
390
|
-
return mail.headers.messageId;
|
|
391
|
-
const h = createHash("sha256");
|
|
392
|
-
h.update(mail.from.address);
|
|
393
|
-
h.update("\0");
|
|
394
|
-
h.update(mail.subject ?? "");
|
|
395
|
-
h.update("\0");
|
|
396
|
-
h.update(mail.receivedAt);
|
|
397
|
-
h.update("\0");
|
|
398
|
-
h.update((mail.text ?? mail.html ?? "").slice(0, 4096));
|
|
399
|
-
return "syn:" + h.digest("hex");
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
//# sourceMappingURL=mail-gateway.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mail-gateway.js","sourceRoot":"","sources":["../../src/mail/mail-gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Postmark provider MailTransport — the managed swap-in backend.
|
|
3
|
-
*
|
|
4
|
-
* Proves the MailTransport contract holds for an API/webhook world (vs the
|
|
5
|
-
* raw-SMTP world of SmtpTransport). The same shared contract suite validates it
|
|
6
|
-
* (test/mail/mail-transport-contract.test.ts) via a harness.
|
|
7
|
-
*
|
|
8
|
-
* Outbound: Postmark REST API. The SDK is an optional peer dep, loaded via
|
|
9
|
-
* dynamic import; a client can also be injected (tests / custom).
|
|
10
|
-
* Inbound: Postmark webhooks POST parsed JSON. `ingestInboundWebhook` /
|
|
11
|
-
* `ingestBounceWebhook` map the payload and await the handler BEFORE
|
|
12
|
-
* the caller returns 200 (commit-before-ACK); a throw → 5xx so
|
|
13
|
-
* Postmark retries. An optional built-in HTTP listener is provided.
|
|
14
|
-
*
|
|
15
|
-
* The pure mapping helpers are exported for unit testing without the SDK,
|
|
16
|
-
* HTTP, or network.
|
|
17
|
-
*/
|
|
18
|
-
import type { MailTransport, MailCapabilities, MailTransportState, MailHealth, OutboundMail, MailSendResult, InboundMail, InboundHandler, InboundAuthResults, MailAttachment, AttachmentStore } from "./types.js";
|
|
19
|
-
export interface PostmarkSendResponse {
|
|
20
|
-
ErrorCode: number;
|
|
21
|
-
MessageID?: string;
|
|
22
|
-
Message?: string;
|
|
23
|
-
SubmittedAt?: string;
|
|
24
|
-
}
|
|
25
|
-
export interface PostmarkClient {
|
|
26
|
-
sendEmail(message: Record<string, unknown>): Promise<PostmarkSendResponse>;
|
|
27
|
-
}
|
|
28
|
-
export interface PostmarkTransportOptions {
|
|
29
|
-
/** Postmark server API token. Required unless a client is injected. */
|
|
30
|
-
serverToken?: string;
|
|
31
|
-
maxMessageBytes?: number;
|
|
32
|
-
attachmentStore?: AttachmentStore;
|
|
33
|
-
/** Optional built-in webhook HTTP listener. */
|
|
34
|
-
webhook?: {
|
|
35
|
-
port: number;
|
|
36
|
-
host?: string;
|
|
37
|
-
inboundPath?: string;
|
|
38
|
-
bouncePath?: string;
|
|
39
|
-
/**
|
|
40
|
-
* Optional HTTP Basic Auth. When set, webhook requests must present
|
|
41
|
-
* matching credentials (Postmark supports basic-auth in the webhook URL),
|
|
42
|
-
* else they are rejected 401. Strongly recommended if the port is exposed.
|
|
43
|
-
*/
|
|
44
|
-
basicAuth?: {
|
|
45
|
-
user: string;
|
|
46
|
-
pass: string;
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
/** Inject a client (tests / custom). Defaults to the postmark SDK. */
|
|
50
|
-
client?: PostmarkClient;
|
|
51
|
-
}
|
|
52
|
-
export declare class PostmarkTransport implements MailTransport {
|
|
53
|
-
private opts;
|
|
54
|
-
readonly capabilities: MailCapabilities;
|
|
55
|
-
private _state;
|
|
56
|
-
private handler?;
|
|
57
|
-
private client?;
|
|
58
|
-
private server?;
|
|
59
|
-
private delivered;
|
|
60
|
-
private static readonly MAX_DELIVERED;
|
|
61
|
-
constructor(opts: PostmarkTransportOptions);
|
|
62
|
-
get state(): MailTransportState;
|
|
63
|
-
onReceive(handler: InboundHandler): void;
|
|
64
|
-
health(): Promise<MailHealth>;
|
|
65
|
-
start(): Promise<void>;
|
|
66
|
-
stop(): Promise<void>;
|
|
67
|
-
send(envelope: OutboundMail): Promise<MailSendResult>;
|
|
68
|
-
/** Record a delivered idempotency key, evicting the oldest when over cap. */
|
|
69
|
-
private rememberDelivered;
|
|
70
|
-
private getClient;
|
|
71
|
-
private resolveAttachmentContents;
|
|
72
|
-
/** Map + ingest a Postmark inbound webhook payload. Awaits the handler. */
|
|
73
|
-
ingestInboundWebhook(payload: PostmarkInbound): Promise<void>;
|
|
74
|
-
/** Map + ingest a Postmark bounce webhook payload. Awaits the handler. */
|
|
75
|
-
ingestBounceWebhook(payload: PostmarkBounce): Promise<void>;
|
|
76
|
-
/**
|
|
77
|
-
* Deliver an already-mapped inbound message to the handler (commit-before-ACK).
|
|
78
|
-
* Public so embedders using their own webhook parser can inject directly.
|
|
79
|
-
*/
|
|
80
|
-
receiveInbound(mail: InboundMail): Promise<void>;
|
|
81
|
-
private storeAttachments;
|
|
82
|
-
private startHttp;
|
|
83
|
-
}
|
|
84
|
-
export interface PostmarkInbound {
|
|
85
|
-
FromFull?: {
|
|
86
|
-
Email: string;
|
|
87
|
-
Name?: string;
|
|
88
|
-
};
|
|
89
|
-
ToFull?: Array<{
|
|
90
|
-
Email: string;
|
|
91
|
-
Name?: string;
|
|
92
|
-
}>;
|
|
93
|
-
CcFull?: Array<{
|
|
94
|
-
Email: string;
|
|
95
|
-
Name?: string;
|
|
96
|
-
}>;
|
|
97
|
-
OriginalRecipient?: string;
|
|
98
|
-
Subject?: string;
|
|
99
|
-
TextBody?: string;
|
|
100
|
-
HtmlBody?: string;
|
|
101
|
-
Date?: string;
|
|
102
|
-
Headers?: Array<{
|
|
103
|
-
Name: string;
|
|
104
|
-
Value: string;
|
|
105
|
-
}>;
|
|
106
|
-
Attachments?: Array<{
|
|
107
|
-
Name: string;
|
|
108
|
-
Content: string;
|
|
109
|
-
ContentType: string;
|
|
110
|
-
ContentLength?: number;
|
|
111
|
-
ContentID?: string;
|
|
112
|
-
}>;
|
|
113
|
-
}
|
|
114
|
-
export interface PostmarkBounce {
|
|
115
|
-
RecordType?: string;
|
|
116
|
-
Type?: string;
|
|
117
|
-
TypeCode?: number;
|
|
118
|
-
Email?: string;
|
|
119
|
-
MessageID?: string;
|
|
120
|
-
Description?: string;
|
|
121
|
-
Details?: string;
|
|
122
|
-
BouncedAt?: string;
|
|
123
|
-
}
|
|
124
|
-
/** Classify a resolved Postmark send response. */
|
|
125
|
-
export declare function postmarkResponseToResult(res: PostmarkSendResponse): MailSendResult;
|
|
126
|
-
/** Classify a thrown Postmark error (rejected promise). */
|
|
127
|
-
export declare function postmarkErrorToResult(err: unknown): MailSendResult;
|
|
128
|
-
/** Map an OutboundMail to a Postmark sendEmail message object. */
|
|
129
|
-
export declare function outboundToPostmark(env: OutboundMail, attachmentContents?: Map<string, string>): Record<string, unknown>;
|
|
130
|
-
/** Map a Postmark inbound webhook payload to an InboundMail. */
|
|
131
|
-
export declare function postmarkInboundToMail(payload: PostmarkInbound, ctx?: {
|
|
132
|
-
attachments?: MailAttachment[];
|
|
133
|
-
}): InboundMail;
|
|
134
|
-
/** Map a Postmark bounce webhook payload to an InboundMail carrying a bounce. */
|
|
135
|
-
export declare function postmarkBounceToInbound(payload: PostmarkBounce): InboundMail;
|
|
136
|
-
/** Best-effort parse of an Authentication-Results header into verdicts. */
|
|
137
|
-
export declare function parseAuthResults(header: string | undefined): InboundAuthResults | undefined;
|
|
138
|
-
//# sourceMappingURL=provider-transport.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provider-transport.d.ts","sourceRoot":"","sources":["../../src/mail/provider-transport.ts"],"names":[],"mappings":"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"}
|