@voltro/plugin-mail 0.84.0 → 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +549 -0
- package/THIRD-PARTY-NOTICES.md +104 -704
- package/dist/index.d.ts +15 -18
- package/dist/index.js +260 -260
- package/package.json +6 -8
package/dist/index.js
CHANGED
|
@@ -1,134 +1,134 @@
|
|
|
1
|
-
import { Context as e, Duration as t, Effect as n, Fiber as r, Layer as i,
|
|
2
|
-
import { definePlugin as
|
|
3
|
-
import { pluginEnv as
|
|
4
|
-
import { createLogger as
|
|
5
|
-
import { and as
|
|
6
|
-
import { FetchHttpClient as
|
|
1
|
+
import { Context as e, Duration as t, Effect as n, Fiber as r, Layer as i, Result as a, Schedule as o, Schema as s, SchemaIssue as c } from "effect";
|
|
2
|
+
import { definePlugin as l, pluginInstanceName as u } from "@voltro/protocol";
|
|
3
|
+
import { pluginEnv as d } from "@voltro/env";
|
|
4
|
+
import { createLogger as f } from "@voltro/logger";
|
|
5
|
+
import { and as p, dropped as m, eq as h, id as g, inSet as _, queryFor as v, registerRetention as y, retentionTtlMsFromEnv as b, table as x, text as S, timestamp as C } from "@voltro/database";
|
|
6
|
+
import { FetchHttpClient as w, HttpClient as T, HttpClientRequest as E } from "effect/http";
|
|
7
7
|
//#region src/types.ts
|
|
8
|
-
var
|
|
8
|
+
var D = class extends s.TaggedError()("MailError", {
|
|
9
9
|
provider: s.String,
|
|
10
10
|
message: s.String,
|
|
11
11
|
transient: s.Boolean,
|
|
12
12
|
status: s.optional(s.Number)
|
|
13
|
-
}) {},
|
|
13
|
+
}) {}, O = class extends s.TaggedError()("MailWebhookError", {
|
|
14
14
|
provider: s.String,
|
|
15
15
|
message: s.String
|
|
16
|
-
}) {},
|
|
16
|
+
}) {}, k = (e) => ({
|
|
17
17
|
name: e.name,
|
|
18
18
|
props: e.props,
|
|
19
19
|
subject: e.subject,
|
|
20
20
|
render: e.render,
|
|
21
21
|
...e.locale === void 0 ? {} : { locale: e.locale },
|
|
22
22
|
...e.preview === void 0 ? {} : { preview: e.preview }
|
|
23
|
-
}),
|
|
23
|
+
}), A = class extends e.Service()("@voltro/plugin-mail/MailService") {}, j = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, ee = (e) => {
|
|
24
24
|
try {
|
|
25
|
-
let t =
|
|
26
|
-
return t.length === 0 ? String(e) : t.map((e) => `${e.path.length > 0 ? e.path.join(".") : "(root)"}: ${e.message}`).join("; ");
|
|
25
|
+
let t = c.makeFormatterStandardSchemaV1()(e.issue).issues;
|
|
26
|
+
return t.length === 0 ? String(e) : t.map((e) => `${e.path !== void 0 && e.path.length > 0 ? e.path.map(String).join(".") : "(root)"}: ${e.message}`).join("; ");
|
|
27
27
|
} catch {
|
|
28
28
|
return String(e);
|
|
29
29
|
}
|
|
30
|
-
},
|
|
31
|
-
if (!
|
|
30
|
+
}, M = null, te = async () => {
|
|
31
|
+
if (!M) {
|
|
32
32
|
let e = await import("@react-email/render");
|
|
33
|
-
if (
|
|
33
|
+
if (M = e.render ?? e.default?.render ?? null, !M) throw Error("@react-email/render: `render` export not found (install @react-email/render + react + react-dom)");
|
|
34
34
|
}
|
|
35
|
-
return
|
|
36
|
-
},
|
|
37
|
-
let r = e, i = yield* s.
|
|
35
|
+
return M;
|
|
36
|
+
}, ne = (e, t) => n.gen(function* () {
|
|
37
|
+
let r = e, i = yield* s.decodeUnknownEffect(r.props)(t).pipe(n.mapError((t) => new D({
|
|
38
38
|
provider: "template",
|
|
39
|
-
message: `invalid props for '${e.name}': ${
|
|
39
|
+
message: `invalid props for '${e.name}': ${ee(t)}`.slice(0, 500),
|
|
40
40
|
transient: !1
|
|
41
41
|
}))), a = r.subject(i), o = r.render(i);
|
|
42
42
|
return {
|
|
43
43
|
subject: a,
|
|
44
44
|
html: yield* n.tryPromise({
|
|
45
|
-
try: async () => (await
|
|
46
|
-
catch: (t) => new
|
|
45
|
+
try: async () => (await te())(o, { plainText: !1 }),
|
|
46
|
+
catch: (t) => new D({
|
|
47
47
|
provider: "template",
|
|
48
48
|
message: `render failed for '${e.name}': ${String(t)}`.slice(0, 500),
|
|
49
49
|
transient: !1
|
|
50
50
|
})
|
|
51
51
|
}),
|
|
52
52
|
text: yield* n.tryPromise({
|
|
53
|
-
try: async () => (await
|
|
54
|
-
catch: (t) => new
|
|
53
|
+
try: async () => (await te())(o, { plainText: !0 }),
|
|
54
|
+
catch: (t) => new D({
|
|
55
55
|
provider: "template",
|
|
56
56
|
message: `render(text) failed for '${e.name}': ${String(t)}`.slice(0, 500),
|
|
57
57
|
transient: !1
|
|
58
58
|
})
|
|
59
59
|
})
|
|
60
60
|
};
|
|
61
|
-
}),
|
|
62
|
-
for (let t of e)
|
|
63
|
-
},
|
|
61
|
+
}), N = /* @__PURE__ */ new Map(), re = (e) => e.locale ? `${e.name}:${e.locale}` : e.name, ie = (e) => {
|
|
62
|
+
for (let t of e) N.set(re(t), t);
|
|
63
|
+
}, P = (e, t) => (t ? N.get(`${e}:${t}`) : void 0) ?? N.get(e), ae = () => N.size, oe = () => [...N.values()].map((e) => e.locale ? {
|
|
64
64
|
name: e.name,
|
|
65
65
|
locale: e.locale
|
|
66
|
-
} : { name: e.name }),
|
|
66
|
+
} : { name: e.name }), se = () => N.clear(), ce = (e) => {
|
|
67
67
|
if (typeof e != "object" || !e) return !1;
|
|
68
68
|
let t = e;
|
|
69
69
|
return typeof t.name == "string" && typeof t.subject == "function" && typeof t.render == "function" && t.props !== void 0;
|
|
70
|
-
},
|
|
71
|
-
id:
|
|
72
|
-
tenant:
|
|
73
|
-
email:
|
|
74
|
-
reason:
|
|
75
|
-
createdAt:
|
|
76
|
-
created_at:
|
|
77
|
-
}).unique("mailSuppressionAddress", ["tenant", "email"]).nonReactive(),
|
|
78
|
-
id:
|
|
79
|
-
tenant:
|
|
80
|
-
key:
|
|
81
|
-
resultId:
|
|
82
|
-
resultProvider:
|
|
83
|
-
createdAt:
|
|
84
|
-
created_at:
|
|
85
|
-
}).unique("mailIdempotencyKey", ["tenant", "key"]).nonReactive(),
|
|
70
|
+
}, F = "_voltro_mail_suppression", I = "_voltro_mail_idempotency", le = x(F, {
|
|
71
|
+
id: g({ scheme: "numeric" }),
|
|
72
|
+
tenant: S().maxLength(191),
|
|
73
|
+
email: S().maxLength(320),
|
|
74
|
+
reason: S().nullable(),
|
|
75
|
+
createdAt: C().default("now"),
|
|
76
|
+
created_at: m()
|
|
77
|
+
}).unique("mailSuppressionAddress", ["tenant", "email"]).nonReactive(), ue = x(I, {
|
|
78
|
+
id: g({ scheme: "numeric" }),
|
|
79
|
+
tenant: S().maxLength(191),
|
|
80
|
+
key: S().maxLength(255),
|
|
81
|
+
resultId: S().nullable().renamedFrom("result_id"),
|
|
82
|
+
resultProvider: S().nullable().renamedFrom("result_provider"),
|
|
83
|
+
createdAt: C().default("now"),
|
|
84
|
+
created_at: m()
|
|
85
|
+
}).unique("mailIdempotencyKey", ["tenant", "key"]).nonReactive(), L = (e) => n.tryPromise({
|
|
86
86
|
try: e,
|
|
87
87
|
catch: (e) => e
|
|
88
|
-
}),
|
|
88
|
+
}), R = (e) => {
|
|
89
89
|
let t = [];
|
|
90
90
|
for (let n = e, r = 0; n != null && r < 4; n = n.cause, r++) t.push(n instanceof Error ? n.message : String(n));
|
|
91
91
|
return t.join(" ← ");
|
|
92
|
-
},
|
|
93
|
-
let e = /* @__PURE__ */ new Set(), t = (e, t) => `${
|
|
92
|
+
}, de = f({ scope: "@voltro/plugin-mail" }), z = (e) => e.trim().toLowerCase(), fe = "*", pe = (e) => e ?? fe, B = () => {
|
|
93
|
+
let e = /* @__PURE__ */ new Set(), t = (e, t) => `${pe(e)}\u0000${z(t)}`;
|
|
94
94
|
return {
|
|
95
95
|
isSuppressed: (r, i) => n.sync(() => e.has(t(r, i)) || e.has(t(null, i))),
|
|
96
96
|
suppress: (r, i) => n.sync(() => void e.add(t(r, i))),
|
|
97
97
|
unsuppress: (r, i) => n.sync(() => void e.delete(t(r, i)))
|
|
98
98
|
};
|
|
99
|
-
},
|
|
99
|
+
}, me = () => {
|
|
100
100
|
let e = null, t = (e, t) => ({
|
|
101
|
-
tenant:
|
|
102
|
-
email:
|
|
101
|
+
tenant: pe(e),
|
|
102
|
+
email: z(t)
|
|
103
103
|
});
|
|
104
104
|
return {
|
|
105
105
|
isSuppressed: (t, r) => {
|
|
106
106
|
let i = e;
|
|
107
|
-
return i ?
|
|
107
|
+
return i ? L(() => i.query(v(le).where(p(h("email", z(r)), _("tenant", [pe(t), fe]))).limit(1).descriptor)).pipe(n.map((e) => e.length > 0), n.catch(() => n.succeed(!1))) : n.succeed(!1);
|
|
108
108
|
},
|
|
109
109
|
suppress: (r, i, a) => {
|
|
110
110
|
let o = e;
|
|
111
|
-
return o ?
|
|
111
|
+
return o ? L(() => o.upsert(F, {
|
|
112
112
|
...t(r, i),
|
|
113
113
|
reason: a,
|
|
114
114
|
createdAt: /* @__PURE__ */ new Date()
|
|
115
|
-
}, { conflictColumns: ["tenant", "email"] })).pipe(n.asVoid, n.
|
|
116
|
-
email:
|
|
117
|
-
message:
|
|
115
|
+
}, { conflictColumns: ["tenant", "email"] })).pipe(n.asVoid, n.catch((e) => n.sync(() => de.warn("suppress write failed", {
|
|
116
|
+
email: z(i),
|
|
117
|
+
message: R(e)
|
|
118
118
|
})))) : n.void;
|
|
119
119
|
},
|
|
120
120
|
unsuppress: (r, i) => {
|
|
121
121
|
let a = e;
|
|
122
122
|
if (!a) return n.void;
|
|
123
123
|
let { tenant: o, email: s } = t(r, i);
|
|
124
|
-
return
|
|
124
|
+
return L(() => a.deleteMany(F, { where: p(h("tenant", o), h("email", s)) })).pipe(n.asVoid, n.catch(() => n.void));
|
|
125
125
|
},
|
|
126
126
|
bind: async (t) => {
|
|
127
127
|
e = t;
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
|
-
},
|
|
131
|
-
let e = /* @__PURE__ */ new Map(), t = (e, t) => `${
|
|
130
|
+
}, he = f({ scope: "@voltro/plugin-mail" }), V = (e) => e ?? "*", H = () => {
|
|
131
|
+
let e = /* @__PURE__ */ new Map(), t = (e, t) => `${V(e)} ${t}`;
|
|
132
132
|
return {
|
|
133
133
|
reserve: (r, i) => n.sync(() => {
|
|
134
134
|
let n = t(r, i);
|
|
@@ -143,13 +143,13 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
143
143
|
}),
|
|
144
144
|
record: (r, i, a) => n.sync(() => void e.set(t(r, i), a))
|
|
145
145
|
};
|
|
146
|
-
},
|
|
146
|
+
}, ge = () => {
|
|
147
147
|
let e = null;
|
|
148
148
|
return {
|
|
149
149
|
reserve: (t, r) => {
|
|
150
150
|
let i = e;
|
|
151
|
-
return i ?
|
|
152
|
-
tenant:
|
|
151
|
+
return i ? L(() => i.insertIgnoreWithOutcome(I, {
|
|
152
|
+
tenant: V(t),
|
|
153
153
|
key: r,
|
|
154
154
|
createdAt: /* @__PURE__ */ new Date()
|
|
155
155
|
}, { conflictColumns: ["tenant", "key"] })).pipe(n.map(({ row: e, outcome: t }) => {
|
|
@@ -162,26 +162,26 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
162
162
|
provider: r
|
|
163
163
|
}
|
|
164
164
|
} : { won: !1 };
|
|
165
|
-
}), n.
|
|
165
|
+
}), n.catch((e) => n.sync(() => (he.warn("idempotency reserve failed — skipping send to avoid a double", {
|
|
166
166
|
key: r,
|
|
167
|
-
message:
|
|
167
|
+
message: R(e)
|
|
168
168
|
}), { won: !1 })))) : n.succeed({ won: !0 });
|
|
169
169
|
},
|
|
170
170
|
record: (t, r, i) => {
|
|
171
171
|
let a = e;
|
|
172
|
-
return a ?
|
|
172
|
+
return a ? L(() => a.updateMany(I, {
|
|
173
173
|
resultId: i.id,
|
|
174
174
|
resultProvider: i.provider
|
|
175
|
-
}, { where:
|
|
175
|
+
}, { where: p(h("tenant", V(t)), h("key", r)) })).pipe(n.asVoid, n.catch((e) => n.sync(() => he.warn("idempotency record failed", {
|
|
176
176
|
key: r,
|
|
177
|
-
message:
|
|
177
|
+
message: R(e)
|
|
178
178
|
})))) : n.void;
|
|
179
179
|
},
|
|
180
180
|
bind: async (t) => {
|
|
181
181
|
e = t;
|
|
182
182
|
}
|
|
183
183
|
};
|
|
184
|
-
},
|
|
184
|
+
}, _e = f({ scope: "@voltro/plugin-mail" }), U = () => {
|
|
185
185
|
let e = /* @__PURE__ */ new Map();
|
|
186
186
|
return {
|
|
187
187
|
hold: (t) => n.sync(() => void e.set(t.id, t)),
|
|
@@ -192,34 +192,34 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
192
192
|
}),
|
|
193
193
|
size: () => n.sync(() => e.size)
|
|
194
194
|
};
|
|
195
|
-
},
|
|
195
|
+
}, ve = 0, ye = (e) => e.idempotencyKey ?? `held-${ve += 1}`, be = (e) => ({
|
|
196
196
|
shouldHold: (t) => !e.providerSchedules && t !== void 0 && t.getTime() > Date.now(),
|
|
197
197
|
hold: (t) => {
|
|
198
198
|
let { scheduledAt: n, ...r } = t;
|
|
199
199
|
return e.store.hold({
|
|
200
|
-
id:
|
|
200
|
+
id: ye(t),
|
|
201
201
|
dueAt: t.scheduledAt?.getTime() ?? Date.now(),
|
|
202
202
|
message: r
|
|
203
203
|
});
|
|
204
204
|
},
|
|
205
205
|
tick: (t = Date.now()) => n.gen(function* () {
|
|
206
206
|
let r = yield* e.store.claimDue(t);
|
|
207
|
-
for (let t of r) yield* e.flush(t.message).pipe(n.
|
|
207
|
+
for (let t of r) yield* e.flush(t.message).pipe(n.catch((e) => n.sync(() => _e.warn("scheduled flush failed", {
|
|
208
208
|
id: t.id,
|
|
209
209
|
message: String(e)
|
|
210
210
|
}))));
|
|
211
211
|
return r.length;
|
|
212
212
|
}),
|
|
213
213
|
pending: () => e.store.size()
|
|
214
|
-
}),
|
|
214
|
+
}), xe = 0, Se = (e) => `${e}-${xe += 1}`, Ce = (e) => e === void 0 || e === 408 || e === 429 || e >= 500, W = (e, t) => {
|
|
215
215
|
let n = t.status;
|
|
216
|
-
return new
|
|
216
|
+
return new D({
|
|
217
217
|
provider: e,
|
|
218
218
|
message: (t.message ?? "send failed").slice(0, 500),
|
|
219
|
-
transient: e === "smtp" ? n === void 0 || n >= 400 && n < 500 :
|
|
219
|
+
transient: e === "smtp" ? n === void 0 || n >= 400 && n < 500 : Ce(n),
|
|
220
220
|
...n === void 0 ? {} : { status: n }
|
|
221
221
|
});
|
|
222
|
-
},
|
|
222
|
+
}, G = (e, t, r, i, a) => n.tryPromise({
|
|
223
223
|
try: async () => {
|
|
224
224
|
let e = await fetch(t, {
|
|
225
225
|
method: "POST",
|
|
@@ -240,19 +240,19 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
240
240
|
},
|
|
241
241
|
catch: (t) => {
|
|
242
242
|
let n = t;
|
|
243
|
-
return
|
|
243
|
+
return W(e, {
|
|
244
244
|
...typeof n.status == "number" ? { status: n.status } : {},
|
|
245
245
|
message: n.message ?? t?.message ?? String(t)
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
|
-
}),
|
|
248
|
+
}), K = 500, we = (e, t) => {
|
|
249
249
|
let n = e.stream === "broadcast" ? t?.broadcast ?? "broadcast" : t?.transactional;
|
|
250
250
|
return {
|
|
251
251
|
...n === void 0 ? {} : { route: n },
|
|
252
252
|
from: e.from,
|
|
253
|
-
to:
|
|
254
|
-
...e.cc ? { cc:
|
|
255
|
-
...e.bcc ? { bcc:
|
|
253
|
+
to: j(e.to),
|
|
254
|
+
...e.cc ? { cc: j(e.cc) } : {},
|
|
255
|
+
...e.bcc ? { bcc: j(e.bcc) } : {},
|
|
256
256
|
...e.replyTo ? { reply_to: [e.replyTo] } : {},
|
|
257
257
|
subject: e.subject,
|
|
258
258
|
...e.html === void 0 ? {} : { html: e.html },
|
|
@@ -270,10 +270,10 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
270
270
|
...e.contentType ? { content_type: e.contentType } : {}
|
|
271
271
|
})) } : {}
|
|
272
272
|
};
|
|
273
|
-
},
|
|
273
|
+
}, Te = (e, t, r, i = Math.floor(Date.now() / 1e3), a = 300) => n.tryPromise({
|
|
274
274
|
try: async () => {
|
|
275
275
|
let n = (e) => {
|
|
276
|
-
throw new
|
|
276
|
+
throw new O({
|
|
277
277
|
provider: "lettermint",
|
|
278
278
|
message: e
|
|
279
279
|
});
|
|
@@ -293,11 +293,11 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
293
293
|
return n("body is not JSON");
|
|
294
294
|
}
|
|
295
295
|
},
|
|
296
|
-
catch: (e) => e instanceof
|
|
296
|
+
catch: (e) => e instanceof O ? e : new O({
|
|
297
297
|
provider: "lettermint",
|
|
298
298
|
message: e?.message ?? String(e)
|
|
299
299
|
})
|
|
300
|
-
}),
|
|
300
|
+
}), Ee = (e) => {
|
|
301
301
|
let t = (e.baseUrl ?? "https://api.lettermint.co/v1").replace(/\/+$/, ""), r = {
|
|
302
302
|
"x-lettermint-token": e.projectToken,
|
|
303
303
|
accept: "application/json"
|
|
@@ -306,31 +306,31 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
306
306
|
name: "lettermint",
|
|
307
307
|
supportsScheduling: !0,
|
|
308
308
|
managesUnsubscribe: !0,
|
|
309
|
-
send: (n) =>
|
|
309
|
+
send: (n) => G("lettermint", `${t}/send`, {
|
|
310
310
|
...r,
|
|
311
311
|
...n.idempotencyKey === void 0 ? {} : { "idempotency-key": n.idempotencyKey }
|
|
312
|
-
},
|
|
312
|
+
}, we(n, e.routes), async (e) => ({
|
|
313
313
|
id: (await e.json()).message_id ?? "lettermint",
|
|
314
314
|
provider: "lettermint"
|
|
315
315
|
})),
|
|
316
|
-
sendBatch: (i) => n.forEach(Array.from({ length: Math.ceil(i.length /
|
|
316
|
+
sendBatch: (i) => n.forEach(Array.from({ length: Math.ceil(i.length / K) }, (e, t) => i.slice(t * K, (t + 1) * K)), (n) => G("lettermint", `${t}/send/batch`, r, n.map((t) => we(t, e.routes)), async (e) => {
|
|
317
317
|
let t = await e.json();
|
|
318
318
|
return n.map((e, n) => ({
|
|
319
319
|
id: t[n]?.message_id ?? "lettermint",
|
|
320
320
|
provider: "lettermint"
|
|
321
321
|
}));
|
|
322
322
|
})).pipe(n.map((e) => e.flat())),
|
|
323
|
-
webhook: { verify:
|
|
323
|
+
webhook: { verify: Te }
|
|
324
324
|
};
|
|
325
|
-
},
|
|
325
|
+
}, De = (e) => ({
|
|
326
326
|
from: e.from,
|
|
327
|
-
to:
|
|
327
|
+
to: j(e.to),
|
|
328
328
|
subject: e.subject,
|
|
329
329
|
html: e.html,
|
|
330
330
|
text: e.text,
|
|
331
331
|
reply_to: e.replyTo,
|
|
332
|
-
cc: e.cc ?
|
|
333
|
-
bcc: e.bcc ?
|
|
332
|
+
cc: e.cc ? j(e.cc) : void 0,
|
|
333
|
+
bcc: e.bcc ? j(e.bcc) : void 0,
|
|
334
334
|
headers: e.headers,
|
|
335
335
|
tags: e.tags?.map((e) => ({
|
|
336
336
|
name: e,
|
|
@@ -342,34 +342,34 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
342
342
|
content: e.content,
|
|
343
343
|
...e.contentType ? { content_type: e.contentType } : {}
|
|
344
344
|
}))
|
|
345
|
-
}),
|
|
345
|
+
}), Oe = (e) => ({
|
|
346
346
|
name: "resend",
|
|
347
347
|
supportsScheduling: !0,
|
|
348
|
-
send: (t) =>
|
|
348
|
+
send: (t) => G("resend", "https://api.resend.com/emails", { authorization: `Bearer ${e.apiKey}` }, De(t), async (e) => ({
|
|
349
349
|
id: (await e.json()).id ?? "resend",
|
|
350
350
|
provider: "resend"
|
|
351
351
|
})),
|
|
352
|
-
sendBatch: (t) =>
|
|
352
|
+
sendBatch: (t) => G("resend", "https://api.resend.com/emails/batch", { authorization: `Bearer ${e.apiKey}` }, t.map(De), async (e) => {
|
|
353
353
|
let n = (await e.json()).data ?? [];
|
|
354
354
|
return t.map((e, t) => ({
|
|
355
355
|
id: n[t]?.id ?? "resend",
|
|
356
356
|
provider: "resend"
|
|
357
357
|
}));
|
|
358
358
|
})
|
|
359
|
-
}),
|
|
359
|
+
}), ke = (e) => ({
|
|
360
360
|
name: "postmark",
|
|
361
|
-
send: (t) =>
|
|
361
|
+
send: (t) => G("postmark", "https://api.postmarkapp.com/email", {
|
|
362
362
|
"x-postmark-server-token": e.serverToken,
|
|
363
363
|
accept: "application/json"
|
|
364
364
|
}, {
|
|
365
365
|
From: t.from,
|
|
366
|
-
To:
|
|
366
|
+
To: j(t.to).join(","),
|
|
367
367
|
Subject: t.subject,
|
|
368
368
|
HtmlBody: t.html,
|
|
369
369
|
TextBody: t.text,
|
|
370
370
|
ReplyTo: t.replyTo,
|
|
371
|
-
Cc: t.cc ?
|
|
372
|
-
Bcc: t.bcc ?
|
|
371
|
+
Cc: t.cc ? j(t.cc).join(",") : void 0,
|
|
372
|
+
Bcc: t.bcc ? j(t.bcc).join(",") : void 0,
|
|
373
373
|
MessageStream: t.stream === "broadcast" ? e.streams?.broadcast ?? "broadcast" : e.streams?.transactional ?? "outbound",
|
|
374
374
|
Headers: t.headers ? Object.entries(t.headers).map(([e, t]) => ({
|
|
375
375
|
Name: e,
|
|
@@ -385,44 +385,44 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
385
385
|
id: (await e.json()).MessageID ?? "postmark",
|
|
386
386
|
provider: "postmark"
|
|
387
387
|
}))
|
|
388
|
-
}),
|
|
388
|
+
}), Ae = (e) => [...e.text ? [{
|
|
389
389
|
type: "text/plain",
|
|
390
390
|
value: e.text
|
|
391
391
|
}] : [], ...e.html ? [{
|
|
392
392
|
type: "text/html",
|
|
393
393
|
value: e.html
|
|
394
|
-
}] : []],
|
|
395
|
-
to:
|
|
396
|
-
cc: e.cc ?
|
|
397
|
-
bcc: e.bcc ?
|
|
394
|
+
}] : []], je = (e) => ({
|
|
395
|
+
to: j(e.to).map((e) => ({ email: e })),
|
|
396
|
+
cc: e.cc ? j(e.cc).map((e) => ({ email: e })) : void 0,
|
|
397
|
+
bcc: e.bcc ? j(e.bcc).map((e) => ({ email: e })) : void 0,
|
|
398
398
|
subject: e.subject,
|
|
399
399
|
...e.scheduledAt ? { send_at: Math.floor(e.scheduledAt.getTime() / 1e3) } : {}
|
|
400
|
-
}),
|
|
400
|
+
}), Me = (e) => e.attachments?.map((e) => ({
|
|
401
401
|
filename: e.filename,
|
|
402
402
|
content: e.content,
|
|
403
403
|
type: e.contentType ?? "application/octet-stream",
|
|
404
404
|
disposition: "attachment"
|
|
405
|
-
})),
|
|
405
|
+
})), Ne = (e) => {
|
|
406
406
|
let t = (e) => ({
|
|
407
|
-
personalizations: [
|
|
407
|
+
personalizations: [je(e)],
|
|
408
408
|
from: { email: e.from },
|
|
409
409
|
reply_to: e.replyTo ? { email: e.replyTo } : void 0,
|
|
410
410
|
subject: e.subject,
|
|
411
|
-
content:
|
|
412
|
-
attachments:
|
|
411
|
+
content: Ae(e),
|
|
412
|
+
attachments: Me(e)
|
|
413
413
|
});
|
|
414
414
|
return {
|
|
415
415
|
name: "sendgrid",
|
|
416
416
|
supportsScheduling: !0,
|
|
417
|
-
send: (n) =>
|
|
417
|
+
send: (n) => G("sendgrid", "https://api.sendgrid.com/v3/mail/send", { authorization: `Bearer ${e.apiKey}` }, t(n), async (e) => ({
|
|
418
418
|
id: e.headers.get("x-message-id") ?? "sendgrid",
|
|
419
419
|
provider: "sendgrid"
|
|
420
420
|
})),
|
|
421
|
-
sendBatch: (t) =>
|
|
422
|
-
personalizations: t.map(
|
|
421
|
+
sendBatch: (t) => G("sendgrid", "https://api.sendgrid.com/v3/mail/send", { authorization: `Bearer ${e.apiKey}` }, {
|
|
422
|
+
personalizations: t.map(je),
|
|
423
423
|
from: { email: t[0]?.from },
|
|
424
424
|
subject: t[0]?.subject,
|
|
425
|
-
content:
|
|
425
|
+
content: Ae(t[0] ?? {})
|
|
426
426
|
}, async (e) => {
|
|
427
427
|
let n = e.headers.get("x-message-id") ?? "sendgrid";
|
|
428
428
|
return t.map((e, t) => ({
|
|
@@ -431,35 +431,35 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
431
431
|
}));
|
|
432
432
|
})
|
|
433
433
|
};
|
|
434
|
-
},
|
|
434
|
+
}, Pe = (e, t) => {
|
|
435
435
|
let n = t, r = n.response?.status;
|
|
436
|
-
return
|
|
436
|
+
return W(e, {
|
|
437
437
|
...typeof r == "number" ? { status: r } : {},
|
|
438
438
|
message: n.message ?? String(t)
|
|
439
439
|
});
|
|
440
|
-
},
|
|
441
|
-
let i = yield* (yield*
|
|
440
|
+
}, Fe = (e, t, r) => n.gen(function* () {
|
|
441
|
+
let i = yield* (yield* T.HttpClient).execute(t);
|
|
442
442
|
if (i.status < 200 || i.status >= 300) {
|
|
443
|
-
let t = yield* i.text.pipe(n.
|
|
444
|
-
return yield* n.fail(
|
|
443
|
+
let t = yield* i.text.pipe(n.catch(() => n.succeed("")));
|
|
444
|
+
return yield* n.fail(W(e, {
|
|
445
445
|
status: i.status,
|
|
446
446
|
message: t || `HTTP ${i.status}`
|
|
447
447
|
}));
|
|
448
448
|
}
|
|
449
449
|
return yield* r(i);
|
|
450
|
-
}).pipe(n.
|
|
450
|
+
}).pipe(n.catch((t) => t instanceof D ? n.fail(t) : n.fail(Pe(e, t))), n.provide(w.layer), n.provideService(w.Fetch, (e, t) => globalThis.fetch(e, t))), Ie = (e) => ({ sign: async (t, n, r) => {
|
|
451
451
|
let { createHash: i, createHmac: a } = await import("node:crypto"), o = (e) => i("sha256").update(e).digest("hex"), s = (e, t) => a("sha256", e).update(t).digest(), c = (/* @__PURE__ */ new Date()).toISOString().replace(/[:-]|\.\d{3}/g, ""), l = c.slice(0, 8), u = `host:${new URL(t).host}\nx-amz-date:${c}\n` + (e.sessionToken ? `x-amz-security-token:${e.sessionToken}\n` : ""), d = e.sessionToken ? "host;x-amz-date;x-amz-security-token" : "host;x-amz-date", f = `POST\n${n}\n\n${u}\n${d}\n${o(r)}`, p = `${l}/${e.region}/ses/aws4_request`, m = `AWS4-HMAC-SHA256\n${c}\n${p}\n${o(f)}`, h = a("sha256", s(s(s(s(`AWS4${e.secretAccessKey}`, l), e.region), "ses"), "aws4_request")).update(m).digest("hex");
|
|
452
452
|
return {
|
|
453
453
|
authorization: `AWS4-HMAC-SHA256 Credential=${e.accessKeyId}/${p}, SignedHeaders=${d}, Signature=${h}`,
|
|
454
454
|
"x-amz-date": c,
|
|
455
455
|
...e.sessionToken ? { "x-amz-security-token": e.sessionToken } : {}
|
|
456
456
|
};
|
|
457
|
-
} }),
|
|
457
|
+
} }), Le = (e) => JSON.stringify({
|
|
458
458
|
FromEmailAddress: e.from,
|
|
459
459
|
Destination: {
|
|
460
|
-
ToAddresses:
|
|
461
|
-
...e.cc ? { CcAddresses:
|
|
462
|
-
...e.bcc ? { BccAddresses:
|
|
460
|
+
ToAddresses: j(e.to),
|
|
461
|
+
...e.cc ? { CcAddresses: j(e.cc) } : {},
|
|
462
|
+
...e.bcc ? { BccAddresses: j(e.bcc) } : {}
|
|
463
463
|
},
|
|
464
464
|
...e.replyTo ? { ReplyToAddresses: [e.replyTo] } : {},
|
|
465
465
|
Content: { Simple: {
|
|
@@ -478,47 +478,47 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
478
478
|
} } : {}
|
|
479
479
|
}
|
|
480
480
|
} }
|
|
481
|
-
}),
|
|
482
|
-
let t =
|
|
481
|
+
}), Re = (e) => {
|
|
482
|
+
let t = Ie(e), r = `https://email.${e.region}.amazonaws.com`, i = "/v2/email/outbound-emails";
|
|
483
483
|
return {
|
|
484
484
|
name: "ses",
|
|
485
485
|
send: (e) => n.gen(function* () {
|
|
486
|
-
let a =
|
|
486
|
+
let a = Le(e), o = yield* n.tryPromise({
|
|
487
487
|
try: () => t.sign(r, i, a),
|
|
488
|
-
catch: (e) =>
|
|
488
|
+
catch: (e) => W("ses", { message: e?.message ?? String(e) })
|
|
489
489
|
});
|
|
490
|
-
return yield*
|
|
490
|
+
return yield* Fe("ses", E.post(`${r}${i}`).pipe(E.setHeaders({
|
|
491
491
|
"content-type": "application/json",
|
|
492
492
|
...o
|
|
493
|
-
}),
|
|
493
|
+
}), E.bodyJsonUnsafe(JSON.parse(a))), (e) => e.json.pipe(n.map((e) => ({
|
|
494
494
|
id: e.MessageId ?? "ses",
|
|
495
495
|
provider: "ses"
|
|
496
496
|
}))));
|
|
497
497
|
})
|
|
498
498
|
};
|
|
499
|
-
},
|
|
499
|
+
}, ze = (e) => {
|
|
500
500
|
let t = [["from", e.from], ["subject", e.subject]];
|
|
501
|
-
for (let n of
|
|
502
|
-
if (e.cc) for (let n of
|
|
503
|
-
if (e.bcc) for (let n of
|
|
501
|
+
for (let n of j(e.to)) t.push(["to", n]);
|
|
502
|
+
if (e.cc) for (let n of j(e.cc)) t.push(["cc", n]);
|
|
503
|
+
if (e.bcc) for (let n of j(e.bcc)) t.push(["bcc", n]);
|
|
504
504
|
if (e.replyTo && t.push(["h:Reply-To", e.replyTo]), e.html && t.push(["html", e.html]), e.text && t.push(["text", e.text]), e.headers) for (let [n, r] of Object.entries(e.headers)) t.push([`h:${n}`, r]);
|
|
505
505
|
if (e.tags) for (let n of e.tags) t.push(["o:tag", n]);
|
|
506
506
|
return e.scheduledAt && t.push(["o:deliverytime", e.scheduledAt.toUTCString()]), t;
|
|
507
|
-
},
|
|
507
|
+
}, Be = (e) => {
|
|
508
508
|
let t = `${e.baseUrl ?? "https://api.mailgun.net"}/v3/${e.domain}/messages`;
|
|
509
509
|
return {
|
|
510
510
|
name: "mailgun",
|
|
511
511
|
supportsScheduling: !0,
|
|
512
512
|
send: (r) => {
|
|
513
513
|
let i = new URLSearchParams();
|
|
514
|
-
for (let [e, t] of
|
|
515
|
-
return
|
|
514
|
+
for (let [e, t] of ze(r)) i.append(e, t);
|
|
515
|
+
return Fe("mailgun", E.post(t).pipe(E.setHeader("authorization", `Basic ${Buffer.from(`api:${e.apiKey}`).toString("base64")}`), E.bodyText(i.toString(), "application/x-www-form-urlencoded")), (e) => e.json.pipe(n.map((e) => ({
|
|
516
516
|
id: e.id ?? "mailgun",
|
|
517
517
|
provider: "mailgun"
|
|
518
518
|
}))));
|
|
519
519
|
}
|
|
520
520
|
};
|
|
521
|
-
},
|
|
521
|
+
}, q = (e) => {
|
|
522
522
|
let t = null;
|
|
523
523
|
return {
|
|
524
524
|
name: "smtp",
|
|
@@ -537,9 +537,9 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
537
537
|
return {
|
|
538
538
|
id: (await t.sendMail({
|
|
539
539
|
from: r.from,
|
|
540
|
-
to:
|
|
541
|
-
cc: r.cc ?
|
|
542
|
-
bcc: r.bcc ?
|
|
540
|
+
to: j(r.to),
|
|
541
|
+
cc: r.cc ? j(r.cc) : void 0,
|
|
542
|
+
bcc: r.bcc ? j(r.bcc) : void 0,
|
|
543
543
|
replyTo: r.replyTo,
|
|
544
544
|
subject: r.subject,
|
|
545
545
|
html: r.html,
|
|
@@ -557,53 +557,53 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
557
557
|
},
|
|
558
558
|
catch: (e) => {
|
|
559
559
|
let t = e;
|
|
560
|
-
return
|
|
560
|
+
return W("smtp", {
|
|
561
561
|
...typeof t.responseCode == "number" ? { status: t.responseCode } : {},
|
|
562
562
|
message: t.message ?? String(e)
|
|
563
563
|
});
|
|
564
564
|
}
|
|
565
565
|
})
|
|
566
566
|
};
|
|
567
|
-
},
|
|
567
|
+
}, Ve = (e) => ({
|
|
568
568
|
name: "console",
|
|
569
569
|
send: (t) => n.sync(() => {
|
|
570
|
-
let n = `✉ to=${
|
|
570
|
+
let n = `✉ to=${j(t.to).join(",")} subject=${JSON.stringify(t.subject)}`;
|
|
571
571
|
return e ? e(n, { from: t.from }) : process.stdout.write(`[mail:console] ${n}\n`), {
|
|
572
|
-
id:
|
|
572
|
+
id: Se("console"),
|
|
573
573
|
provider: "console"
|
|
574
574
|
};
|
|
575
575
|
})
|
|
576
|
-
}),
|
|
577
|
-
|
|
578
|
-
},
|
|
576
|
+
}), J = [], He = () => [...J], Ue = () => {
|
|
577
|
+
J.length = 0;
|
|
578
|
+
}, We = () => ({
|
|
579
579
|
name: "memory",
|
|
580
|
-
send: (e) => n.sync(() => (
|
|
581
|
-
id:
|
|
580
|
+
send: (e) => n.sync(() => (J.push(e), {
|
|
581
|
+
id: Se("mem"),
|
|
582
582
|
provider: "memory"
|
|
583
583
|
}))
|
|
584
|
-
}),
|
|
584
|
+
}), Y = f({ scope: "@voltro/plugin-mail" }), Ge = (e) => {
|
|
585
585
|
if (e.provider !== void 0 && typeof e.provider != "string") return e.provider;
|
|
586
586
|
let t = e.env ?? {}, n = e.provider ?? t.MAIL_PROVIDER ?? "console", r = (e, t) => {
|
|
587
587
|
if (!t) throw Error(`@voltro/plugin-mail: provider '${n}' needs apiKey or ${e}`);
|
|
588
588
|
return t;
|
|
589
589
|
};
|
|
590
590
|
switch (n) {
|
|
591
|
-
case "lettermint": return
|
|
592
|
-
case "resend": return
|
|
593
|
-
case "postmark": return
|
|
594
|
-
case "sendgrid": return
|
|
595
|
-
case "ses": return
|
|
591
|
+
case "lettermint": return Ee({ projectToken: r("LETTERMINT_PROJECT_TOKEN", e.apiKey ?? t.LETTERMINT_PROJECT_TOKEN) });
|
|
592
|
+
case "resend": return Oe({ apiKey: r("RESEND_API_KEY", e.apiKey ?? t.RESEND_API_KEY) });
|
|
593
|
+
case "postmark": return ke({ serverToken: r("POSTMARK_SERVER_TOKEN", e.apiKey ?? t.POSTMARK_SERVER_TOKEN) });
|
|
594
|
+
case "sendgrid": return Ne({ apiKey: r("SENDGRID_API_KEY", e.apiKey ?? t.SENDGRID_API_KEY) });
|
|
595
|
+
case "ses": return Re({
|
|
596
596
|
region: r("AWS_REGION", t.AWS_REGION),
|
|
597
597
|
accessKeyId: r("AWS_ACCESS_KEY_ID", t.AWS_ACCESS_KEY_ID),
|
|
598
598
|
secretAccessKey: r("AWS_SECRET_ACCESS_KEY", t.AWS_SECRET_ACCESS_KEY),
|
|
599
599
|
...t.AWS_SESSION_TOKEN ? { sessionToken: t.AWS_SESSION_TOKEN } : {}
|
|
600
600
|
});
|
|
601
|
-
case "mailgun": return
|
|
601
|
+
case "mailgun": return Be({
|
|
602
602
|
apiKey: r("MAILGUN_API_KEY", e.apiKey ?? t.MAILGUN_API_KEY),
|
|
603
603
|
domain: r("MAILGUN_DOMAIN", t.MAILGUN_DOMAIN),
|
|
604
604
|
...t.MAILGUN_BASE_URL ? { baseUrl: t.MAILGUN_BASE_URL } : {}
|
|
605
605
|
});
|
|
606
|
-
case "smtp": return t.SMTP_URL ?
|
|
606
|
+
case "smtp": return t.SMTP_URL ? q({ url: t.SMTP_URL }) : q({
|
|
607
607
|
host: r("SMTP_URL/SMTP_HOST", t.SMTP_HOST),
|
|
608
608
|
...t.SMTP_PORT ? { port: Number(t.SMTP_PORT) } : {},
|
|
609
609
|
secure: t.SMTP_SECURE === "true",
|
|
@@ -612,25 +612,25 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
612
612
|
pass: t.SMTP_PASS
|
|
613
613
|
} } : {}
|
|
614
614
|
});
|
|
615
|
-
case "memory": return
|
|
616
|
-
default: return
|
|
615
|
+
case "memory": return We();
|
|
616
|
+
default: return Ve((e, t) => Y.info(e, t));
|
|
617
617
|
}
|
|
618
|
-
},
|
|
619
|
-
let t = e.attempts ?? 3, r = e.suppression ??
|
|
618
|
+
}, X = (e) => {
|
|
619
|
+
let t = e.attempts ?? 3, r = e.suppression ?? B(), i = e.allowlist, a = e.production !== !0 && i !== void 0 && i.length > 0, s = (e) => i.some((t) => t.toLowerCase() === e.toLowerCase()), c = o.recurs(t).pipe(o.while(({ input: e }) => e.transient)), l = /* @__PURE__ */ new Map();
|
|
620
620
|
for (let t of e.templates ?? []) l.set(t.locale ? `${t.name}:${t.locale}` : t.name, t);
|
|
621
|
-
let u = (e, t) => (t ? l.get(`${e}:${t}`) : void 0) ?? l.get(e) ??
|
|
621
|
+
let u = (e, t) => (t ? l.get(`${e}:${t}`) : void 0) ?? l.get(e) ?? P(e, t), d = /* @__PURE__ */ new Map(), f = (e, t) => `${e.name}|${e.locale ?? ""}|${JSON.stringify(t ?? null)}`, p = (e, t) => {
|
|
622
622
|
if (d.set(e, t), d.size > 500) {
|
|
623
623
|
let e = d.keys().next().value;
|
|
624
624
|
e !== void 0 && d.delete(e);
|
|
625
625
|
}
|
|
626
|
-
}, m = e.idempotency ??
|
|
627
|
-
store: e.schedule ??
|
|
626
|
+
}, m = e.idempotency ?? H(), h = be({
|
|
627
|
+
store: e.schedule ?? U(),
|
|
628
628
|
providerSchedules: e.provider.supportsScheduling === !0,
|
|
629
|
-
flush: (e) =>
|
|
629
|
+
flush: (e) => y(e)
|
|
630
630
|
}), g = (t) => {
|
|
631
631
|
if (t.stream !== "broadcast" || e.provider.managesUnsubscribe === !0) return n.succeed(void 0);
|
|
632
632
|
let r = t.unsubscribe;
|
|
633
|
-
if (r === void 0 || !r.oneClickUrl.startsWith("https://")) return n.fail(new
|
|
633
|
+
if (r === void 0 || !r.oneClickUrl.startsWith("https://")) return n.fail(new D({
|
|
634
634
|
provider: e.provider.name,
|
|
635
635
|
message: `a broadcast needs \`unsubscribe: { oneClickUrl }\` (an https URL) — '${e.provider.name}' does not unsubscribe recipients itself`,
|
|
636
636
|
transient: !1
|
|
@@ -642,15 +642,15 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
642
642
|
});
|
|
643
643
|
}, _ = (t) => n.gen(function* () {
|
|
644
644
|
let i = t.from ?? e.from;
|
|
645
|
-
if (!i) return yield* n.fail(new
|
|
645
|
+
if (!i) return yield* n.fail(new D({
|
|
646
646
|
provider: e.provider.name,
|
|
647
647
|
message: "no `from` — set mailPlugin({ from }) or pass message.from",
|
|
648
648
|
transient: !1
|
|
649
649
|
}));
|
|
650
|
-
let o =
|
|
650
|
+
let o = j(t.to);
|
|
651
651
|
if (a) {
|
|
652
652
|
let n = o.filter(s);
|
|
653
|
-
if (n.length === 0) return
|
|
653
|
+
if (n.length === 0) return Y.warn("mail skipped — no recipient in allowlist (non-production)", {
|
|
654
654
|
to: o.join(","),
|
|
655
655
|
subject: t.subject
|
|
656
656
|
}), e.onSent?.({
|
|
@@ -672,7 +672,7 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
672
672
|
}
|
|
673
673
|
let c = t.tenantId ?? null, l = [];
|
|
674
674
|
for (let e of o) (yield* r.isSuppressed(c, e)) || l.push(e);
|
|
675
|
-
if (l.length === 0) return
|
|
675
|
+
if (l.length === 0) return Y.warn("mail skipped — all recipients suppressed", {
|
|
676
676
|
to: o.join(","),
|
|
677
677
|
subject: t.subject
|
|
678
678
|
}), e.onSent?.({
|
|
@@ -705,10 +705,10 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
705
705
|
...f === void 0 ? {} : { headers: f }
|
|
706
706
|
}
|
|
707
707
|
};
|
|
708
|
-
}),
|
|
709
|
-
let r =
|
|
708
|
+
}), v = (t) => {
|
|
709
|
+
let r = j(t.to);
|
|
710
710
|
return e.provider.send(t).pipe(n.retry(c), n.tap((i) => n.sync(() => {
|
|
711
|
-
|
|
711
|
+
Y.info("mail sent", {
|
|
712
712
|
provider: i.provider,
|
|
713
713
|
id: i.id,
|
|
714
714
|
to: r.join(",")
|
|
@@ -722,7 +722,7 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
722
722
|
ts: Date.now()
|
|
723
723
|
});
|
|
724
724
|
})), n.tapError((i) => n.sync(() => {
|
|
725
|
-
|
|
725
|
+
Y.warn("mail failed", {
|
|
726
726
|
provider: i.provider,
|
|
727
727
|
status: i.status,
|
|
728
728
|
message: i.message
|
|
@@ -737,14 +737,14 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
737
737
|
ts: Date.now()
|
|
738
738
|
});
|
|
739
739
|
})));
|
|
740
|
-
},
|
|
740
|
+
}, y = (t) => n.gen(function* () {
|
|
741
741
|
let n = yield* _(t);
|
|
742
|
-
return n.kind === "skip" ? n.result : h.shouldHold(t.scheduledAt) ? (yield* h.hold(n.message),
|
|
742
|
+
return n.kind === "skip" ? n.result : h.shouldHold(t.scheduledAt) ? (yield* h.hold(n.message), Y.info("mail scheduled (held for later flush)", {
|
|
743
743
|
subject: n.message.subject,
|
|
744
744
|
dueAt: t.scheduledAt?.toISOString()
|
|
745
745
|
}), e.onSent?.({
|
|
746
746
|
id: "scheduled",
|
|
747
|
-
to:
|
|
747
|
+
to: j(n.message.to),
|
|
748
748
|
from: n.message.from,
|
|
749
749
|
subject: n.message.subject,
|
|
750
750
|
provider: "scheduled",
|
|
@@ -753,24 +753,24 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
753
753
|
}), {
|
|
754
754
|
id: "scheduled",
|
|
755
755
|
provider: "scheduled"
|
|
756
|
-
}) : yield*
|
|
757
|
-
}),
|
|
756
|
+
}) : yield* v(n.message);
|
|
757
|
+
}), b = (e, t, r) => t === void 0 ? r : n.gen(function* () {
|
|
758
758
|
let n = yield* m.reserve(e, t);
|
|
759
|
-
if (!n.won) return
|
|
759
|
+
if (!n.won) return Y.info("mail idempotent replay — skipped", { key: t }), n.prior ?? {
|
|
760
760
|
id: "idempotent-replay",
|
|
761
761
|
provider: "idempotent"
|
|
762
762
|
};
|
|
763
763
|
let i = yield* r;
|
|
764
764
|
return yield* m.record(e, t, i), i;
|
|
765
|
-
}),
|
|
765
|
+
}), x = (e) => n.suspend(() => {
|
|
766
766
|
let t = u(e.template, e.locale);
|
|
767
|
-
if (!t) return n.fail(new
|
|
767
|
+
if (!t) return n.fail(new D({
|
|
768
768
|
provider: "template",
|
|
769
769
|
message: `unknown template '${e.template}'${e.locale ? ` (locale '${e.locale}')` : ""}`,
|
|
770
770
|
transient: !1
|
|
771
771
|
}));
|
|
772
772
|
let r = f(t, e.props), i = d.get(r);
|
|
773
|
-
return (i ? n.succeed(i) :
|
|
773
|
+
return (i ? n.succeed(i) : ne(t, e.props).pipe(n.tap((e) => n.sync(() => p(r, e))))).pipe(n.map((t) => ({
|
|
774
774
|
to: e.to,
|
|
775
775
|
subject: t.subject,
|
|
776
776
|
html: t.html,
|
|
@@ -789,15 +789,15 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
789
789
|
...e.unsubscribe === void 0 ? {} : { unsubscribe: e.unsubscribe },
|
|
790
790
|
...e.metadata === void 0 ? {} : { metadata: e.metadata }
|
|
791
791
|
})));
|
|
792
|
-
}),
|
|
792
|
+
}), S = (e) => "template" in e ? x(e) : n.succeed(e);
|
|
793
793
|
return {
|
|
794
794
|
service: {
|
|
795
795
|
send: (e) => n.gen(function* () {
|
|
796
|
-
let t = yield*
|
|
797
|
-
return yield*
|
|
796
|
+
let t = yield* S(e);
|
|
797
|
+
return yield* b(t.tenantId ?? null, t.idempotencyKey, y(t));
|
|
798
798
|
}),
|
|
799
799
|
sendBatch: (t) => n.gen(function* () {
|
|
800
|
-
let r = yield* n.forEach(t,
|
|
800
|
+
let r = yield* n.forEach(t, S), i = r.some((e) => e.idempotencyKey !== void 0 || h.shouldHold(e.scheduledAt));
|
|
801
801
|
if (e.provider.sendBatch && !i) {
|
|
802
802
|
let t = [], i = [];
|
|
803
803
|
for (let e of r) {
|
|
@@ -807,13 +807,13 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
807
807
|
let a = t.length > 0 ? yield* e.provider.sendBatch(t).pipe(n.retry(c), n.tap((r) => n.sync(() => {
|
|
808
808
|
t.forEach((t, n) => {
|
|
809
809
|
let i = r[n];
|
|
810
|
-
i && (
|
|
810
|
+
i && (Y.info("mail sent (batch)", {
|
|
811
811
|
provider: i.provider,
|
|
812
812
|
id: i.id,
|
|
813
|
-
to:
|
|
813
|
+
to: j(t.to).join(",")
|
|
814
814
|
}), e.onSent?.({
|
|
815
815
|
id: i.id,
|
|
816
|
-
to:
|
|
816
|
+
to: j(t.to),
|
|
817
817
|
from: t.from,
|
|
818
818
|
subject: t.subject,
|
|
819
819
|
provider: i.provider,
|
|
@@ -821,7 +821,7 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
821
821
|
ts: Date.now()
|
|
822
822
|
}));
|
|
823
823
|
});
|
|
824
|
-
})), n.tapError((e) => n.sync(() =>
|
|
824
|
+
})), n.tapError((e) => n.sync(() => Y.warn("mail batch failed", {
|
|
825
825
|
provider: e.provider,
|
|
826
826
|
status: e.status,
|
|
827
827
|
message: e.message
|
|
@@ -831,7 +831,7 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
831
831
|
provider: e.provider.name
|
|
832
832
|
} : t);
|
|
833
833
|
}
|
|
834
|
-
return yield* n.forEach(r, (e) =>
|
|
834
|
+
return yield* n.forEach(r, (e) => b(e.tenantId ?? null, e.idempotencyKey, y(e)));
|
|
835
835
|
}),
|
|
836
836
|
suppress: r.suppress,
|
|
837
837
|
unsuppress: r.unsuppress,
|
|
@@ -843,7 +843,7 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
843
843
|
},
|
|
844
844
|
scheduler: h
|
|
845
845
|
};
|
|
846
|
-
},
|
|
846
|
+
}, Ke = (e) => X(e).service, qe = (e) => i.succeed(A, Ke(e)), Z = (e, t, n, r, i, a = {}) => {
|
|
847
847
|
if (!t) return null;
|
|
848
848
|
let o = a.metadata !== null && typeof a.metadata == "object" ? Object.fromEntries(Object.entries(a.metadata).filter(([, e]) => typeof e == "string")) : void 0;
|
|
849
849
|
return {
|
|
@@ -855,33 +855,33 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
855
855
|
...a.eventId === void 0 ? {} : { eventId: a.eventId },
|
|
856
856
|
...o === void 0 ? {} : { metadata: o }
|
|
857
857
|
};
|
|
858
|
-
},
|
|
858
|
+
}, Je = (e) => e === "message.hard_bounced" ? "bounced" : e === "message.spam_complaint" ? "complained" : e === "message.unsubscribed" ? "unsubscribed" : e === "message.delivered" ? "delivered" : e === "message.opened" ? "opened" : e === "message.clicked" ? "clicked" : "unknown", Ye = (e) => e === "hard_bounce" ? "bounced" : e === "spam_complaint" ? "complained" : e === "unsubscribe" ? "unsubscribed" : "unknown", Xe = (e) => e === "email.bounced" ? "bounced" : e === "email.complained" ? "complained" : e === "email.delivered" ? "delivered" : e === "email.opened" ? "opened" : e === "email.clicked" ? "clicked" : "unknown", Ze = (e) => e === "Bounce" ? "bounced" : e === "SpamComplaint" ? "complained" : e === "Delivery" ? "delivered" : e === "Open" ? "opened" : e === "Click" ? "clicked" : "unknown", Qe = (e) => e === "bounce" || e === "dropped" ? "bounced" : e === "spamreport" ? "complained" : e === "delivered" ? "delivered" : e === "open" ? "opened" : e === "click" ? "clicked" : "unknown", $e = (e, t) => {
|
|
859
859
|
let n = [], r = (e) => {
|
|
860
860
|
e && n.push(e);
|
|
861
861
|
};
|
|
862
862
|
if (e === "sendgrid" && Array.isArray(t)) {
|
|
863
|
-
for (let e of t) r(
|
|
863
|
+
for (let e of t) r(Z(Qe(String(e.event)), e.email, "sendgrid", e.sg_message_id, e));
|
|
864
864
|
return n;
|
|
865
865
|
}
|
|
866
866
|
let i = t ?? {};
|
|
867
867
|
if (e === "lettermint") {
|
|
868
868
|
let e = String(i.event), a = i.data ?? {}, o = typeof i.id == "string" ? i.id : void 0;
|
|
869
|
-
return e === "suppression.added" ? (a.type === "email" && r(
|
|
869
|
+
return e === "suppression.added" ? (a.type === "email" && r(Z(Ye(String(a.reason)), a.value, "lettermint", void 0, t, { eventId: o })), n) : e === "suppression.removed" ? (a.type === "email" && r(Z("unsuppressed", a.value, "lettermint", void 0, t, { eventId: o })), n) : (e.startsWith("message.") && r(Z(Je(e), a.recipient, "lettermint", a.message_id, t, {
|
|
870
870
|
eventId: o,
|
|
871
871
|
metadata: a.metadata
|
|
872
872
|
})), n);
|
|
873
873
|
}
|
|
874
874
|
if (e === "resend") {
|
|
875
875
|
let e = i.data ?? {}, a = Array.isArray(e.to) ? e.to[0] : e.to ?? e.email;
|
|
876
|
-
return r(
|
|
876
|
+
return r(Z(Xe(String(i.type)), a, "resend", e.email_id, t)), n;
|
|
877
877
|
}
|
|
878
878
|
if (e === "postmark") {
|
|
879
879
|
let e = i.Email ?? i.Recipient;
|
|
880
|
-
return r(
|
|
880
|
+
return r(Z(Ze(String(i.RecordType)), e, "postmark", i.MessageID, t, { metadata: i.Metadata })), n;
|
|
881
881
|
}
|
|
882
882
|
return n;
|
|
883
883
|
}, et = (e, t, r, i = null) => n.gen(function* () {
|
|
884
|
-
let n =
|
|
884
|
+
let n = $e(e, t);
|
|
885
885
|
for (let e of n) e.type === "bounced" || e.type === "complained" ? yield* r.suppress(i, e.email, e.type) : e.type === "unsuppressed" && (yield* r.unsuppress(i, e.email));
|
|
886
886
|
return n;
|
|
887
887
|
}), tt = (e = 200) => {
|
|
@@ -925,27 +925,27 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
925
925
|
case "smtp": return n((t.SMTP_URL ? rt(t.SMTP_URL) : void 0) ?? (t.SMTP_HOST ? `${t.SMTP_HOST}${t.SMTP_PORT ? `:${t.SMTP_PORT}` : ""}` : void 0) ?? "runtime:SMTP_URL or SMTP_HOST");
|
|
926
926
|
default: return [];
|
|
927
927
|
}
|
|
928
|
-
},
|
|
928
|
+
}, Q = (e, t) => {
|
|
929
929
|
if (t > 6) return null;
|
|
930
|
+
let n = e.encoding === void 0 ? e : e.encoding[e.encoding.length - 1].to;
|
|
931
|
+
if (n !== e) return Q(n, t + 1);
|
|
930
932
|
switch (e._tag) {
|
|
931
|
-
case "
|
|
932
|
-
case "
|
|
933
|
-
case "
|
|
933
|
+
case "String": return "";
|
|
934
|
+
case "Number": return 0;
|
|
935
|
+
case "Boolean": return !1;
|
|
934
936
|
case "Literal": return e.literal;
|
|
935
|
-
case "
|
|
936
|
-
case "
|
|
937
|
+
case "Enum": return e.enums.length > 0 ? e.enums[0][1] : null;
|
|
938
|
+
case "Objects": {
|
|
937
939
|
let n = {};
|
|
938
|
-
for (let r of e.propertySignatures) typeof r.name == "string" && (n[r.name] =
|
|
940
|
+
for (let r of e.propertySignatures) typeof r.name == "string" && (n[r.name] = Q(r.type, t + 1));
|
|
939
941
|
return n;
|
|
940
942
|
}
|
|
941
|
-
case "
|
|
942
|
-
case "Union": return e.types.length > 0 ?
|
|
943
|
-
case "
|
|
944
|
-
case "Transformation": return Z(e.from, t + 1);
|
|
945
|
-
case "Suspend": return Z(e.f(), t + 1);
|
|
943
|
+
case "Arrays": return [];
|
|
944
|
+
case "Union": return e.types.length > 0 ? Q(e.types[0], t + 1) : null;
|
|
945
|
+
case "Suspend": return Q(e.thunk(), t + 1);
|
|
946
946
|
default: return null;
|
|
947
947
|
}
|
|
948
|
-
}, at = (e) =>
|
|
948
|
+
}, at = (e) => Q(e.ast, 0), ot = d([
|
|
949
949
|
{
|
|
950
950
|
name: "MAIL_PROVIDER",
|
|
951
951
|
required: !1,
|
|
@@ -1066,25 +1066,25 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1066
1066
|
secret: !1,
|
|
1067
1067
|
description: "Comma-separated recipient allowlist; in dev, mail to addresses outside it is skipped."
|
|
1068
1068
|
}
|
|
1069
|
-
]),
|
|
1069
|
+
]), st = "@voltro/plugin-mail", $ = (e, t) => ({
|
|
1070
1070
|
status: e,
|
|
1071
1071
|
contentType: "application/json",
|
|
1072
1072
|
body: JSON.stringify(t)
|
|
1073
|
-
}),
|
|
1074
|
-
let
|
|
1075
|
-
if (
|
|
1076
|
-
let
|
|
1077
|
-
if (!
|
|
1073
|
+
}), ct = (e, t, r, i) => {
|
|
1074
|
+
let o = e.webhook;
|
|
1075
|
+
if (o === void 0) throw Error(`@voltro/plugin-mail: provider '${e.name}' has no webhook verifier — mailPlugin({ webhook }) needs one (lettermint)`);
|
|
1076
|
+
let s = r.secret ?? ot.read("MAIL_WEBHOOK_SECRET");
|
|
1077
|
+
if (!s && i) throw Error("@voltro/plugin-mail: mailPlugin({ webhook }) needs a signing secret in production — set MAIL_WEBHOOK_SECRET");
|
|
1078
1078
|
return {
|
|
1079
1079
|
method: "POST",
|
|
1080
1080
|
path: r.path ?? "/webhooks/mail",
|
|
1081
1081
|
handle: async (i) => {
|
|
1082
|
-
if (!
|
|
1083
|
-
let
|
|
1084
|
-
if (
|
|
1085
|
-
let
|
|
1082
|
+
if (!s) return $(503, { error: "mail webhook secret not configured" });
|
|
1083
|
+
let c = await n.runPromise(n.result(o.verify(i.headers, new TextDecoder().decode(i.rawBody), s)));
|
|
1084
|
+
if (a.isFailure(c)) return $(401, { error: c.failure.message });
|
|
1085
|
+
let l = $e(e.name, c.success);
|
|
1086
1086
|
try {
|
|
1087
|
-
for (let e of
|
|
1087
|
+
for (let e of l) {
|
|
1088
1088
|
e.type === "bounced" || e.type === "complained" ? await n.runPromise(t.suppress(null, e.email, e.type)) : e.type === "unsuppressed" && await n.runPromise(t.unsuppress(null, e.email));
|
|
1089
1089
|
let a = r.onEvent?.(e, { store: i.store });
|
|
1090
1090
|
n.isEffect(a) ? await n.runPromise(a) : await a;
|
|
@@ -1095,23 +1095,23 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1095
1095
|
cause: e
|
|
1096
1096
|
};
|
|
1097
1097
|
}
|
|
1098
|
-
return $(200, { received:
|
|
1098
|
+
return $(200, { received: l.length });
|
|
1099
1099
|
}
|
|
1100
1100
|
};
|
|
1101
|
-
},
|
|
1102
|
-
let a = process.env, s =
|
|
1101
|
+
}, lt = (e = {}) => {
|
|
1102
|
+
let a = process.env, s = Ge({
|
|
1103
1103
|
...e.provider === void 0 ? {} : { provider: e.provider },
|
|
1104
1104
|
...e.apiKey === void 0 ? {} : { apiKey: e.apiKey },
|
|
1105
1105
|
env: a
|
|
1106
|
-
}),
|
|
1107
|
-
e.idempotency === "postgres" &&
|
|
1106
|
+
}), c = ot.read("MAIL_ALLOWLIST"), d = e.allowlist ?? (c ? c.split(",").map((e) => e.trim()).filter(Boolean) : void 0), f = a.NODE_ENV === "production", p = e.suppression === void 0 || e.suppression === "memory" ? B() : e.suppression === "postgres" ? me() : e.suppression, m = e.idempotency === void 0 || e.idempotency === "memory" ? H() : e.idempotency === "postgres" ? ge() : e.idempotency, h = e.schedule ?? U(), g = [...e.suppression === "postgres" ? [le] : [], ...e.idempotency === "postgres" ? [ue] : []];
|
|
1107
|
+
e.idempotency === "postgres" && y({
|
|
1108
1108
|
source: "plugin",
|
|
1109
|
-
table:
|
|
1109
|
+
table: I,
|
|
1110
1110
|
timeColumn: "createdAt",
|
|
1111
|
-
ttlMs:
|
|
1111
|
+
ttlMs: b(process.env.VOLTRO_MAIL_IDEMPOTENCY_TTL_HOURS, 720),
|
|
1112
1112
|
label: "mail idempotency keys"
|
|
1113
1113
|
});
|
|
1114
|
-
let _ = tt(),
|
|
1114
|
+
let _ = tt(), v = X({
|
|
1115
1115
|
provider: s,
|
|
1116
1116
|
suppression: p,
|
|
1117
1117
|
idempotency: m,
|
|
@@ -1123,21 +1123,21 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1123
1123
|
...e.attempts === void 0 ? {} : { attempts: e.attempts },
|
|
1124
1124
|
...e.templates === void 0 ? {} : { templates: e.templates },
|
|
1125
1125
|
production: f
|
|
1126
|
-
}),
|
|
1127
|
-
for (let t of e.templates ?? [])
|
|
1128
|
-
let
|
|
1126
|
+
}), x = i.succeed(A, v.service), S = s.supportsScheduling !== !0, C = e.scheduleTickMs ?? 1e3, w, T = /* @__PURE__ */ new Map();
|
|
1127
|
+
for (let t of e.templates ?? []) T.set(t.locale ? `${t.name}:${t.locale}` : t.name, t);
|
|
1128
|
+
let E = (e, t) => (t ? T.get(`${e}:${t}`) : void 0) ?? T.get(e) ?? P(e, t), D = (e) => ({
|
|
1129
1129
|
name: e.name,
|
|
1130
1130
|
...e.locale ? { locale: e.locale } : {},
|
|
1131
1131
|
props: e.preview ?? at(e.props)
|
|
1132
|
-
}),
|
|
1132
|
+
}), O = () => {
|
|
1133
1133
|
let t = /* @__PURE__ */ new Map();
|
|
1134
|
-
for (let n of e.templates ?? []) t.set(n.locale ? `${n.name}:${n.locale}` : n.name,
|
|
1135
|
-
for (let e of
|
|
1136
|
-
let n =
|
|
1137
|
-
n && t.set(e.locale ? `${e.name}:${e.locale}` : e.name,
|
|
1134
|
+
for (let n of e.templates ?? []) t.set(n.locale ? `${n.name}:${n.locale}` : n.name, D(n));
|
|
1135
|
+
for (let e of oe()) {
|
|
1136
|
+
let n = P(e.name, e.locale);
|
|
1137
|
+
n && t.set(e.locale ? `${e.name}:${e.locale}` : e.name, D(n));
|
|
1138
1138
|
}
|
|
1139
1139
|
return [...t.values()];
|
|
1140
|
-
},
|
|
1140
|
+
}, k = e.webhook === void 0 ? [] : [ct(s, p, e.webhook, f)], j = [
|
|
1141
1141
|
{
|
|
1142
1142
|
method: "GET",
|
|
1143
1143
|
path: "/outbox",
|
|
@@ -1155,7 +1155,7 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1155
1155
|
description: "Discovered + registered email templates",
|
|
1156
1156
|
handler: () => n.succeed({
|
|
1157
1157
|
kind: "json",
|
|
1158
|
-
data: { templates:
|
|
1158
|
+
data: { templates: O() }
|
|
1159
1159
|
})
|
|
1160
1160
|
},
|
|
1161
1161
|
{
|
|
@@ -1178,11 +1178,11 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1178
1178
|
status: 400,
|
|
1179
1179
|
data: { error: "missing \"template\"" }
|
|
1180
1180
|
};
|
|
1181
|
-
let r =
|
|
1182
|
-
return r ? yield*
|
|
1181
|
+
let r = E(t.template, t.locale);
|
|
1182
|
+
return r ? yield* ne(r, t.props).pipe(n.map((e) => ({
|
|
1183
1183
|
kind: "json",
|
|
1184
1184
|
data: e
|
|
1185
|
-
})), n.
|
|
1185
|
+
})), n.catch((e) => n.succeed({
|
|
1186
1186
|
kind: "json",
|
|
1187
1187
|
status: 400,
|
|
1188
1188
|
data: { error: e.message }
|
|
@@ -1193,38 +1193,38 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1193
1193
|
};
|
|
1194
1194
|
})
|
|
1195
1195
|
}
|
|
1196
|
-
],
|
|
1196
|
+
], ee = [
|
|
1197
1197
|
"network:outbound:*",
|
|
1198
1198
|
"inspect:read",
|
|
1199
1199
|
"inspect:write",
|
|
1200
1200
|
...g.length > 0 ? ["store:write"] : []
|
|
1201
1201
|
];
|
|
1202
1202
|
return {
|
|
1203
|
-
...
|
|
1204
|
-
name:
|
|
1205
|
-
base:
|
|
1203
|
+
...l({
|
|
1204
|
+
name: u({
|
|
1205
|
+
base: st,
|
|
1206
1206
|
alias: e.alias,
|
|
1207
1207
|
instance: e.name
|
|
1208
1208
|
}),
|
|
1209
|
-
baseName:
|
|
1209
|
+
baseName: st,
|
|
1210
1210
|
description: "Transactional and broadcast email — MailService over Lettermint / Resend / Postmark / SendGrid / SES / Mailgun / SMTP (+ console/memory), with default-from, transient retry, suppression and a dev allowlist.",
|
|
1211
|
-
permissions:
|
|
1212
|
-
declaredEnv:
|
|
1211
|
+
permissions: ee,
|
|
1212
|
+
declaredEnv: ot.declared,
|
|
1213
1213
|
egress: it({
|
|
1214
1214
|
...e.provider === void 0 ? {} : { provider: e.provider },
|
|
1215
1215
|
env: a
|
|
1216
1216
|
}),
|
|
1217
|
-
services:
|
|
1218
|
-
inspectEndpoints:
|
|
1219
|
-
...
|
|
1217
|
+
services: x,
|
|
1218
|
+
inspectEndpoints: j,
|
|
1219
|
+
...k.length > 0 ? { httpRoutes: k } : {},
|
|
1220
1220
|
...g.length > 0 ? { extendSchema: { tables: g } } : {},
|
|
1221
1221
|
bindDataStore: async (e) => {
|
|
1222
1222
|
await p.bind?.(e), await m.bind?.(e);
|
|
1223
1223
|
},
|
|
1224
1224
|
onActivate: (r) => n.gen(function* () {
|
|
1225
|
-
if (p.activate && (yield* n.promise(() => p.activate(r.env))), m.activate && (yield* n.promise(() => m.activate(r.env))),
|
|
1226
|
-
let e =
|
|
1227
|
-
|
|
1225
|
+
if (p.activate && (yield* n.promise(() => p.activate(r.env))), m.activate && (yield* n.promise(() => m.activate(r.env))), S) {
|
|
1226
|
+
let e = v.scheduler.tick().pipe(n.repeat(o.spaced(t.millis(Math.max(50, C)))));
|
|
1227
|
+
w = n.runFork(e);
|
|
1228
1228
|
}
|
|
1229
1229
|
r.logger.info("mail active", {
|
|
1230
1230
|
provider: s.name,
|
|
@@ -1237,11 +1237,11 @@ var w = class extends s.TaggedError()("MailError", {
|
|
|
1237
1237
|
});
|
|
1238
1238
|
}),
|
|
1239
1239
|
onDeactivate: () => n.gen(function* () {
|
|
1240
|
-
|
|
1240
|
+
w !== void 0 && (yield* r.interrupt(w), w = void 0), p.deactivate && (yield* n.promise(() => p.deactivate())), m.deactivate && (yield* n.promise(() => m.deactivate()));
|
|
1241
1241
|
})
|
|
1242
1242
|
}),
|
|
1243
|
-
service:
|
|
1243
|
+
service: v.service
|
|
1244
1244
|
};
|
|
1245
1245
|
};
|
|
1246
1246
|
//#endregion
|
|
1247
|
-
export {
|
|
1247
|
+
export { D as MailError, A as MailService, O as MailWebhookError, Ke as buildMailService, X as buildMailServiceWithScheduler, se as clearGlobalTemplates, Ue as clearMailBuffer, Ve as consoleProvider, tt as createOutbox, k as defineEmail, ae as globalTemplateCount, et as handleMailEvents, ye as heldId, ce as isEmailTemplate, Ee as lettermintProvider, oe as listGlobalTemplates, P as lookupGlobalTemplate, it as mailEgressOf, lt as mailPlugin, qe as mailServiceLayer, Be as mailgunProvider, be as makeScheduler, H as memoryIdempotencyStore, We as memoryProvider, U as memoryScheduleStore, B as memorySuppressionStore, $e as parseMailEvent, ge as postgresIdempotencyStore, me as postgresSuppressionStore, ke as postmarkProvider, He as readMailBuffer, ie as registerEmailTemplates, ne as renderTemplate, Oe as resendProvider, Ge as resolveProvider, Ne as sendgridProvider, Re as sesProvider, q as smtpProvider, Te as verifyLettermintSignature };
|