@visulima/email 2.1.6 → 2.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/dist/crypto/index.d.ts +183 -183
- package/dist/crypto/index.js +1 -1
- package/dist/deliverability/dmarc-report.d.ts +43 -43
- package/dist/deliverability/dmarc-report.js +1 -1
- package/dist/deliverability/index.d.ts +201 -201
- package/dist/events/index.d.ts +17 -17
- package/dist/inbound/index.d.ts +180 -180
- package/dist/index.d.ts +35 -46
- package/dist/index.js +1 -1
- package/dist/middleware/index.d.ts +213 -216
- package/dist/middleware/index.js +1 -1
- package/dist/packem_shared/{DkimSigner-CiLBaXrg.js → DkimSigner-udCl3JXO.js} +6 -6
- package/dist/packem_shared/{DraftMailMessage-CGTVuy2z.js → DraftMailMessage-BgP1OF1G.js} +1 -1
- package/dist/packem_shared/EmailError-2CCyVX1S.js +1 -0
- package/dist/packem_shared/Mail-DduRntbB.js +1 -0
- package/dist/packem_shared/MailMessage-BRBT4Jea.js +1 -0
- package/dist/packem_shared/{RequiredOptionError-DuNNY_a5.js → RequiredOptionError-BmpC5whN.js} +1 -1
- package/dist/packem_shared/SmimeEncrypter-Dm9McVTQ.js +6 -0
- package/dist/packem_shared/SmimeSigner-B6hkacNk.js +8 -0
- package/dist/packem_shared/{address-formatter-BWR2Dddx.js → address-formatter-bfmGfQ83.js} +1 -1
- package/dist/packem_shared/{ahaSendProvider-DSuZIzaQ.js → ahaSendProvider-C6nBGCCa.js} +1 -1
- package/dist/packem_shared/arcMessageSignatureBase-B2uArM48.js +17 -0
- package/dist/packem_shared/attachment-processor-DjbjtJ6H.js +1 -0
- package/dist/packem_shared/{autoSendProvider-DqAoelWR.js → autoSendProvider-Dhig--Zo.js} +1 -1
- package/dist/packem_shared/{awsSesProvider-ClK1FUln.js → awsSesProvider-CMqAmU5N.js} +13 -13
- package/dist/packem_shared/azureProvider-C-bNOOil.js +1 -0
- package/dist/packem_shared/{brevoProvider-CIzuIDlt.js → brevoProvider-CkOjDyir.js} +1 -1
- package/dist/packem_shared/build-mime-message-t8KYiQkO.js +3 -0
- package/dist/packem_shared/{circuitBreakerMiddleware-D2SA_07f.js → circuitBreakerMiddleware-BSCPR72q.js} +1 -1
- package/dist/packem_shared/{cloudflareEmailProvider-B8mOEl3N.js → cloudflareEmailProvider-RCixPWnY.js} +1 -1
- package/dist/packem_shared/{createTestEmail-f12yLlWn.js → createTestEmail-XiF5E8vJ.js} +1 -1
- package/dist/packem_shared/dedupeMiddleware-CYYI_O7S.js +1 -0
- package/dist/packem_shared/{detectMimeType-DFH3kp6K.js → detectMimeType-B9_7ujpC.js} +1 -1
- package/dist/packem_shared/event-bus.d-BNQA-FZE.d.ts +104 -0
- package/dist/packem_shared/{failoverProvider-BgX6zfnY.js → failoverProvider-BkOOP7pt.js} +1 -1
- package/dist/packem_shared/generate-boundary-0xGe9GqK.js +1 -0
- package/dist/packem_shared/{httpProvider-aBfTXyCT.js → httpProvider-6idLfv-f.js} +1 -1
- package/dist/packem_shared/index-y0s2wQdc.js +11 -0
- package/dist/packem_shared/{infobipProvider-DxzsONUX.js → infobipProvider-CHHsqRXy.js} +1 -1
- package/dist/packem_shared/isValidSigningCertUrl-D7PuiRW4.js +3 -0
- package/dist/packem_shared/{loopsProvider-QBsAH6Ee.js → loopsProvider-Cl-dOuCN.js} +1 -1
- package/dist/packem_shared/mail.d-B9JyPxzq.d.ts +910 -0
- package/dist/packem_shared/{mailCrabProvider-DRE5snM9.js → mailCrabProvider-De2YxPlF.js} +1 -1
- package/dist/packem_shared/{mailPaceProvider-DCa-4ghl.js → mailPaceProvider-DwNTuFb2.js} +1 -1
- package/dist/packem_shared/{mailchannelsProvider-GiwkYBdD.js → mailchannelsProvider-Dwl0Typz.js} +1 -1
- package/dist/packem_shared/{mailerSendProvider-RK6IbUrL.js → mailerSendProvider-CyMIbqGq.js} +1 -1
- package/dist/packem_shared/mailgunProvider-DWKJYRKT.js +1 -0
- package/dist/packem_shared/mailjetProvider-DXPJQO1G.js +1 -0
- package/dist/packem_shared/{mailomatProvider-DPDpVS8r.js → mailomatProvider-DopZk27y.js} +1 -1
- package/dist/packem_shared/{mailtrapProvider-DtrS4Q34.js → mailtrapProvider-CTg4z3GN.js} +1 -1
- package/dist/packem_shared/{make-request-B9XjBynA.js → make-request-CDhxj-9b.js} +1 -1
- package/dist/packem_shared/{mandrillProvider-B84zH-eV.js → mandrillProvider-CAQeMtU_.js} +1 -1
- package/dist/packem_shared/{mockProvider-Behywbl1.js → mockProvider-EcpYlg-_.js} +1 -1
- package/dist/packem_shared/{netcoreProvider-D-wtCyJj.js → netcoreProvider-ua1avx07.js} +1 -1
- package/dist/packem_shared/{nodemailerProvider-BFHobXxt.js → nodemailerProvider-BZmQfKlM.js} +1 -1
- package/dist/packem_shared/{opentelemetryProvider-ByHC01ub.js → opentelemetryProvider-CAfWpywa.js} +1 -1
- package/dist/packem_shared/{outlook365Provider-Btk4Emig.js → outlook365Provider-SFYELGDr.js} +1 -1
- package/dist/packem_shared/{plunkProvider-Bw8e6460.js → plunkProvider-9amwuQri.js} +1 -1
- package/dist/packem_shared/{postalProvider-CT8zr89z.js → postalProvider-CeF3TOIW.js} +1 -1
- package/dist/packem_shared/{postmarkProvider-CQSqZWDs.js → postmarkProvider-BPgKEkgF.js} +1 -1
- package/dist/packem_shared/{provider-base-C7PuopYK.js → provider-base-B-xhQSqE.js} +1 -1
- package/dist/packem_shared/{provider.d-J-y6iogK.d.ts → provider.d-Cx5YQJdP.d.ts} +9 -9
- package/dist/packem_shared/{resendProvider-drJYlvLP.js → resendProvider-C9_sM8bH.js} +1 -1
- package/dist/packem_shared/{retry-ipI5DRJ8.js → retry-D1Rh-6Z4.js} +1 -1
- package/dist/packem_shared/{roundRobinProvider-D1by5KGW.js → roundRobinProvider-BPzLWZf-.js} +1 -1
- package/dist/packem_shared/{scalewayProvider-DU5gXQrl.js → scalewayProvider-DfC7275i.js} +1 -1
- package/dist/packem_shared/{sendGridProvider-BuTbEXW8.js → sendGridProvider-CUBBHBzs.js} +1 -1
- package/dist/packem_shared/smtpProvider-9nBSGtQl.js +27 -0
- package/dist/packem_shared/{sparkpostProvider-UAsFYIjP.js → sparkpostProvider-Be_d7S8o.js} +1 -1
- package/dist/packem_shared/{sweegoProvider-SUz0LIcA.js → sweegoProvider-CP1cNC-d.js} +1 -1
- package/dist/packem_shared/{tracer.d-MU42G1jG.d.ts → tracer.d-sb5yrt_n.d.ts} +2 -2
- package/dist/packem_shared/types.d-B0t3PQ3t.d.ts +107 -0
- package/dist/packem_shared/{types.d-ejzh-xBP.d.ts → types.d-B9295M4_.d.ts} +82 -82
- package/dist/packem_shared/types.d-BzoHR9nB.d.ts +61 -0
- package/dist/packem_shared/types.d-C5geVKes.d.ts +51 -0
- package/dist/packem_shared/types.d-GKqPNk0I.d.ts +24 -0
- package/dist/packem_shared/types.d-I-KeZ5w2.d.ts +9 -0
- package/dist/packem_shared/types.d-kHO4kX9q.d.ts +69 -0
- package/dist/packem_shared/utils-DjEtR3qT.js +1 -0
- package/dist/packem_shared/verifyMailgunWebhook-DNk080BF.js +1 -0
- package/dist/packem_shared/verifyPostmarkWebhook-B4OIEHQF.js +1 -0
- package/dist/packem_shared/verifyResendWebhook-C7E32LZ1.js +1 -0
- package/dist/packem_shared/verifySendGridWebhook-DtFMgBRP.js +1 -0
- package/dist/packem_shared/withEvents-CytsykaK.js +1 -0
- package/dist/packem_shared/{withSuppression-DBaZDMAr.js → withSuppression-wDl4NTb-.js} +1 -1
- package/dist/packem_shared/{zeptomailProvider-DXNX9mG_.js → zeptomailProvider-BZ0fK0Lk.js} +1 -1
- package/dist/providers/ahasend/index.d.ts +18 -18
- package/dist/providers/ahasend/index.js +1 -1
- package/dist/providers/autosend/index.d.ts +30 -30
- package/dist/providers/autosend/index.js +1 -1
- package/dist/providers/aws-ses/index.d.ts +20 -20
- package/dist/providers/aws-ses/index.js +1 -1
- package/dist/providers/azure/index.d.ts +26 -26
- package/dist/providers/azure/index.js +1 -1
- package/dist/providers/brevo/index.d.ts +35 -35
- package/dist/providers/brevo/index.js +1 -1
- package/dist/providers/cloudflare-email/index.d.ts +25 -25
- package/dist/providers/cloudflare-email/index.js +1 -1
- package/dist/providers/failover/index.d.ts +14 -14
- package/dist/providers/failover/index.js +1 -1
- package/dist/providers/http/index.d.ts +15 -15
- package/dist/providers/http/index.js +1 -1
- package/dist/providers/infobip/index.d.ts +28 -28
- package/dist/providers/infobip/index.js +1 -1
- package/dist/providers/loops/index.d.ts +25 -25
- package/dist/providers/loops/index.js +1 -1
- package/dist/providers/mailchannels/index.d.ts +13 -13
- package/dist/providers/mailchannels/index.js +1 -1
- package/dist/providers/mailcrab/index.d.ts +17 -17
- package/dist/providers/mailcrab/index.js +1 -1
- package/dist/providers/mailersend/index.d.ts +24 -24
- package/dist/providers/mailersend/index.js +1 -1
- package/dist/providers/mailgun/index.d.ts +37 -37
- package/dist/providers/mailgun/index.js +1 -1
- package/dist/providers/mailjet/index.d.ts +36 -36
- package/dist/providers/mailjet/index.js +1 -1
- package/dist/providers/mailomat/index.d.ts +20 -20
- package/dist/providers/mailomat/index.js +1 -1
- package/dist/providers/mailpace/index.d.ts +24 -24
- package/dist/providers/mailpace/index.js +1 -1
- package/dist/providers/mailtrap/index.d.ts +22 -22
- package/dist/providers/mailtrap/index.js +1 -1
- package/dist/providers/mandrill/index.d.ts +36 -36
- package/dist/providers/mandrill/index.js +1 -1
- package/dist/providers/mock/index.d.ts +8 -8
- package/dist/providers/mock/index.js +1 -1
- package/dist/providers/netcore/index.d.ts +17 -17
- package/dist/providers/netcore/index.js +1 -1
- package/dist/providers/nodemailer/index.d.ts +22 -22
- package/dist/providers/nodemailer/index.js +1 -1
- package/dist/providers/opentelemetry/index.d.ts +20 -20
- package/dist/providers/opentelemetry/index.js +1 -1
- package/dist/providers/outlook365/index.d.ts +82 -82
- package/dist/providers/outlook365/index.js +1 -1
- package/dist/providers/plunk/index.d.ts +18 -18
- package/dist/providers/plunk/index.js +1 -1
- package/dist/providers/postal/index.d.ts +24 -24
- package/dist/providers/postal/index.js +1 -1
- package/dist/providers/postmark/index.d.ts +30 -30
- package/dist/providers/postmark/index.js +1 -1
- package/dist/providers/resend/index.d.ts +24 -24
- package/dist/providers/resend/index.js +1 -1
- package/dist/providers/roundrobin/index.d.ts +14 -14
- package/dist/providers/roundrobin/index.js +1 -1
- package/dist/providers/scaleway/index.d.ts +22 -22
- package/dist/providers/scaleway/index.js +1 -1
- package/dist/providers/sendgrid/index.d.ts +25 -25
- package/dist/providers/sendgrid/index.js +1 -1
- package/dist/providers/smtp/index.d.ts +11 -11
- package/dist/providers/smtp/index.js +1 -1
- package/dist/providers/sparkpost/index.d.ts +21 -21
- package/dist/providers/sparkpost/index.js +1 -1
- package/dist/providers/sweego/index.d.ts +20 -20
- package/dist/providers/sweego/index.js +1 -1
- package/dist/providers/zeptomail/index.d.ts +17 -17
- package/dist/providers/zeptomail/index.js +1 -1
- package/dist/queue/bullmq-queue.d.ts +26 -26
- package/dist/queue/index.d.ts +86 -86
- package/dist/queue/pg-boss-queue.d.ts +13 -13
- package/dist/queue/sqs-queue.d.ts +20 -20
- package/dist/queue/unstorage-queue.d.ts +47 -47
- package/dist/queue/unstorage-queue.js +1 -1
- package/dist/render/cid.d.ts +12 -12
- package/dist/render/css-inline.d.ts +12 -12
- package/dist/render/css-inline.js +1 -1
- package/dist/render/dark-mode.d.ts +12 -12
- package/dist/render/preheader.d.ts +16 -16
- package/dist/template-engines/handlebars.d.ts +19 -19
- package/dist/template-engines/handlebars.js +1 -1
- package/dist/template-engines/html-to-text.d.ts +12 -12
- package/dist/template-engines/html-to-text.js +1 -1
- package/dist/template-engines/i18n.d.ts +43 -43
- package/dist/template-engines/i18n.js +1 -1
- package/dist/template-engines/jsx-email.d.ts +8 -8
- package/dist/template-engines/jsx-email.js +1 -1
- package/dist/template-engines/liquid.d.ts +9 -9
- package/dist/template-engines/liquid.js +1 -1
- package/dist/template-engines/mjml.d.ts +9 -9
- package/dist/template-engines/mjml.js +1 -1
- package/dist/template-engines/react-email.d.ts +8 -8
- package/dist/template-engines/react-email.js +1 -1
- package/dist/template-engines/vue-email.d.ts +8 -8
- package/dist/template-engines/vue-email.js +1 -1
- package/dist/test/index.d.ts +89 -89
- package/dist/test/index.js +1 -1
- package/dist/utils/cache.d.ts +27 -27
- package/dist/utils/format-email-address.d.ts +6 -6
- package/dist/utils/format-email-address.js +1 -1
- package/dist/utils/normalize-email-aliases.d.ts +19 -19
- package/dist/utils/parse-address.d.ts +16 -16
- package/dist/utils/parse-eml.d.ts +18 -18
- package/dist/utils/parse-eml.js +3 -3
- package/dist/utils/result.d.ts +30 -30
- package/dist/utils/result.js +1 -1
- package/dist/utils/validation/check-feature-support.d.ts +33 -33
- package/dist/utils/validation/validate-email.d.ts +4 -4
- package/dist/webhooks/index.d.ts +134 -134
- package/dist/webhooks/index.js +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/EmailError-B-sEf3bp.js +0 -1
- package/dist/packem_shared/Mail-CYAwMRnX.js +0 -1
- package/dist/packem_shared/MailMessage-DQRgs5Dz.js +0 -1
- package/dist/packem_shared/SmimeEncrypter-DavopRlE.js +0 -6
- package/dist/packem_shared/SmimeSigner-0onWksAv.js +0 -8
- package/dist/packem_shared/arcMessageSignatureBase-DDLEHW2E.js +0 -17
- package/dist/packem_shared/attachment-processor-CMp7qqMI.js +0 -1
- package/dist/packem_shared/azureProvider-Cw_Tmde6.js +0 -1
- package/dist/packem_shared/build-mime-message-BW5FQ2Bt.js +0 -3
- package/dist/packem_shared/dedupeMiddleware-B6ajWOTi.js +0 -1
- package/dist/packem_shared/event-bus.d-DEl3w_EW.d.ts +0 -104
- package/dist/packem_shared/generate-boundary-DQbzDiOI.js +0 -1
- package/dist/packem_shared/index-BoZvzveg.js +0 -11
- package/dist/packem_shared/isValidSigningCertUrl-Bii1AMGC.js +0 -3
- package/dist/packem_shared/mail.d-B9SSqyy0.d.ts +0 -909
- package/dist/packem_shared/mailgunProvider-D9HUWGKN.js +0 -1
- package/dist/packem_shared/mailjetProvider-DelLs2Vt.js +0 -1
- package/dist/packem_shared/smtpProvider-5MI3-EPh.js +0 -25
- package/dist/packem_shared/types.d-BId55FW2.d.ts +0 -107
- package/dist/packem_shared/types.d-CmoWvdZi.d.ts +0 -61
- package/dist/packem_shared/types.d-DCkecJse.d.ts +0 -51
- package/dist/packem_shared/types.d-Mpu0HZoG.d.ts +0 -24
- package/dist/packem_shared/types.d-lcJZmwRK.d.ts +0 -69
- package/dist/packem_shared/types.d-nyR1ty1Q.d.ts +0 -9
- package/dist/packem_shared/utils-BfYfPB_I.js +0 -1
- package/dist/packem_shared/verifyMailgunWebhook-Cwl0OD3P.js +0 -1
- package/dist/packem_shared/verifyPostmarkWebhook-C72ZvbrG.js +0 -1
- package/dist/packem_shared/verifyResendWebhook-YK2zNDXR.js +0 -1
- package/dist/packem_shared/verifySendGridWebhook-Dbwc1tfG.js +0 -1
- package/dist/packem_shared/withEvents-CCVblSqj.js +0 -1
|
@@ -1,246 +1,243 @@
|
|
|
1
|
-
import { M as Middleware } from "../packem_shared/types.d-
|
|
2
|
-
export { type S as SendFunction, c as composeMiddleware } from "../packem_shared/types.d-
|
|
3
|
-
import { E as EmailOptions, M as MaybePromise, a as EmailResult, R as Result, c as EmailAddress } from "../packem_shared/types.d-
|
|
4
|
-
import { d as EventBus } from "../packem_shared/event-bus.d-
|
|
5
|
-
import { b as SuppressionStore } from "../packem_shared/types.d-
|
|
6
|
-
import { T as Tracer } from "../packem_shared/tracer.d-
|
|
1
|
+
import { M as Middleware } from "../packem_shared/types.d-GKqPNk0I.js";
|
|
2
|
+
export { type S as SendFunction, c as composeMiddleware } from "../packem_shared/types.d-GKqPNk0I.js";
|
|
3
|
+
import { E as EmailOptions, M as MaybePromise, a as EmailResult, R as Result, c as EmailAddress } from "../packem_shared/types.d-B9295M4_.js";
|
|
4
|
+
import { d as EventBus } from "../packem_shared/event-bus.d-BNQA-FZE.js";
|
|
5
|
+
import { b as SuppressionStore } from "../packem_shared/types.d-BzoHR9nB.js";
|
|
6
|
+
import { T as Tracer } from "../packem_shared/tracer.d-sb5yrt_n.js";
|
|
7
7
|
import 'node:buffer';
|
|
8
8
|
/**
|
|
9
|
-
* The state of a {@link circuitBreakerMiddleware}.
|
|
10
|
-
*
|
|
11
|
-
* `closed` = healthy; `open` = failing fast; `half-open` = trialing one request to test recovery.
|
|
12
|
-
*/
|
|
9
|
+
* The state of a {@link circuitBreakerMiddleware}.
|
|
10
|
+
*
|
|
11
|
+
* `closed` = healthy; `open` = failing fast; `half-open` = trialing one request to test recovery.
|
|
12
|
+
*/
|
|
13
13
|
type CircuitState = "closed" | "half-open" | "open";
|
|
14
14
|
/**
|
|
15
|
-
* Options for the {@link circuitBreakerMiddleware}.
|
|
16
|
-
*/
|
|
15
|
+
* Options for the {@link circuitBreakerMiddleware}.
|
|
16
|
+
*/
|
|
17
17
|
interface CircuitBreakerMiddlewareOptions {
|
|
18
18
|
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
* Consecutive failures before the circuit opens.
|
|
20
|
+
* @default 5
|
|
21
|
+
*/
|
|
22
22
|
failureThreshold?: number;
|
|
23
23
|
/**
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
25
|
+
*/
|
|
26
26
|
now?: () => number;
|
|
27
27
|
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
* Notified whenever the circuit changes state.
|
|
29
|
+
* @param state The new state.
|
|
30
|
+
*/
|
|
31
31
|
onStateChange?: (state: CircuitState) => void;
|
|
32
32
|
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
* How long, in milliseconds, the circuit stays open before allowing a half-open trial.
|
|
34
|
+
* @default 30000
|
|
35
|
+
*/
|
|
36
36
|
resetTimeout?: number;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* Trips a circuit after repeated provider failures, failing fast while open and trialing recovery via
|
|
40
|
-
* a half-open state — protecting a struggling provider from being hammered.
|
|
41
|
-
* @param options Breaker configuration. See {@link CircuitBreakerMiddlewareOptions}.
|
|
42
|
-
* @returns A middleware that fails fast while the provider is unhealthy.
|
|
43
|
-
*/
|
|
39
|
+
* Trips a circuit after repeated provider failures, failing fast while open and trialing recovery via
|
|
40
|
+
* a half-open state — protecting a struggling provider from being hammered.
|
|
41
|
+
* @param options Breaker configuration. See {@link CircuitBreakerMiddlewareOptions}.
|
|
42
|
+
* @returns A middleware that fails fast while the provider is unhealthy.
|
|
43
|
+
*/
|
|
44
44
|
declare const circuitBreakerMiddleware: (options?: CircuitBreakerMiddlewareOptions) => Middleware;
|
|
45
45
|
/**
|
|
46
|
-
* Options for the {@link dedupeMiddleware}.
|
|
47
|
-
*/
|
|
46
|
+
* Options for the {@link dedupeMiddleware}.
|
|
47
|
+
*/
|
|
48
48
|
interface DedupeMiddlewareOptions {
|
|
49
49
|
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
* Derives the dedupe key for a message. Defaults to a content hash of recipients + subject + body.
|
|
51
|
+
* @param options The message being sent.
|
|
52
|
+
*/
|
|
53
53
|
keyFn?: (options: EmailOptions) => string;
|
|
54
54
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
56
|
+
*/
|
|
57
57
|
now?: () => number;
|
|
58
58
|
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
* How long, in milliseconds, a key is remembered.
|
|
60
|
+
* @default 60000
|
|
61
|
+
*/
|
|
62
62
|
ttl?: number;
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
* Suppresses duplicate sends of the same message within a TTL window, returning the original result
|
|
66
|
-
* for repeats instead of re-sending.
|
|
67
|
-
*
|
|
68
|
-
* Useful behind at-least-once delivery sources (queues, webhooks) that may replay a message.
|
|
69
|
-
* @param options Dedupe configuration. See {@link DedupeMiddlewareOptions}.
|
|
70
|
-
* @returns A middleware that drops duplicate sends within the TTL.
|
|
71
|
-
*/
|
|
65
|
+
* Suppresses duplicate sends of the same message within a TTL window, returning the original result
|
|
66
|
+
* for repeats instead of re-sending.
|
|
67
|
+
*
|
|
68
|
+
* Useful behind at-least-once delivery sources (queues, webhooks) that may replay a message.
|
|
69
|
+
* @param options Dedupe configuration. See {@link DedupeMiddlewareOptions}.
|
|
70
|
+
* @returns A middleware that drops duplicate sends within the TTL.
|
|
71
|
+
*/
|
|
72
72
|
declare const dedupeMiddleware: (options?: DedupeMiddlewareOptions) => Middleware;
|
|
73
73
|
/**
|
|
74
|
-
* Options for {@link withEvents}.
|
|
75
|
-
*/
|
|
74
|
+
* Options for {@link withEvents}.
|
|
75
|
+
*/
|
|
76
76
|
interface EventsMiddlewareOptions {
|
|
77
77
|
/**
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
* Generates event ids. Defaults to `crypto.randomUUID`.
|
|
79
|
+
*/
|
|
80
80
|
idFactory?: () => string;
|
|
81
81
|
/**
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
83
|
+
*/
|
|
84
84
|
now?: () => number;
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
|
-
* Emits unified `EmailEvent`s onto an {@link EventBus} around each send: `queued` before, then
|
|
88
|
-
* `sent` or `failed` after. Combine with webhook-derived events for a single timeline per message.
|
|
89
|
-
* @param bus The event bus to publish to.
|
|
90
|
-
* @param options Middleware options. See {@link EventsMiddlewareOptions}.
|
|
91
|
-
* @returns A middleware that publishes send-lifecycle events.
|
|
92
|
-
*/
|
|
87
|
+
* Emits unified `EmailEvent`s onto an {@link EventBus} around each send: `queued` before, then
|
|
88
|
+
* `sent` or `failed` after. Combine with webhook-derived events for a single timeline per message.
|
|
89
|
+
* @param bus The event bus to publish to.
|
|
90
|
+
* @param options Middleware options. See {@link EventsMiddlewareOptions}.
|
|
91
|
+
* @returns A middleware that publishes send-lifecycle events.
|
|
92
|
+
*/
|
|
93
93
|
declare const withEvents: (bus: EventBus, options?: EventsMiddlewareOptions) => Middleware;
|
|
94
94
|
/**
|
|
95
|
-
* Options for the {@link loggingMiddleware}.
|
|
96
|
-
*/
|
|
95
|
+
* Options for the {@link loggingMiddleware}.
|
|
96
|
+
*/
|
|
97
97
|
interface LoggingMiddlewareOptions {
|
|
98
98
|
/**
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
* The logger to write to.
|
|
100
|
+
* @default console
|
|
101
|
+
*/
|
|
102
102
|
logger?: Pick<Console, "error" | "info">;
|
|
103
103
|
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
* Redact recipient addresses (e.g. `j••@example.com`) to keep PII out of logs.
|
|
105
|
+
* @default true
|
|
106
|
+
*/
|
|
107
107
|
redact?: boolean;
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
|
-
* Logs each send attempt and its outcome, redacting recipient PII by default.
|
|
111
|
-
* @param options Logging configuration. See {@link LoggingMiddlewareOptions}.
|
|
112
|
-
* @returns A middleware that logs sends and their results.
|
|
113
|
-
*/
|
|
110
|
+
* Logs each send attempt and its outcome, redacting recipient PII by default.
|
|
111
|
+
* @param options Logging configuration. See {@link LoggingMiddlewareOptions}.
|
|
112
|
+
* @returns A middleware that logs sends and their results.
|
|
113
|
+
*/
|
|
114
114
|
declare const loggingMiddleware: (options?: LoggingMiddlewareOptions) => Middleware;
|
|
115
115
|
/**
|
|
116
|
-
* A minimal metrics sink — implement it with prom-client, OpenTelemetry metrics, StatsD, etc.
|
|
117
|
-
*/
|
|
116
|
+
* A minimal metrics sink — implement it with prom-client, OpenTelemetry metrics, StatsD, etc.
|
|
117
|
+
*/
|
|
118
118
|
interface MetricsRecorder {
|
|
119
119
|
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
* Increments a counter.
|
|
121
|
+
* @param metric The metric name.
|
|
122
|
+
* @param labels Optional labels/dimensions.
|
|
123
|
+
*/
|
|
124
124
|
increment: (metric: string, labels?: Record<string, string>) => void;
|
|
125
125
|
/**
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
* Records an observation (e.g. a duration) on a histogram/summary.
|
|
127
|
+
* @param metric The metric name.
|
|
128
|
+
* @param value The observed value.
|
|
129
|
+
* @param labels Optional labels/dimensions.
|
|
130
|
+
*/
|
|
131
131
|
observe: (metric: string, value: number, labels?: Record<string, string>) => void;
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
134
|
-
* Options for {@link withMetrics}.
|
|
135
|
-
*/
|
|
134
|
+
* Options for {@link withMetrics}.
|
|
135
|
+
*/
|
|
136
136
|
interface MetricsMiddlewareOptions {
|
|
137
137
|
/**
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
* Prefix for emitted metric names.
|
|
139
|
+
* @default "email_"
|
|
140
|
+
*/
|
|
141
141
|
prefix?: string;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
* Records per-send metrics (a `*_sent_total` counter and a `*_duration_ms` observation, labelled by
|
|
145
|
-
* provider and status) into an injected {@link MetricsRecorder}. Dependency-free — wire it to
|
|
146
|
-
* prom-client or any metrics backend.
|
|
147
|
-
* @param recorder The metrics sink.
|
|
148
|
-
* @param options Middleware options. See {@link MetricsMiddlewareOptions}.
|
|
149
|
-
* @returns A middleware that records send metrics.
|
|
150
|
-
*/
|
|
144
|
+
* Records per-send metrics (a `*_sent_total` counter and a `*_duration_ms` observation, labelled by
|
|
145
|
+
* provider and status) into an injected {@link MetricsRecorder}. Dependency-free — wire it to
|
|
146
|
+
* prom-client or any metrics backend.
|
|
147
|
+
* @param recorder The metrics sink.
|
|
148
|
+
* @param options Middleware options. See {@link MetricsMiddlewareOptions}.
|
|
149
|
+
* @returns A middleware that records send metrics.
|
|
150
|
+
*/
|
|
151
151
|
declare const withMetrics: (recorder: MetricsRecorder, options?: MetricsMiddlewareOptions) => Middleware;
|
|
152
152
|
/**
|
|
153
|
-
* A token that may carry an absolute expiry.
|
|
154
|
-
*/
|
|
153
|
+
* A token that may carry an absolute expiry.
|
|
154
|
+
*/
|
|
155
155
|
interface CacheableToken {
|
|
156
156
|
/**
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
* The bearer access token.
|
|
158
|
+
*/
|
|
159
159
|
accessToken: string;
|
|
160
160
|
/**
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
* Absolute expiry time in milliseconds since the epoch. Omit for non-expiring tokens.
|
|
162
|
+
*/
|
|
163
163
|
expiresAt?: number;
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
|
-
*
|
|
167
|
-
*/
|
|
168
|
-
/**
|
|
169
|
-
* An OAuth2 access token plus its expiry.
|
|
170
|
-
*/
|
|
166
|
+
* An OAuth2 access token plus its expiry.
|
|
167
|
+
*/
|
|
171
168
|
type OAuth2Token = CacheableToken;
|
|
172
169
|
/**
|
|
173
|
-
* Options for the {@link oauth2Middleware}.
|
|
174
|
-
*/
|
|
170
|
+
* Options for the {@link oauth2Middleware}.
|
|
171
|
+
*/
|
|
175
172
|
interface OAuth2MiddlewareOptions {
|
|
176
173
|
/**
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
174
|
+
* Fetches (or refreshes) the access token. Called only when the cached token is missing or within
|
|
175
|
+
* {@link OAuth2MiddlewareOptions.skewMs} of expiry. Wire this to your Gmail / Microsoft 365 refresh
|
|
176
|
+
* flow.
|
|
177
|
+
*/
|
|
181
178
|
fetchToken: () => Promise<OAuth2Token> | OAuth2Token;
|
|
182
179
|
/**
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
* The header to inject the credential into.
|
|
181
|
+
* @default "Authorization"
|
|
182
|
+
*/
|
|
186
183
|
headerName?: string;
|
|
187
184
|
/**
|
|
188
|
-
|
|
189
|
-
|
|
185
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
186
|
+
*/
|
|
190
187
|
now?: () => number;
|
|
191
188
|
/**
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
* Receives every freshly-acquired token — use it to feed SMTP XOAUTH2 or a provider client that
|
|
190
|
+
* authenticates outside the message headers.
|
|
191
|
+
* @param token The new token.
|
|
192
|
+
*/
|
|
196
193
|
onToken?: (token: OAuth2Token) => void;
|
|
197
194
|
/**
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
195
|
+
* The auth scheme prefix for the header value.
|
|
196
|
+
* @default "Bearer"
|
|
197
|
+
*/
|
|
201
198
|
scheme?: string;
|
|
202
199
|
/**
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
200
|
+
* Refresh this many milliseconds before the token actually expires.
|
|
201
|
+
* @default 60000
|
|
202
|
+
*/
|
|
206
203
|
skewMs?: number;
|
|
207
204
|
}
|
|
208
205
|
/**
|
|
209
|
-
* Injects an OAuth2 bearer credential into each outgoing message, refreshing it on demand and caching
|
|
210
|
-
* it until just before expiry.
|
|
211
|
-
*
|
|
212
|
-
* Supplies the token to provider clients (Gmail, Microsoft 365) either via a request header or the
|
|
213
|
-
* {@link OAuth2MiddlewareOptions.onToken} callback (for SMTP XOAUTH2).
|
|
214
|
-
* @param options OAuth2 configuration. See {@link OAuth2MiddlewareOptions}.
|
|
215
|
-
* @returns The middleware.
|
|
216
|
-
*/
|
|
206
|
+
* Injects an OAuth2 bearer credential into each outgoing message, refreshing it on demand and caching
|
|
207
|
+
* it until just before expiry.
|
|
208
|
+
*
|
|
209
|
+
* Supplies the token to provider clients (Gmail, Microsoft 365) either via a request header or the
|
|
210
|
+
* {@link OAuth2MiddlewareOptions.onToken} callback (for SMTP XOAUTH2).
|
|
211
|
+
* @param options OAuth2 configuration. See {@link OAuth2MiddlewareOptions}.
|
|
212
|
+
* @returns The middleware.
|
|
213
|
+
*/
|
|
217
214
|
declare const oauth2Middleware: (options: OAuth2MiddlewareOptions) => Middleware;
|
|
218
215
|
/**
|
|
219
|
-
* Options for the {@link rateLimitMiddleware}.
|
|
220
|
-
*/
|
|
216
|
+
* Options for the {@link rateLimitMiddleware}.
|
|
217
|
+
*/
|
|
221
218
|
interface RateLimitMiddlewareOptions {
|
|
222
219
|
/**
|
|
223
|
-
|
|
224
|
-
|
|
220
|
+
* Maximum burst capacity (tokens). Defaults to {@link RateLimitMiddlewareOptions.rate}.
|
|
221
|
+
*/
|
|
225
222
|
burst?: number;
|
|
226
223
|
/**
|
|
227
|
-
|
|
228
|
-
|
|
224
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
225
|
+
*/
|
|
229
226
|
now?: () => number;
|
|
230
227
|
/**
|
|
231
|
-
|
|
232
|
-
|
|
228
|
+
* Sustained send rate, in messages per second.
|
|
229
|
+
*/
|
|
233
230
|
rate: number;
|
|
234
231
|
/**
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
232
|
+
* Sleep implementation — injectable for tests. Defaults to `setTimeout`.
|
|
233
|
+
* @param ms Milliseconds to wait.
|
|
234
|
+
*/
|
|
238
235
|
sleep?: (ms: number) => Promise<void>;
|
|
239
236
|
}
|
|
240
237
|
/**
|
|
241
|
-
* Pre-tuned per-second rate presets for common providers' default plans. Override as needed for your
|
|
242
|
-
* own quota.
|
|
243
|
-
*/
|
|
238
|
+
* Pre-tuned per-second rate presets for common providers' default plans. Override as needed for your
|
|
239
|
+
* own quota.
|
|
240
|
+
*/
|
|
244
241
|
declare const RATE_LIMIT_PRESETS: {
|
|
245
242
|
readonly "aws-ses": 14;
|
|
246
243
|
readonly mailgun: 100;
|
|
@@ -249,106 +246,106 @@ declare const RATE_LIMIT_PRESETS: {
|
|
|
249
246
|
readonly sendgrid: 100;
|
|
250
247
|
};
|
|
251
248
|
/**
|
|
252
|
-
* Throttles sends with a token-bucket limiter, awaiting capacity rather than failing when the rate is
|
|
253
|
-
* exceeded.
|
|
254
|
-
* @param options Rate configuration. See {@link RateLimitMiddlewareOptions} and {@link RATE_LIMIT_PRESETS}.
|
|
255
|
-
* @returns A middleware that paces sends to the configured rate.
|
|
256
|
-
*/
|
|
249
|
+
* Throttles sends with a token-bucket limiter, awaiting capacity rather than failing when the rate is
|
|
250
|
+
* exceeded.
|
|
251
|
+
* @param options Rate configuration. See {@link RateLimitMiddlewareOptions} and {@link RATE_LIMIT_PRESETS}.
|
|
252
|
+
* @returns A middleware that paces sends to the configured rate.
|
|
253
|
+
*/
|
|
257
254
|
declare const rateLimitMiddleware: (options: RateLimitMiddlewareOptions) => Middleware;
|
|
258
255
|
/**
|
|
259
|
-
* Wraps a transform that rewrites the message before it is sent — e.g. running the HTML through the
|
|
260
|
-
* render helpers (preheader, dark-mode, CID rewrite) and the opt-in CSS inliner.
|
|
261
|
-
* @param transform Maps the resolved {@link EmailOptions} to its rendered form.
|
|
262
|
-
* @returns A middleware that applies the transform ahead of the provider call.
|
|
263
|
-
* @example
|
|
264
|
-
* ```ts
|
|
265
|
-
* import { injectPreheader } from "@visulima/email/render/preheader";
|
|
266
|
-
* import { addDarkModeSupport } from "@visulima/email/render/dark-mode";
|
|
267
|
-
*
|
|
268
|
-
* mail.use(withRender(async (email) => ({
|
|
269
|
-
* ...email,
|
|
270
|
-
* html: email.html ? addDarkModeSupport(injectPreheader(email.html, "Hi!")) : email.html,
|
|
271
|
-
* })));
|
|
272
|
-
* ```
|
|
273
|
-
*/
|
|
256
|
+
* Wraps a transform that rewrites the message before it is sent — e.g. running the HTML through the
|
|
257
|
+
* render helpers (preheader, dark-mode, CID rewrite) and the opt-in CSS inliner.
|
|
258
|
+
* @param transform Maps the resolved {@link EmailOptions} to its rendered form.
|
|
259
|
+
* @returns A middleware that applies the transform ahead of the provider call.
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* import { injectPreheader } from "@visulima/email/render/preheader";
|
|
263
|
+
* import { addDarkModeSupport } from "@visulima/email/render/dark-mode";
|
|
264
|
+
*
|
|
265
|
+
* mail.use(withRender(async (email) => ({
|
|
266
|
+
* ...email,
|
|
267
|
+
* html: email.html ? addDarkModeSupport(injectPreheader(email.html, "Hi!")) : email.html,
|
|
268
|
+
* })));
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
274
271
|
declare const withRender: (transform: (options: EmailOptions) => MaybePromise<EmailOptions>) => Middleware;
|
|
275
272
|
/**
|
|
276
|
-
* Options for the {@link retryMiddleware}.
|
|
277
|
-
*/
|
|
273
|
+
* Options for the {@link retryMiddleware}.
|
|
274
|
+
*/
|
|
278
275
|
interface RetryMiddlewareOptions {
|
|
279
276
|
/**
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
277
|
+
* The base backoff delay in milliseconds. Actual delays grow exponentially and are jittered.
|
|
278
|
+
* @default 200
|
|
279
|
+
*/
|
|
283
280
|
baseDelay?: number;
|
|
284
281
|
/**
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
282
|
+
* Called when all retries are exhausted — a dead-letter hook for durable storage/alerting.
|
|
283
|
+
* @param options The message that ultimately failed.
|
|
284
|
+
* @param result The final failed result.
|
|
285
|
+
*/
|
|
289
286
|
onDeadLetter?: (options: EmailOptions, result: Result<EmailResult>) => Promise<void> | void;
|
|
290
287
|
/**
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
288
|
+
* Maximum number of attempts (including the first).
|
|
289
|
+
* @default 3
|
|
290
|
+
*/
|
|
294
291
|
retries?: number;
|
|
295
292
|
/**
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
293
|
+
* Decides whether a failed result is retryable. Defaults to retrying every failure.
|
|
294
|
+
* @param result The failed result.
|
|
295
|
+
*/
|
|
299
296
|
shouldRetry?: (result: Result<EmailResult>) => boolean;
|
|
300
297
|
/**
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
298
|
+
* Sleep implementation — injectable for tests. Defaults to `setTimeout`.
|
|
299
|
+
* @param ms Milliseconds to wait.
|
|
300
|
+
*/
|
|
304
301
|
sleep?: (ms: number) => Promise<void>;
|
|
305
302
|
}
|
|
306
303
|
/**
|
|
307
|
-
* Retries failed sends with full-jitter exponential backoff, optionally dead-lettering the final
|
|
308
|
-
* failure.
|
|
309
|
-
*
|
|
310
|
-
* Full jitter (`random(0, base * 2^attempt)`) avoids the thundering-herd retries a fixed schedule
|
|
311
|
-
* causes.
|
|
312
|
-
* @param options Retry configuration. See {@link RetryMiddlewareOptions}.
|
|
313
|
-
* @returns A middleware that re-attempts failed sends before giving up.
|
|
314
|
-
*/
|
|
304
|
+
* Retries failed sends with full-jitter exponential backoff, optionally dead-lettering the final
|
|
305
|
+
* failure.
|
|
306
|
+
*
|
|
307
|
+
* Full jitter (`random(0, base * 2^attempt)`) avoids the thundering-herd retries a fixed schedule
|
|
308
|
+
* causes.
|
|
309
|
+
* @param options Retry configuration. See {@link RetryMiddlewareOptions}.
|
|
310
|
+
* @returns A middleware that re-attempts failed sends before giving up.
|
|
311
|
+
*/
|
|
315
312
|
declare const retryMiddleware: (options?: RetryMiddlewareOptions) => Middleware;
|
|
316
313
|
/**
|
|
317
|
-
* Options for {@link withSuppression}.
|
|
318
|
-
*/
|
|
314
|
+
* Options for {@link withSuppression}.
|
|
315
|
+
*/
|
|
319
316
|
interface SuppressionMiddlewareOptions {
|
|
320
317
|
/**
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
318
|
+
* Called with the recipients that were removed because they are suppressed.
|
|
319
|
+
* @param suppressed The dropped recipients.
|
|
320
|
+
*/
|
|
324
321
|
onSuppressed?: (suppressed: EmailAddress[]) => void;
|
|
325
322
|
}
|
|
326
323
|
/**
|
|
327
|
-
* Filters suppressed recipients out of the `to` list before sending, and short-circuits with a failed
|
|
328
|
-
* result when every recipient is suppressed.
|
|
329
|
-
* @param store The suppression store to check against.
|
|
330
|
-
* @param options Middleware options. See {@link SuppressionMiddlewareOptions}.
|
|
331
|
-
* @returns A middleware that enforces the suppression list.
|
|
332
|
-
*/
|
|
324
|
+
* Filters suppressed recipients out of the `to` list before sending, and short-circuits with a failed
|
|
325
|
+
* result when every recipient is suppressed.
|
|
326
|
+
* @param store The suppression store to check against.
|
|
327
|
+
* @param options Middleware options. See {@link SuppressionMiddlewareOptions}.
|
|
328
|
+
* @returns A middleware that enforces the suppression list.
|
|
329
|
+
*/
|
|
333
330
|
declare const withSuppression: (store: SuppressionStore, options?: SuppressionMiddlewareOptions) => Middleware;
|
|
334
331
|
/**
|
|
335
|
-
* Options for {@link withTelemetry}.
|
|
336
|
-
*/
|
|
332
|
+
* Options for {@link withTelemetry}.
|
|
333
|
+
*/
|
|
337
334
|
interface TelemetryMiddlewareOptions {
|
|
338
335
|
/**
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
336
|
+
* The span name.
|
|
337
|
+
* @default "email.send"
|
|
338
|
+
*/
|
|
342
339
|
spanName?: string;
|
|
343
340
|
}
|
|
344
341
|
/**
|
|
345
|
-
* Wraps each send in an OpenTelemetry span, recording the provider, recipient count and outcome.
|
|
346
|
-
*
|
|
347
|
-
* The `@opentelemetry/api` `Tracer` is injected (type-only import here), so this middleware adds no
|
|
348
|
-
* runtime dependency — pass `trace.getTracer("email")` from your instrumented app.
|
|
349
|
-
* @param tracer An OpenTelemetry `Tracer`.
|
|
350
|
-
* @param options Middleware options. See {@link TelemetryMiddlewareOptions}.
|
|
351
|
-
* @returns A middleware that traces sends.
|
|
352
|
-
*/
|
|
342
|
+
* Wraps each send in an OpenTelemetry span, recording the provider, recipient count and outcome.
|
|
343
|
+
*
|
|
344
|
+
* The `@opentelemetry/api` `Tracer` is injected (type-only import here), so this middleware adds no
|
|
345
|
+
* runtime dependency — pass `trace.getTracer("email")` from your instrumented app.
|
|
346
|
+
* @param tracer An OpenTelemetry `Tracer`.
|
|
347
|
+
* @param options Middleware options. See {@link TelemetryMiddlewareOptions}.
|
|
348
|
+
* @returns A middleware that traces sends.
|
|
349
|
+
*/
|
|
353
350
|
declare const withTelemetry: (tracer: Tracer, options?: TelemetryMiddlewareOptions) => Middleware;
|
|
354
351
|
export { type CircuitBreakerMiddlewareOptions, type CircuitState, type DedupeMiddlewareOptions, type EventsMiddlewareOptions, type LoggingMiddlewareOptions, type MetricsMiddlewareOptions, type MetricsRecorder, type Middleware, type OAuth2MiddlewareOptions, type OAuth2Token, RATE_LIMIT_PRESETS, type RateLimitMiddlewareOptions, type RetryMiddlewareOptions, type SuppressionMiddlewareOptions, type TelemetryMiddlewareOptions, circuitBreakerMiddleware, dedupeMiddleware, loggingMiddleware, oauth2Middleware, rateLimitMiddleware, retryMiddleware, withEvents, withMetrics, withRender, withSuppression, withTelemetry };
|
package/dist/middleware/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{circuitBreakerMiddleware as o}from"../packem_shared/circuitBreakerMiddleware-
|
|
1
|
+
import{circuitBreakerMiddleware as o}from"../packem_shared/circuitBreakerMiddleware-BSCPR72q.js";import{dedupeMiddleware as i}from"../packem_shared/dedupeMiddleware-CYYI_O7S.js";import{withEvents as p}from"../packem_shared/withEvents-CytsykaK.js";import{loggingMiddleware as f}from"../packem_shared/loggingMiddleware-CZIiVMVp.js";import{withMetrics as w}from"../packem_shared/withMetrics-DWywX_6M.js";import{oauth2Middleware as l}from"../packem_shared/oauth2Middleware-DQh-hIkv.js";import{RATE_LIMIT_PRESETS as h,rateLimitMiddleware as s}from"../packem_shared/RATE_LIMIT_PRESETS-BPADLgcA.js";import{default as c}from"../packem_shared/withRender-VP9wE5Yr.js";import{retryMiddleware as E}from"../packem_shared/retryMiddleware-DbViDX4r.js";import{withSuppression as g}from"../packem_shared/withSuppression-wDl4NTb-.js";import{withTelemetry as S}from"../packem_shared/withTelemetry-DL2qo0Hp.js";import{composeMiddleware as I}from"../packem_shared/composeMiddleware-BHwLLEzK.js";export{h as RATE_LIMIT_PRESETS,o as circuitBreakerMiddleware,I as composeMiddleware,i as dedupeMiddleware,f as loggingMiddleware,l as oauth2Middleware,s as rateLimitMiddleware,E as retryMiddleware,p as withEvents,w as withMetrics,c as withRender,g as withSuppression,S as withTelemetry};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{createRequire as j}from"node:module";import{
|
|
2
|
-
`)},
|
|
1
|
+
import{createRequire as j}from"node:module";import{q as M}from"./index-y0s2wQdc.js";import{s as x}from"./headers-to-record-De1Eg951.js";let b;const C=o=>(b??=j(import.meta.url))(o),p=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,_=o=>{if(typeof p<"u"&&p.versions&&p.versions.node){const[e,t]=p.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return p.getBuiltinModule(o)}return C(o)},{createHash:h,createPrivateKey:w,sign:T,createSign:v}=_("node:crypto"),q=(o,e="simple")=>{const t=[];for(const[s,a]of Object.entries(o)){const n=e==="relaxed"?s.toLowerCase().trim():s,r=e==="relaxed"?a.replaceAll(/\s+/g," ").trim():a;t.push(`${n}:${r}`)}return t.join(`\r
|
|
2
|
+
`)},I=(o,e="simple")=>{if(e==="simple"){const n=o.replace(/(\r\n|\r|\n)$/,`
|
|
3
3
|
`);let r=n.length;for(;r>0&&n[r-1]===`
|
|
4
4
|
`;)r-=1;const l=n.slice(0,r);return l?`${l}
|
|
5
5
|
`:`
|
|
@@ -11,8 +11,8 @@ import{createRequire as j}from"node:module";import{z as M}from"./index-BoZvzveg.
|
|
|
11
11
|
`);let s=t.length;for(;s>0&&t[s-1]===`
|
|
12
12
|
`;)s-=1;const a=t.slice(0,s);return a?`${a}
|
|
13
13
|
`:`
|
|
14
|
-
`},
|
|
14
|
+
`},K=(o,e,t)=>{const s=e.headerCanon??"simple",a=e.bodyCanon??"simple",n=Object.keys(o).filter(r=>!e.headersToIgnore?.some(l=>l.toLowerCase()===r.toLowerCase())).map(r=>r.toLowerCase()).join(":");return["v=1",`a=${e.algorithm??"rsa-sha256"}`,`c=${s}/${a}`,`d=${e.domainName}`,`s=${e.keySelector}`,`h=${n}`,`bh=${t}`,"b="].join("; ")},R=(o,e,t)=>t==="ed25519-sha256"?T(null,h("sha256").update(o).digest(),e).toString("base64"):v("RSA-SHA256").update(o).sign(e,"base64");class i{static sanitizeDisplayName(e){let t=e.replaceAll(/[\r\n\t]+/g," ");t=[...t].filter(n=>{const r=n.codePointAt(0);return r===void 0?!1:r>=32&&r<=126||r>159}).join("");const s="\\",a='"';return t=t.replaceAll(s,s+s).replaceAll(a,s+a),t=t.trim().replaceAll(/\s+/g," "),t}static formatAddress(e){if(e.name){const t=i.sanitizeDisplayName(e.name);return t?`"${t}" <${e.email}>`:e.email}return e.email}static formatAddresses(e){return(Array.isArray(e)?e:[e]).map(t=>i.formatAddress(t)).join(", ")}options;constructor(e){this.options=e}async sign(e){let t=this.options.privateKey;if(t.startsWith("file://")){const c=t.slice(7);t=await M(c,{encoding:"utf8"})}const s={...e.headers?x(e.headers):{},From:i.formatAddress(e.from),To:i.formatAddresses(e.to)};e.cc&&(s.Cc=i.formatAddresses(e.cc)),e.replyTo&&(s["Reply-To"]=i.formatAddress(e.replyTo)),s.Subject=e.subject,s["MIME-Version"]="1.0";const a=[];e.text&&a.push(e.text),e.html&&a.push(e.html);const n=a.join(`
|
|
15
15
|
|
|
16
|
-
`),r=this.options.headerCanon??"simple",l=this.options.bodyCanon??"simple",u=
|
|
17
|
-
DKIM-Signature: ${m}`;let d;try{const c=w({key:t,passphrase:this.options.passphrase});d=
|
|
18
|
-
`)??d,A={...s,"DKIM-Signature":`${m}${
|
|
16
|
+
`),r=this.options.headerCanon??"simple",l=this.options.bodyCanon??"simple",u=q(s,r),f=I(n,l),g=h("sha256").update(f).digest("base64"),m=K(s,this.options,g),y=`${u}\r
|
|
17
|
+
DKIM-Signature: ${m}`;let d;try{const c=w({key:t,passphrase:this.options.passphrase});d=R(y,c,this.options.algorithm)}catch(c){throw new Error(`Failed to create DKIM signature: ${c.message}`)}const $=d.match(/.{1,72}/g)?.join(`\r
|
|
18
|
+
`)??d,A={...s,"DKIM-Signature":`${m}${$}`};return{...e,headers:A}}}const z=o=>new i(o);export{i as DkimSigner,z as createDkimSigner};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import s from"./MailMessage-
|
|
1
|
+
import s from"./MailMessage-BRBT4Jea.js";class r extends s{constructor(){super(),this.header("X-Unsent","1")}}export{r as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class h extends Error{loc;title;hint;type="VisulimaError";constructor({cause:t,hint:e,location:s,message:a,name:c,stack:o,title:n}){super(a,{cause:t}),this.title=n,this.name=c,this.stack=o??this.stack,this.loc=s,this.hint=e}setLocation(t){this.loc=t}setName(t){this.name=t}setMessage(t){this.message=t}setHint(t){this.hint=t}}let l=class extends h{component;code;constructor(t,e,s){super({cause:s?.cause,hint:s?.hint,message:`[@visulima/email] [${t}] ${e}`,name:"EmailError",title:`Email ${t} Error`}),this.component=t,this.code=s?.code}};export{l as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import h from"./DraftMailMessage-BgP1OF1G.js";import v from"./EmailError-2CCyVX1S.js";import f from"./MailMessage-BRBT4Jea.js";import{composeMiddleware as C}from"./composeMiddleware-BHwLLEzK.js";import{j as w}from"./build-mime-message-t8KYiQkO.js";import{c as M}from"./create-logger-BQTS3f-I.js";import{s as g}from"./headers-to-record-De1Eg951.js";import T from"../utils/validation/check-feature-support.js";const S=(i,e,s)=>{e.success&&e.data?i&&i.info("Email sent successfully",{messageId:e.data.messageId,provider:e.data.provider}):i&&i.error("Email send failed",{error:e.error,provider:s})},j=async(i,e,s)=>{const r={...i,to:e.to};return e.cc&&(r.cc=e.cc),e.bcc&&(r.bcc=e.bcc),e.replyTo&&(r.replyTo=e.replyTo),e.headers&&(r.headers={...g(i.headers??{}),...g(e.headers)}),r.subject=e.subject??i.subject,s&&e.data&&(r.subject=await s(r.subject,e.data),i.html!==void 0&&(r.html=await s(i.html,e.data)),i.text!==void 0&&(r.text=await s(i.text,e.data))),r};class u{static extractErrorMessages(e){return e instanceof Error?[e.message]:[String(e??"Unknown error")]}provider;logger;loggerInstance;globalConfig;featureCheck;middlewares=[];composedSend;mountedProviders=new Map;constructor(e,s){this.provider=e,this.featureCheck=s?.featureCheck??"error"}setLogger(e){return this.loggerInstance=e,this.logger=M("Mail",e),this}use(e){return this.middlewares.push(e),this.composedSend=void 0,this}mount(e,s){return this.mountedProviders.set(e,s),this}setFrom(e){return this.globalConfig??={},this.globalConfig.from=e,this.logger&&this.logger.debug("Default from address updated",{from:e.email}),this}setReplyTo(e){return this.globalConfig??={},this.globalConfig.replyTo=e,this.logger&&this.logger.debug("Default reply-to address updated",{replyTo:e.email}),this}setHeaders(e){if(this.globalConfig??={},this.globalConfig.headers=e,this.logger){const s=g(e);this.logger.debug("Default headers updated",{count:Object.keys(s).length,headers:Object.keys(s)})}return this}async draft(e){let s=e instanceof f||e instanceof h?await this.buildDraftFromMessage(e):await this.buildDraftFromOptions(e);s=this.applyGlobalConfig(s);const r=s.headers?g(s.headers):{};s.headers={...r,"X-Unsent":"1"};const t=await w(s,{includeBcc:!0});return this.logger&&this.logger.debug("Draft created successfully in EML format",{from:s.from.email,size:t.length,subject:s.subject,to:Array.isArray(s.to)?s.to.length:1}),t}async send(e){if(e instanceof h)throw new TypeError("Cannot send draft messages. Convert to MailMessage first or remove X-Unsent header.");let s;if(e instanceof f)this.logger&&this.logger.debug("Sending MailMessage instance"),this.loggerInstance&&e.setLogger(this.loggerInstance),s=await e.build();else{const o=e;this.logger&&this.logger.debug("Sending email with options",{subject:o.subject,to:Array.isArray(o.to)?o.to.length:1}),s=o}s=this.applyGlobalConfig(s);const r=this.assertFeatureSupport(s,this.resolveProvider(s));if(r)return{error:r,success:!1};const t=await this.dispatch(s);return S(this.logger,t,this.provider.name??"unknown"),t}sendMany(e,s){const r=Math.max(1,Math.floor(s?.concurrency??1));return r===1?this.sendManySerial(e,s?.signal):this.sendManyConcurrent(e,r,s?.signal)}sendBatch(e,s,r){const t=async function*(){const o=e instanceof f?await e.build():e;for(const a of s)yield await j(o,a,r?.render)};return this.sendMany(t(),{concurrency:r?.concurrency,signal:r?.signal})}async sendOneToReceipt(e){const s=this.provider.name;try{const r=await this.send(e);return r.success&&r.data?{messageId:r.data.messageId,provider:r.data.provider??s,response:r.data.response,successful:!0,timestamp:r.data.timestamp}:{errorMessages:u.extractErrorMessages(r.error),provider:s,successful:!1}}catch(r){return{errorMessages:u.extractErrorMessages(r),provider:s,successful:!1}}}async*sendManySerial(e,s){const r=this.provider.name;let t=0,o=0,a=0;this.logger&&this.logger.debug("Starting batch email send",{provider:r});for await(const l of e){if(l instanceof h)throw new TypeError("Cannot send draft messages. Convert to MailMessage first or remove X-Unsent header.");if(s?.aborted){this.logger&&this.logger.warn("Batch send operation was aborted",{failed:a,processed:t,successful:o}),yield{errorMessages:["Send operation was aborted"],provider:r,successful:!1};return}t+=1;const n=await this.sendOneToReceipt(l);n.successful?o+=1:a+=1,yield n}this.logger&&this.logger.debug("Batch email send completed",{failureCount:a,processedCount:t,provider:r,successCount:o})}async*sendManyConcurrent(e,s,r){const t=this.provider.name;this.logger&&this.logger.debug("Starting concurrent batch email send",{concurrency:s,provider:t});const o=Symbol.asyncIterator in e?e[Symbol.asyncIterator]():e[Symbol.iterator](),a=new Map;let l=0,n=!1,p=!1;const m=async()=>{for(;!n&&!p&&a.size<s;){const d=await o.next();if(d.done){n=!0;break}const c=d.value;if(c instanceof h)throw new TypeError("Cannot send draft messages. Convert to MailMessage first or remove X-Unsent header.");const b=l;l+=1,a.set(b,this.sendOneToReceipt(c).then(y=>({id:b,receipt:y})))}};for(await m();a.size>0;){if(r?.aborted){p=!0,yield{errorMessages:["Send operation was aborted"],provider:t,successful:!1};return}const{id:d,receipt:c}=await Promise.race(a.values());a.delete(d),yield c,await m()}this.logger&&this.logger.debug("Concurrent batch email send completed",{processedCount:l,provider:t})}async dispatch(e){return this.middlewares.length===0?await this.resolveProvider(e).sendEmail(e):(this.composedSend??=C(this.middlewares,s=>Promise.resolve(this.resolveProvider(s).sendEmail(s))),await this.composedSend(e))}resolveProvider(e){return e.stream!==void 0?this.mountedProviders.get(e.stream)??this.provider:this.provider}assertFeatureSupport(e,s){if(this.featureCheck==="off")return;const{supported:r,violations:t}=T(e,s.features);if(r)return;const o=s.name??"unknown",a=t.map(n=>n.field),l=t.map(n=>n.message);if(this.featureCheck==="warn"){this.logger&&this.logger.warn("Message uses capabilities the provider does not support",{fields:a,provider:o});return}return this.logger&&this.logger.error("Message rejected by capability guard",{fields:a,provider:o}),new v(o,`Provider does not support the following message fields: ${a.join(", ")}`,{code:"UNSUPPORTED_FEATURES",hint:l})}async buildDraftFromMessage(e){return this.logger&&this.logger.debug("Creating draft from MailMessage instance"),this.loggerInstance&&e.setLogger(this.loggerInstance),this.applyGlobalConfigToMessage(e),await e.build()}async buildDraftFromOptions(e){return this.logger&&this.logger.debug("Creating draft from email options",{subject:e.subject,to:Array.isArray(e.to)?e.to.length:1}),e}applyGlobalConfigToMessage(e){const s=this.globalConfig?.from;s&&!e.getFrom()&&e.from(s);const r=this.globalConfig?.replyTo;if(r&&!e.getReplyTo()&&e.replyTo(r),this.globalConfig?.headers){const t=g(this.globalConfig.headers);Object.entries(t).forEach(([o,a])=>{e.header(o,a)})}}applyGlobalConfig(e){if(!this.globalConfig)return e;const s={...e};if(!s.from&&this.globalConfig.from&&(s.from=this.globalConfig.from,this.logger&&this.logger.debug("Applied global from address",{from:this.globalConfig.from.email})),!s.replyTo&&this.globalConfig.replyTo&&(s.replyTo=this.globalConfig.replyTo,this.logger&&this.logger.debug("Applied global reply-to address",{replyTo:this.globalConfig.replyTo.email})),this.globalConfig.headers){const r=g(this.globalConfig.headers),t=s.headers?g(s.headers):{};s.headers={...r,...t},this.logger&&this.logger.debug("Merged global headers",{globalCount:Object.keys(r).length,messageCount:Object.keys(t).length})}return s}}const F=(i,e)=>new u(i,e);export{u as Mail,F as createMail};
|