@visulima/email 1.0.0-alpha.34 → 1.0.0-alpha.35
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 +19 -0
- package/README.md +77 -0
- package/dist/crypto/index.d.ts +160 -3
- package/dist/crypto/index.js +1 -1
- package/dist/deliverability/dmarc-report.d.ts +95 -0
- package/dist/deliverability/dmarc-report.js +1 -0
- package/dist/deliverability/index.d.ts +360 -0
- package/dist/deliverability/index.js +1 -0
- package/dist/events/index.d.ts +31 -0
- package/dist/events/index.js +1 -0
- package/dist/inbound/index.d.ts +375 -0
- package/dist/inbound/index.js +1 -0
- package/dist/index.d.ts +11 -734
- package/dist/index.js +1 -1
- package/dist/middleware/index.d.ts +346 -0
- package/dist/middleware/index.js +1 -0
- package/dist/packem_shared/ALL_EVENTS-A0nTVOo0.js +1 -0
- package/dist/packem_shared/DkimSigner-dKZ45Csc.js +18 -0
- package/dist/packem_shared/Mail-B2QII2P9.js +1 -0
- package/dist/packem_shared/{MailMessage-BvaH5tZZ.js → MailMessage-DB1zaWfM.js} +1 -1
- package/dist/packem_shared/MemoryEventStore-BEKPxa-I.js +1 -0
- package/dist/packem_shared/MemoryQueue-C-CtRRG7.js +1 -0
- package/dist/packem_shared/MemorySuppressionStore-BKY1FrA1.js +1 -0
- package/dist/packem_shared/RATE_LIMIT_PRESETS-DQF78mdO.js +1 -0
- package/dist/packem_shared/{SmimeEncrypter-ZhHEgDwY.js → SmimeEncrypter-BirIsrip.js} +2 -2
- package/dist/packem_shared/{SmimeSigner-CYSVF6ez.js → SmimeSigner-CkyaShTs.js} +2 -2
- package/dist/packem_shared/addDarkModeSupport-Ys9U2-GH.js +1 -0
- package/dist/packem_shared/address-formatter-CnPg51_n.js +1 -0
- package/dist/packem_shared/ahaSendProvider-yuqYMW0n.js +1 -0
- package/dist/packem_shared/arcMessageSignatureBase-Cpdnv-H8.js +17 -0
- package/dist/packem_shared/attachment-processor-CFUC3V45.js +1 -0
- package/dist/packem_shared/azureProvider-CK_Wuw4r.js +1 -0
- package/dist/packem_shared/brevoProvider-CNwuzzBA.js +1 -0
- package/dist/packem_shared/build-mime-message-D8WEZejb.js +3 -0
- package/dist/packem_shared/buildListUnsubscribe-CIbz0rtk.js +1 -0
- package/dist/packem_shared/circuitBreakerMiddleware-B7DlzZSG.js +1 -0
- package/dist/packem_shared/cloudflareEmailProvider-C-G821Hg.js +1 -0
- package/dist/packem_shared/composeMiddleware-CkEhbDjL.js +1 -0
- package/dist/packem_shared/createTestEmail-hHdtgmUM.js +1 -0
- package/dist/packem_shared/createWorker-Nkc1GHet.js +1 -0
- package/dist/packem_shared/dedupeMiddleware-JeJbff46.js +1 -0
- package/dist/packem_shared/{detectMimeType-bo5oxfnt.js → detectMimeType-B4QMh7k8.js} +1 -1
- package/dist/packem_shared/emailMatchers-CLANeU71.js +1 -0
- package/dist/packem_shared/event-bus.d-DEl3w_EW.d.ts +104 -0
- package/dist/packem_shared/extractReply-CCWnNRWe.js +5 -0
- package/dist/packem_shared/filterSuppressed-DntqRV0q.js +1 -0
- package/dist/packem_shared/format-address-Cv6uWTS5.js +1 -0
- package/dist/packem_shared/infobipProvider-DdV62IAG.js +1 -0
- package/dist/packem_shared/injectPreheader-BxPjb0eJ.js +1 -0
- package/dist/packem_shared/inlineCss-BLaEi337.js +1 -0
- package/dist/packem_shared/isValidSigningCertUrl-CF_KuCAi.js +3 -0
- package/dist/packem_shared/loggingMiddleware-CyHzn37U.js +1 -0
- package/dist/packem_shared/loopsProvider-DSedSU3q.js +1 -0
- package/dist/packem_shared/mail.d-LmrdSngG.d.ts +861 -0
- package/dist/packem_shared/{mailCrabProvider-B7H6HwWu.js → mailCrabProvider-xSLhA1CY.js} +1 -1
- package/dist/packem_shared/mailPaceProvider-CWBIjvvJ.js +1 -0
- package/dist/packem_shared/mailchannelsProvider-zKcunGDQ.js +1 -0
- package/dist/packem_shared/mailerSendProvider-BEvPlBKB.js +1 -0
- package/dist/packem_shared/mailgunProvider-CfQAINTC.js +1 -0
- package/dist/packem_shared/mailjetProvider-DEfKptWc.js +1 -0
- package/dist/packem_shared/mailomatProvider-D5sHlxZh.js +1 -0
- package/dist/packem_shared/mailtrapProvider-DwgMKakk.js +1 -0
- package/dist/packem_shared/mandrillProvider-CdGjO3Td.js +1 -0
- package/dist/packem_shared/normalizeMessageId-B_9mXlh4.js +1 -0
- package/dist/packem_shared/oauth2Middleware-B1xz58iP.js +1 -0
- package/dist/packem_shared/parseAddress-CrYOac3K.js +1 -0
- package/dist/packem_shared/parseArfReport-CUHb8WVj.js +6 -0
- package/dist/packem_shared/parseCloudflareInbound-BGgH5u7M.js +1 -0
- package/dist/packem_shared/parseDmarcRecord-DjNqCMZc.js +1 -0
- package/dist/packem_shared/parseInbound-BP-gEjhh.js +1 -0
- package/dist/packem_shared/parseMailgunInbound-C3sZ1TiH.js +1 -0
- package/dist/packem_shared/parseMtaStsPolicy-rFOOVXXK.js +6 -0
- package/dist/packem_shared/parsePostmarkInbound-C0Ttfroo.js +1 -0
- package/dist/packem_shared/parseSendGridInbound-BkvaoYRl.js +4 -0
- package/dist/packem_shared/parseSesInbound-BFS--T8X.js +1 -0
- package/dist/packem_shared/parseTlsRptRecord-DnLwAWsk.js +1 -0
- package/dist/packem_shared/plunkProvider-BIhMU2b5.js +1 -0
- package/dist/packem_shared/postProcessHtml-C73e0b9H.js +1 -0
- package/dist/packem_shared/postalProvider-CmmbCZSi.js +1 -0
- package/dist/packem_shared/postmarkProvider-i9u0h26U.js +1 -0
- package/dist/packem_shared/provider-base-BpHE_uK8.js +1 -0
- package/dist/packem_shared/{provider.d-DcfYeGJJ.d.ts → provider.d-J-y6iogK.d.ts} +1 -1
- package/dist/packem_shared/{readFile-BAVMZg5e-C4whBIPd.js → readFile-BkNfutxp-BS8Q2183.js} +1 -1
- package/dist/packem_shared/resendProvider-BNduBn0w.js +1 -0
- package/dist/packem_shared/retry-UPd8F62N.js +1 -0
- package/dist/packem_shared/retryMiddleware-DHespsU2.js +1 -0
- package/dist/packem_shared/rewriteCidLinks-B-Sd5XHs.js +1 -0
- package/dist/packem_shared/scalewayProvider-8gb4sIOB.js +1 -0
- package/dist/packem_shared/sendGridProvider-CayLXvPO.js +1 -0
- package/dist/packem_shared/smtpProvider-DoXVsN4p.js +24 -0
- package/dist/packem_shared/sweegoProvider-C0g9Ajdn.js +1 -0
- package/dist/packem_shared/toEmailSnapshot-CYpMmnAA.js +1 -0
- package/dist/packem_shared/tracer.d-MU42G1jG.d.ts +494 -0
- package/dist/packem_shared/{types.d-CNnnk-Ya.d.ts → types.d-BId55FW2.d.ts} +6 -1
- package/dist/packem_shared/types.d-BMpI2UXj.d.ts +51 -0
- package/dist/packem_shared/types.d-CmoWvdZi.d.ts +61 -0
- package/dist/packem_shared/types.d-Mpu0HZoG.d.ts +24 -0
- package/dist/packem_shared/{types.d-wwpgA3to.d.ts → types.d-ejzh-xBP.d.ts} +6 -1
- package/dist/packem_shared/types.d-lcJZmwRK.d.ts +69 -0
- package/dist/packem_shared/utils-BwolsGlK.js +1 -0
- package/dist/packem_shared/verifyMailgunWebhook-Df7n2Quh.js +1 -0
- package/dist/packem_shared/verifyPostmarkWebhook-D_eXt_Lq.js +1 -0
- package/dist/packem_shared/verifySendGridWebhook-XOSj5yTe.js +1 -0
- package/dist/packem_shared/verifyStandardWebhook-DdUTlIVh.js +1 -0
- package/dist/packem_shared/withEvents-Q9bwpCFG.js +1 -0
- package/dist/packem_shared/withMetrics-BPs3Kdxn.js +1 -0
- package/dist/packem_shared/withRender-DQM2zbbI.js +1 -0
- package/dist/packem_shared/withSuppression-DfjV_tbI.js +1 -0
- package/dist/packem_shared/withTelemetry-CsQsv1DV.js +1 -0
- package/dist/packem_shared/zeptomailProvider-BIbHieGJ.js +1 -0
- package/dist/providers/ahasend/index.d.ts +3 -3
- package/dist/providers/ahasend/index.js +1 -1
- package/dist/providers/aws-ses/index.d.ts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/azure/index.js +1 -1
- package/dist/providers/brevo/index.d.ts +3 -3
- package/dist/providers/brevo/index.js +1 -1
- package/dist/providers/cloudflare-email/index.d.ts +36 -0
- package/dist/providers/cloudflare-email/index.js +1 -0
- package/dist/providers/failover/index.d.ts +3 -3
- package/dist/providers/http/index.d.ts +3 -3
- package/dist/providers/infobip/index.d.ts +3 -3
- package/dist/providers/infobip/index.js +1 -1
- package/dist/providers/loops/index.d.ts +47 -0
- package/dist/providers/loops/index.js +1 -0
- package/dist/providers/mailchannels/index.d.ts +26 -0
- package/dist/providers/mailchannels/index.js +1 -0
- package/dist/providers/mailcrab/index.d.ts +3 -3
- package/dist/providers/mailcrab/index.js +1 -1
- package/dist/providers/mailersend/index.d.ts +3 -3
- package/dist/providers/mailersend/index.js +1 -1
- package/dist/providers/mailgun/index.d.ts +3 -3
- package/dist/providers/mailgun/index.js +1 -1
- package/dist/providers/mailjet/index.d.ts +3 -3
- package/dist/providers/mailjet/index.js +1 -1
- package/dist/providers/mailomat/index.d.ts +3 -3
- package/dist/providers/mailomat/index.js +1 -1
- package/dist/providers/mailpace/index.d.ts +3 -3
- package/dist/providers/mailpace/index.js +1 -1
- package/dist/providers/mailtrap/index.d.ts +3 -3
- package/dist/providers/mailtrap/index.js +1 -1
- package/dist/providers/mandrill/index.d.ts +3 -3
- package/dist/providers/mandrill/index.js +1 -1
- package/dist/providers/mock/index.d.ts +6 -53
- package/dist/providers/nodemailer/index.d.ts +3 -3
- package/dist/providers/opentelemetry/index.d.ts +3 -495
- package/dist/providers/plunk/index.d.ts +3 -3
- package/dist/providers/plunk/index.js +1 -1
- package/dist/providers/postal/index.d.ts +3 -3
- package/dist/providers/postal/index.js +1 -1
- package/dist/providers/postmark/index.d.ts +3 -3
- package/dist/providers/postmark/index.js +1 -1
- package/dist/providers/resend/index.d.ts +3 -3
- package/dist/providers/resend/index.js +1 -1
- package/dist/providers/roundrobin/index.d.ts +3 -3
- package/dist/providers/scaleway/index.d.ts +3 -3
- package/dist/providers/scaleway/index.js +1 -1
- package/dist/providers/sendgrid/index.d.ts +3 -3
- package/dist/providers/sendgrid/index.js +1 -1
- package/dist/providers/smtp/index.d.ts +3 -3
- package/dist/providers/smtp/index.js +1 -1
- package/dist/providers/sweego/index.d.ts +3 -3
- package/dist/providers/sweego/index.js +1 -1
- package/dist/providers/zeptomail/index.d.ts +3 -3
- package/dist/providers/zeptomail/index.js +1 -1
- package/dist/queue/bullmq-queue.d.ts +46 -0
- package/dist/queue/bullmq-queue.js +1 -0
- package/dist/queue/index.d.ts +148 -0
- package/dist/queue/index.js +1 -0
- package/dist/queue/pg-boss-queue.d.ts +41 -0
- package/dist/queue/pg-boss-queue.js +1 -0
- package/dist/queue/sqs-queue.d.ts +72 -0
- package/dist/queue/sqs-queue.js +1 -0
- package/dist/queue/unstorage-queue.d.ts +81 -0
- package/dist/queue/unstorage-queue.js +1 -0
- package/dist/render/index.d.ts +107 -0
- package/dist/render/index.js +1 -0
- package/dist/template-engines/i18n.d.ts +61 -0
- package/dist/template-engines/i18n.js +1 -0
- package/dist/template-engines/jsx-email.d.ts +11 -0
- package/dist/template-engines/jsx-email.js +1 -0
- package/dist/template-engines/liquid.d.ts +12 -0
- package/dist/template-engines/liquid.js +1 -0
- package/dist/test/index.d.ts +159 -0
- package/dist/test/index.js +1 -0
- package/dist/utils/format-email-address.d.ts +1 -1
- package/dist/utils/format-email-address.js +1 -1
- package/dist/utils/parse-address.d.ts +1 -1
- package/dist/utils/result.d.ts +49 -0
- package/dist/utils/result.js +1 -0
- package/dist/utils/validation/check-feature-support.d.ts +1 -1
- package/dist/webhooks/index.d.ts +231 -0
- package/dist/webhooks/index.js +1 -0
- package/package.json +115 -3
- package/dist/packem_shared/DkimSigner-CT2DSHD1.js +0 -18
- package/dist/packem_shared/Mail-BWSWWq6m.js +0 -1
- package/dist/packem_shared/address-formatter-Cm_E_ZMa.js +0 -1
- package/dist/packem_shared/ahaSendProvider-DOAAW65O.js +0 -1
- package/dist/packem_shared/attachment-processor-DsmIomKc.js +0 -1
- package/dist/packem_shared/azureProvider-EkNYKAiF.js +0 -1
- package/dist/packem_shared/brevoProvider-CkR4U4RD.js +0 -1
- package/dist/packem_shared/build-mime-message-6xstxaUV.js +0 -2
- package/dist/packem_shared/infobipProvider-BhTsWi7e.js +0 -1
- package/dist/packem_shared/mailPaceProvider-DRt6Z9Hr.js +0 -1
- package/dist/packem_shared/mailerSendProvider-Dx_iHInH.js +0 -1
- package/dist/packem_shared/mailgunProvider-ChkLGZZW.js +0 -1
- package/dist/packem_shared/mailjetProvider-BMRhNe6H.js +0 -1
- package/dist/packem_shared/mailomatProvider-CydV-JB6.js +0 -1
- package/dist/packem_shared/mailtrapProvider-CuAfJWDr.js +0 -1
- package/dist/packem_shared/mandrillProvider-BBeLbaw0.js +0 -1
- package/dist/packem_shared/plunkProvider-BQyjG6YT.js +0 -1
- package/dist/packem_shared/postalProvider-DPHQ620q.js +0 -1
- package/dist/packem_shared/postmarkProvider-bMTC2gdJ.js +0 -1
- package/dist/packem_shared/provider-base-Cmzx6BTO.js +0 -1
- package/dist/packem_shared/resendProvider-Cns1tvF5.js +0 -1
- package/dist/packem_shared/scalewayProvider-O1dHz7iJ.js +0 -1
- package/dist/packem_shared/sendGridProvider-DmywC-eT.js +0 -1
- package/dist/packem_shared/smtpProvider-Unjao_fn.js +0 -23
- package/dist/packem_shared/sweegoProvider-D086G6xG.js +0 -1
- package/dist/packem_shared/zeptomailProvider-DKKEpEsW.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{detectMimeType as o,generateContentId as t,readFileAsBuffer as a}from"./packem_shared/detectMimeType-
|
|
1
|
+
import{detectMimeType as o,generateContentId as t,readFileAsBuffer as a}from"./packem_shared/detectMimeType-B4QMh7k8.js";import{default as f}from"./packem_shared/EmailError-zm2ffVav.js";import{default as m}from"./packem_shared/RequiredOptionError-CevW3u2K.js";import{Mail as s,createMail as u}from"./packem_shared/Mail-B2QII2P9.js";import{MailMessage as n}from"./packem_shared/MailMessage-DB1zaWfM.js";import{defineProvider as c}from"./packem_shared/defineProvider-CtLH0VBE.js";import{isErr as E,isOk as O,mapOk as k,tryAsync as y,unwrap as g,unwrapOr as w}from"./utils/result.js";import{default as F}from"./utils/validation/check-feature-support.js";export{f as EmailError,s as Mail,n as MailMessage,m as RequiredOptionError,F as checkFeatureSupport,u as createMail,c as defineProvider,o as detectMimeType,t as generateContentId,E as isErr,O as isOk,k as mapOk,a as readFileAsBuffer,y as tryAsync,g as unwrap,w as unwrapOr};
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { M as Middleware } from "../packem_shared/types.d-Mpu0HZoG.js";
|
|
2
|
+
export { type S as SendFunction, c as composeMiddleware } from "../packem_shared/types.d-Mpu0HZoG.js";
|
|
3
|
+
import { E as EmailOptions, M as MaybePromise, a as EmailResult, R as Result, c as EmailAddress } from "../packem_shared/types.d-ejzh-xBP.js";
|
|
4
|
+
import { d as EventBus } from "../packem_shared/event-bus.d-DEl3w_EW.js";
|
|
5
|
+
import { b as SuppressionStore } from "../packem_shared/types.d-CmoWvdZi.js";
|
|
6
|
+
import { T as Tracer } from "../packem_shared/tracer.d-MU42G1jG.js";
|
|
7
|
+
import 'node:buffer';
|
|
8
|
+
/**
|
|
9
|
+
* The state of a {@link circuitBreakerMiddleware}.
|
|
10
|
+
*
|
|
11
|
+
* `closed` = healthy; `open` = failing fast; `half-open` = trialing one request to test recovery.
|
|
12
|
+
*/
|
|
13
|
+
type CircuitState = "closed" | "half-open" | "open";
|
|
14
|
+
/**
|
|
15
|
+
* Options for the {@link circuitBreakerMiddleware}.
|
|
16
|
+
*/
|
|
17
|
+
interface CircuitBreakerMiddlewareOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Consecutive failures before the circuit opens.
|
|
20
|
+
* @default 5
|
|
21
|
+
*/
|
|
22
|
+
failureThreshold?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
25
|
+
*/
|
|
26
|
+
now?: () => number;
|
|
27
|
+
/**
|
|
28
|
+
* Notified whenever the circuit changes state.
|
|
29
|
+
* @param state The new state.
|
|
30
|
+
*/
|
|
31
|
+
onStateChange?: (state: CircuitState) => void;
|
|
32
|
+
/**
|
|
33
|
+
* How long, in milliseconds, the circuit stays open before allowing a half-open trial.
|
|
34
|
+
* @default 30000
|
|
35
|
+
*/
|
|
36
|
+
resetTimeout?: number;
|
|
37
|
+
}
|
|
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
|
+
*/
|
|
44
|
+
declare const circuitBreakerMiddleware: (options?: CircuitBreakerMiddlewareOptions) => Middleware;
|
|
45
|
+
/**
|
|
46
|
+
* Options for the {@link dedupeMiddleware}.
|
|
47
|
+
*/
|
|
48
|
+
interface DedupeMiddlewareOptions {
|
|
49
|
+
/**
|
|
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
|
+
keyFn?: (options: EmailOptions) => string;
|
|
54
|
+
/**
|
|
55
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
56
|
+
*/
|
|
57
|
+
now?: () => number;
|
|
58
|
+
/**
|
|
59
|
+
* How long, in milliseconds, a key is remembered.
|
|
60
|
+
* @default 60000
|
|
61
|
+
*/
|
|
62
|
+
ttl?: number;
|
|
63
|
+
}
|
|
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
|
+
*/
|
|
72
|
+
declare const dedupeMiddleware: (options?: DedupeMiddlewareOptions) => Middleware;
|
|
73
|
+
/**
|
|
74
|
+
* Options for {@link withEvents}.
|
|
75
|
+
*/
|
|
76
|
+
interface EventsMiddlewareOptions {
|
|
77
|
+
/**
|
|
78
|
+
* Generates event ids. Defaults to `crypto.randomUUID`.
|
|
79
|
+
*/
|
|
80
|
+
idFactory?: () => string;
|
|
81
|
+
/**
|
|
82
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
83
|
+
*/
|
|
84
|
+
now?: () => number;
|
|
85
|
+
}
|
|
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
|
+
*/
|
|
93
|
+
declare const withEvents: (bus: EventBus, options?: EventsMiddlewareOptions) => Middleware;
|
|
94
|
+
/**
|
|
95
|
+
* Options for the {@link loggingMiddleware}.
|
|
96
|
+
*/
|
|
97
|
+
interface LoggingMiddlewareOptions {
|
|
98
|
+
/**
|
|
99
|
+
* The logger to write to.
|
|
100
|
+
* @default console
|
|
101
|
+
*/
|
|
102
|
+
logger?: Pick<Console, "error" | "info">;
|
|
103
|
+
/**
|
|
104
|
+
* Redact recipient addresses (e.g. `j••@example.com`) to keep PII out of logs.
|
|
105
|
+
* @default true
|
|
106
|
+
*/
|
|
107
|
+
redact?: boolean;
|
|
108
|
+
}
|
|
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
|
+
*/
|
|
114
|
+
declare const loggingMiddleware: (options?: LoggingMiddlewareOptions) => Middleware;
|
|
115
|
+
/**
|
|
116
|
+
* A minimal metrics sink — implement it with prom-client, OpenTelemetry metrics, StatsD, etc.
|
|
117
|
+
*/
|
|
118
|
+
interface MetricsRecorder {
|
|
119
|
+
/**
|
|
120
|
+
* Increments a counter.
|
|
121
|
+
* @param metric The metric name.
|
|
122
|
+
* @param labels Optional labels/dimensions.
|
|
123
|
+
*/
|
|
124
|
+
increment: (metric: string, labels?: Record<string, string>) => void;
|
|
125
|
+
/**
|
|
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
|
+
observe: (metric: string, value: number, labels?: Record<string, string>) => void;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Options for {@link withMetrics}.
|
|
135
|
+
*/
|
|
136
|
+
interface MetricsMiddlewareOptions {
|
|
137
|
+
/**
|
|
138
|
+
* Prefix for emitted metric names.
|
|
139
|
+
* @default "email_"
|
|
140
|
+
*/
|
|
141
|
+
prefix?: string;
|
|
142
|
+
}
|
|
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
|
+
*/
|
|
151
|
+
declare const withMetrics: (recorder: MetricsRecorder, options?: MetricsMiddlewareOptions) => Middleware;
|
|
152
|
+
/**
|
|
153
|
+
* An OAuth2 access token plus its expiry.
|
|
154
|
+
*/
|
|
155
|
+
interface OAuth2Token {
|
|
156
|
+
/**
|
|
157
|
+
* The bearer access token.
|
|
158
|
+
*/
|
|
159
|
+
accessToken: string;
|
|
160
|
+
/**
|
|
161
|
+
* Absolute expiry time in milliseconds since the epoch. Omit for non-expiring tokens.
|
|
162
|
+
*/
|
|
163
|
+
expiresAt?: number;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Options for the {@link oauth2Middleware}.
|
|
167
|
+
*/
|
|
168
|
+
interface OAuth2MiddlewareOptions {
|
|
169
|
+
/**
|
|
170
|
+
* Fetches (or refreshes) the access token. Called only when the cached token is missing or within
|
|
171
|
+
* {@link OAuth2MiddlewareOptions.skewMs} of expiry. Wire this to your Gmail / Microsoft 365 refresh
|
|
172
|
+
* flow.
|
|
173
|
+
*/
|
|
174
|
+
fetchToken: () => Promise<OAuth2Token> | OAuth2Token;
|
|
175
|
+
/**
|
|
176
|
+
* The header to inject the credential into.
|
|
177
|
+
* @default "Authorization"
|
|
178
|
+
*/
|
|
179
|
+
headerName?: string;
|
|
180
|
+
/**
|
|
181
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
182
|
+
*/
|
|
183
|
+
now?: () => number;
|
|
184
|
+
/**
|
|
185
|
+
* Receives every freshly-acquired token — use it to feed SMTP XOAUTH2 or a provider client that
|
|
186
|
+
* authenticates outside the message headers.
|
|
187
|
+
* @param token The new token.
|
|
188
|
+
*/
|
|
189
|
+
onToken?: (token: OAuth2Token) => void;
|
|
190
|
+
/**
|
|
191
|
+
* The auth scheme prefix for the header value.
|
|
192
|
+
* @default "Bearer"
|
|
193
|
+
*/
|
|
194
|
+
scheme?: string;
|
|
195
|
+
/**
|
|
196
|
+
* Refresh this many milliseconds before the token actually expires.
|
|
197
|
+
* @default 60000
|
|
198
|
+
*/
|
|
199
|
+
skewMs?: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Injects an OAuth2 bearer credential into each outgoing message, refreshing it on demand and caching
|
|
203
|
+
* it until just before expiry.
|
|
204
|
+
*
|
|
205
|
+
* Supplies the token to provider clients (Gmail, Microsoft 365) either via a request header or the
|
|
206
|
+
* {@link OAuth2MiddlewareOptions.onToken} callback (for SMTP XOAUTH2).
|
|
207
|
+
* @param options OAuth2 configuration. See {@link OAuth2MiddlewareOptions}.
|
|
208
|
+
* @returns The middleware.
|
|
209
|
+
*/
|
|
210
|
+
declare const oauth2Middleware: (options: OAuth2MiddlewareOptions) => Middleware;
|
|
211
|
+
/**
|
|
212
|
+
* Options for the {@link rateLimitMiddleware}.
|
|
213
|
+
*/
|
|
214
|
+
interface RateLimitMiddlewareOptions {
|
|
215
|
+
/**
|
|
216
|
+
* Maximum burst capacity (tokens). Defaults to {@link RateLimitMiddlewareOptions.rate}.
|
|
217
|
+
*/
|
|
218
|
+
burst?: number;
|
|
219
|
+
/**
|
|
220
|
+
* Time source in milliseconds — injectable for tests. Defaults to `Date.now`.
|
|
221
|
+
*/
|
|
222
|
+
now?: () => number;
|
|
223
|
+
/**
|
|
224
|
+
* Sustained send rate, in messages per second.
|
|
225
|
+
*/
|
|
226
|
+
rate: number;
|
|
227
|
+
/**
|
|
228
|
+
* Sleep implementation — injectable for tests. Defaults to `setTimeout`.
|
|
229
|
+
* @param ms Milliseconds to wait.
|
|
230
|
+
*/
|
|
231
|
+
sleep?: (ms: number) => Promise<void>;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Pre-tuned per-second rate presets for common providers' default plans. Override as needed for your
|
|
235
|
+
* own quota.
|
|
236
|
+
*/
|
|
237
|
+
declare const RATE_LIMIT_PRESETS: {
|
|
238
|
+
readonly "aws-ses": 14;
|
|
239
|
+
readonly mailgun: 100;
|
|
240
|
+
readonly postmark: 100;
|
|
241
|
+
readonly resend: 10;
|
|
242
|
+
readonly sendgrid: 100;
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Throttles sends with a token-bucket limiter, awaiting capacity rather than failing when the rate is
|
|
246
|
+
* exceeded.
|
|
247
|
+
* @param options Rate configuration. See {@link RateLimitMiddlewareOptions} and {@link RATE_LIMIT_PRESETS}.
|
|
248
|
+
* @returns A middleware that paces sends to the configured rate.
|
|
249
|
+
*/
|
|
250
|
+
declare const rateLimitMiddleware: (options: RateLimitMiddlewareOptions) => Middleware;
|
|
251
|
+
/**
|
|
252
|
+
* Wraps a transform that rewrites the message before it is sent — e.g. running the HTML through the
|
|
253
|
+
* `@visulima/email/render` post-processing pipeline (preheader, CID rewrite, dark-mode, CSS inline).
|
|
254
|
+
* @param transform Maps the resolved {@link EmailOptions} to its rendered form.
|
|
255
|
+
* @returns A middleware that applies the transform ahead of the provider call.
|
|
256
|
+
* @example
|
|
257
|
+
* ```ts
|
|
258
|
+
* import { postProcessHtml } from "@visulima/email/render";
|
|
259
|
+
*
|
|
260
|
+
* mail.use(withRender(async (email) => ({
|
|
261
|
+
* ...email,
|
|
262
|
+
* html: email.html ? postProcessHtml(email.html, { preheader: "Hi!", darkMode: true }) : email.html,
|
|
263
|
+
* })));
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare const withRender: (transform: (options: EmailOptions) => MaybePromise<EmailOptions>) => Middleware;
|
|
267
|
+
/**
|
|
268
|
+
* Options for the {@link retryMiddleware}.
|
|
269
|
+
*/
|
|
270
|
+
interface RetryMiddlewareOptions {
|
|
271
|
+
/**
|
|
272
|
+
* The base backoff delay in milliseconds. Actual delays grow exponentially and are jittered.
|
|
273
|
+
* @default 200
|
|
274
|
+
*/
|
|
275
|
+
baseDelay?: number;
|
|
276
|
+
/**
|
|
277
|
+
* Called when all retries are exhausted — a dead-letter hook for durable storage/alerting.
|
|
278
|
+
* @param options The message that ultimately failed.
|
|
279
|
+
* @param result The final failed result.
|
|
280
|
+
*/
|
|
281
|
+
onDeadLetter?: (options: EmailOptions, result: Result<EmailResult>) => Promise<void> | void;
|
|
282
|
+
/**
|
|
283
|
+
* Maximum number of attempts (including the first).
|
|
284
|
+
* @default 3
|
|
285
|
+
*/
|
|
286
|
+
retries?: number;
|
|
287
|
+
/**
|
|
288
|
+
* Decides whether a failed result is retryable. Defaults to retrying every failure.
|
|
289
|
+
* @param result The failed result.
|
|
290
|
+
*/
|
|
291
|
+
shouldRetry?: (result: Result<EmailResult>) => boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Sleep implementation — injectable for tests. Defaults to `setTimeout`.
|
|
294
|
+
* @param ms Milliseconds to wait.
|
|
295
|
+
*/
|
|
296
|
+
sleep?: (ms: number) => Promise<void>;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Retries failed sends with full-jitter exponential backoff, optionally dead-lettering the final
|
|
300
|
+
* failure.
|
|
301
|
+
*
|
|
302
|
+
* Full jitter (`random(0, base * 2^attempt)`) avoids the thundering-herd retries a fixed schedule
|
|
303
|
+
* causes.
|
|
304
|
+
* @param options Retry configuration. See {@link RetryMiddlewareOptions}.
|
|
305
|
+
* @returns A middleware that re-attempts failed sends before giving up.
|
|
306
|
+
*/
|
|
307
|
+
declare const retryMiddleware: (options?: RetryMiddlewareOptions) => Middleware;
|
|
308
|
+
/**
|
|
309
|
+
* Options for {@link withSuppression}.
|
|
310
|
+
*/
|
|
311
|
+
interface SuppressionMiddlewareOptions {
|
|
312
|
+
/**
|
|
313
|
+
* Called with the recipients that were removed because they are suppressed.
|
|
314
|
+
* @param suppressed The dropped recipients.
|
|
315
|
+
*/
|
|
316
|
+
onSuppressed?: (suppressed: EmailAddress[]) => void;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Filters suppressed recipients out of the `to` list before sending, and short-circuits with a failed
|
|
320
|
+
* result when every recipient is suppressed.
|
|
321
|
+
* @param store The suppression store to check against.
|
|
322
|
+
* @param options Middleware options. See {@link SuppressionMiddlewareOptions}.
|
|
323
|
+
* @returns A middleware that enforces the suppression list.
|
|
324
|
+
*/
|
|
325
|
+
declare const withSuppression: (store: SuppressionStore, options?: SuppressionMiddlewareOptions) => Middleware;
|
|
326
|
+
/**
|
|
327
|
+
* Options for {@link withTelemetry}.
|
|
328
|
+
*/
|
|
329
|
+
interface TelemetryMiddlewareOptions {
|
|
330
|
+
/**
|
|
331
|
+
* The span name.
|
|
332
|
+
* @default "email.send"
|
|
333
|
+
*/
|
|
334
|
+
spanName?: string;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Wraps each send in an OpenTelemetry span, recording the provider, recipient count and outcome.
|
|
338
|
+
*
|
|
339
|
+
* The `@opentelemetry/api` `Tracer` is injected (type-only import here), so this middleware adds no
|
|
340
|
+
* runtime dependency — pass `trace.getTracer("email")` from your instrumented app.
|
|
341
|
+
* @param tracer An OpenTelemetry `Tracer`.
|
|
342
|
+
* @param options Middleware options. See {@link TelemetryMiddlewareOptions}.
|
|
343
|
+
* @returns A middleware that traces sends.
|
|
344
|
+
*/
|
|
345
|
+
declare const withTelemetry: (tracer: Tracer, options?: TelemetryMiddlewareOptions) => Middleware;
|
|
346
|
+
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 };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{circuitBreakerMiddleware as o}from"../packem_shared/circuitBreakerMiddleware-B7DlzZSG.js";import{dedupeMiddleware as i}from"../packem_shared/dedupeMiddleware-JeJbff46.js";import{withEvents as p}from"../packem_shared/withEvents-Q9bwpCFG.js";import{loggingMiddleware as f}from"../packem_shared/loggingMiddleware-CyHzn37U.js";import{withMetrics as w}from"../packem_shared/withMetrics-BPs3Kdxn.js";import{oauth2Middleware as l}from"../packem_shared/oauth2Middleware-B1xz58iP.js";import{RATE_LIMIT_PRESETS as h,rateLimitMiddleware as s}from"../packem_shared/RATE_LIMIT_PRESETS-DQF78mdO.js";import{default as c}from"../packem_shared/withRender-DQM2zbbI.js";import{retryMiddleware as E}from"../packem_shared/retryMiddleware-DHespsU2.js";import{withSuppression as g}from"../packem_shared/withSuppression-DfjV_tbI.js";import{withTelemetry as S}from"../packem_shared/withTelemetry-CsQsv1DV.js";import{composeMiddleware as I}from"../packem_shared/composeMiddleware-CkEhbDjL.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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var l=Object.defineProperty;var r=(n,t)=>l(n,"name",{value:t,configurable:!0});var c=Object.defineProperty,i=r((n,t)=>c(n,"name",{value:t,configurable:!0}),"s");const f="*";class h{static{r(this,"EventBus")}static{i(this,"EventBus")}listeners=new Map;on(t,s){let e=this.listeners.get(t);return e||(e=new Set,this.listeners.set(t,e)),e.add(s),()=>{this.off(t,s)}}once(t,s){const e=i(o=>{this.off(t,e),s(o)},"wrapped");return this.on(t,e)}off(t,s){this.listeners.get(t)?.delete(s)}emit(t){const s=i(e=>{try{e(t)}catch{}},"invoke");for(const e of this.listeners.get(t.type)??[])s(e);for(const e of this.listeners.get("*")??[])s(e)}clear(t){t===void 0?this.listeners.clear():this.listeners.delete(t)}}export{f as ALL_EVENTS,h as EventBus};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var v=Object.defineProperty;var m=(r,e)=>v(r,"name",{value:e,configurable:!0});import{createRequire as C}from"node:module";import{E as _}from"./readFile-BkNfutxp-BS8Q2183.js";import{i as x}from"./headers-to-record-Qo124ImV.js";const w=C(import.meta.url),d=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,S=m(r=>{if(typeof d<"u"&&d.versions&&d.versions.node){const[e,t]=d.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return d.getBuiltinModule(r)}return w(r)},"__cjs_getBuiltinModule"),{createHash:f,createPrivateKey:T,sign:D,createSign:M}=S("node:crypto");var z=Object.defineProperty,l=m((r,e)=>z(r,"name",{value:e,configurable:!0}),"l");const I=l((r,e="simple")=>{const t=[];for(const[s,a]of Object.entries(r)){const i=e==="relaxed"?s.toLowerCase().trim():s,o=e==="relaxed"?a.replaceAll(/\s+/g," ").trim():a;t.push(`${i}:${o}`)}return t.join(`\r
|
|
2
|
+
`)},"canonicalizeHeaders"),K=l((r,e="simple")=>{if(e==="simple"){const i=r.replace(/(\r\n|\r|\n)$/,`
|
|
3
|
+
`);let o=i.length;for(;o>0&&i[o-1]===`
|
|
4
|
+
`;)o-=1;const c=i.slice(0,o);return c?`${c}
|
|
5
|
+
`:`
|
|
6
|
+
`}let t=r.replaceAll(`\r
|
|
7
|
+
`,`
|
|
8
|
+
`).replaceAll("\r",`
|
|
9
|
+
`);t=t.split(`
|
|
10
|
+
`).map(i=>i.replaceAll(/\s+/g," ").replace(/[ \t]+$/,"")).join(`
|
|
11
|
+
`);let s=t.length;for(;s>0&&t[s-1]===`
|
|
12
|
+
`;)s-=1;const a=t.slice(0,s);return a?`${a}
|
|
13
|
+
`:`
|
|
14
|
+
`},"canonicalizeBody"),H=l((r,e,t)=>{const s=e.headerCanon??"simple",a=e.bodyCanon??"simple",i=Object.keys(r).filter(o=>!e.headersToIgnore?.some(c=>c.toLowerCase()===o.toLowerCase())).map(o=>o.toLowerCase()).join(":");return["v=1",`a=${e.algorithm??"rsa-sha256"}`,`c=${s}/${a}`,`d=${e.domainName}`,`s=${e.keySelector}`,`h=${i}`,`bh=${t}`,"b="].join("; ")},"createDkimSignatureHeader"),L=l((r,e,t)=>t==="ed25519-sha256"?D(null,f("sha256").update(r).digest(),e).toString("base64"):M("RSA-SHA256").update(r).sign(e,"base64"),"signDkimData");class n{static{m(this,"DkimSigner")}static{l(this,"DkimSigner")}static sanitizeDisplayName(e){let t=e.replaceAll(/[\r\n\t]+/g," ");t=[...t].filter(i=>{const o=i.codePointAt(0);return o===void 0?!1:o>=32&&o<=126||o>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=n.sanitizeDisplayName(e.name);return t?`"${t}" <${e.email}>`:e.email}return e.email}static formatAddresses(e){return(Array.isArray(e)?e:[e]).map(t=>n.formatAddress(t)).join(", ")}options;constructor(e){this.options=e}async sign(e){let t=this.options.privateKey;if(t.startsWith("file://")){const p=t.slice(7);t=await _(p,{encoding:"utf8"})}const s={...e.headers?x(e.headers):{},From:n.formatAddress(e.from),To:n.formatAddresses(e.to)};e.cc&&(s.Cc=n.formatAddresses(e.cc)),e.replyTo&&(s["Reply-To"]=n.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 i=a.join(`
|
|
15
|
+
|
|
16
|
+
`),o=this.options.headerCanon??"simple",c=this.options.bodyCanon??"simple",g=I(s,o),y=K(i,c),A=f("sha256").update(y).digest("base64"),h=H(s,this.options,A),$=`${g}\r
|
|
17
|
+
DKIM-Signature: ${h}`;let u;try{const p=T({key:t,passphrase:this.options.passphrase});u=L($,p,this.options.algorithm)}catch(p){throw new Error(`Failed to create DKIM signature: ${p.message}`)}const b=u.match(/.{1,72}/g)?.join(`\r
|
|
18
|
+
`)??u,j={...s,"DKIM-Signature":`${h}${b}`};return{...e,headers:j}}}const k=l(r=>new n(r),"createDkimSigner");export{n as DkimSigner,k as createDkimSigner};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var d=(o,e)=>p(o,"name",{value:e,configurable:!0});import{MailMessage as c}from"./MailMessage-DB1zaWfM.js";import m from"./EmailError-zm2ffVav.js";import{composeMiddleware as b}from"./composeMiddleware-CkEhbDjL.js";import{z as y}from"./build-mime-message-D8WEZejb.js";import{c as v}from"./create-logger-BiWdqFNg.js";import{i as n}from"./headers-to-record-Qo124ImV.js";import C from"../utils/validation/check-feature-support.js";var w=Object.defineProperty,M=d((o,e)=>w(o,"name",{value:e,configurable:!0}),"s");class u extends c{static{d(this,"DraftMailMessage")}static{M(this,"DraftMailMessage")}constructor(){super(),this.header("X-Unsent","1")}}var T=Object.defineProperty,h=d((o,e)=>T(o,"name",{value:e,configurable:!0}),"g");const j=h((o,e,s)=>{e.success&&e.data?o&&o.info("Email sent successfully",{messageId:e.data.messageId,provider:e.data.provider}):o&&o.error("Email send failed",{error:e.error,provider:s})},"logSendResult"),E=h(async(o,e,s)=>{const r={...o,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={...n(o.headers??{}),...n(e.headers)}),r.subject=e.subject??o.subject,s&&e.data&&(r.subject=await s(r.subject,e.data),o.html!==void 0&&(r.html=await s(o.html,e.data)),o.text!==void 0&&(r.text=await s(o.text,e.data))),r},"buildPersonalized");class f{static{d(this,"Mail")}static{h(this,"Mail")}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=v("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=n(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 c||e instanceof u?await this.buildDraftFromMessage(e):await this.buildDraftFromOptions(e);s=this.applyGlobalConfig(s);const r=s.headers?n(s.headers):{};s.headers={...r,"X-Unsent":"1"};const t=await y(s);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 u)throw new TypeError("Cannot send draft messages. Convert to MailMessage first or remove X-Unsent header.");let s;if(e instanceof c)this.logger&&this.logger.debug("Sending MailMessage instance"),this.loggerInstance&&e.setLogger(this.loggerInstance),s=await e.build();else{const a=e;this.logger&&this.logger.debug("Sending email with options",{subject:a.subject,to:Array.isArray(a.to)?a.to.length:1}),s=a}s=this.applyGlobalConfig(s);const r=this.assertFeatureSupport(s);if(r)return{error:r,success:!1};const t=await this.dispatch(s);return j(this.logger,t,this.provider.name??"unknown"),t}async*sendMany(e,s){const r=this.provider.name;let t=0,a=0,l=0;this.logger&&this.logger.debug("Starting batch email send",{provider:r});for await(const g of e){if(g instanceof u)throw new TypeError("Cannot send draft messages. Convert to MailMessage first or remove X-Unsent header.");if(s?.signal?.aborted){this.logger&&this.logger.warn("Batch send operation was aborted",{failed:l,processed:t,successful:a}),yield{errorMessages:["Send operation was aborted"],provider:r,successful:!1};return}t+=1;try{const i=await this.send(g);i.success&&i.data?(a+=1,this.logger&&this.logger.debug(`Email ${t} sent successfully`,{messageId:i.data.messageId}),yield{messageId:i.data.messageId,provider:i.data.provider??r,response:i.data.response,successful:!0,timestamp:i.data.timestamp}):(l+=1,this.logger&&this.logger.error(`Email ${t} send failed`,{error:i.error}),yield{errorMessages:f.extractErrorMessages(i.error),provider:r,successful:!1})}catch(i){l+=1,this.logger&&this.logger.error(`Email ${t} send failed with exception`,i),yield{errorMessages:f.extractErrorMessages(i),provider:r,successful:!1}}}this.logger&&this.logger.debug("Batch email send completed",{failureCount:l,processedCount:t,provider:r,successCount:a})}sendBatch(e,s,r){const t=h(async function*(){const a=e instanceof c?await e.build():e;for(const l of s)yield await E(a,l,r?.render)},"build");return this.sendMany(t(),{signal:r?.signal})}async dispatch(e){return this.middlewares.length===0?await this.resolveProvider(e).sendEmail(e):(this.composedSend??=b(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){if(this.featureCheck==="off")return;const{supported:s,violations:r}=C(e,this.provider.features);if(s)return;const t=this.provider.name??"unknown",a=r.map(g=>g.field),l=r.map(g=>g.message);if(this.featureCheck==="warn"){this.logger&&this.logger.warn("Message uses capabilities the provider does not support",{fields:a,provider:t});return}return this.logger&&this.logger.error("Message rejected by capability guard",{fields:a,provider:t}),new m(t,`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=n(this.globalConfig.headers);Object.entries(t).forEach(([a,l])=>{e.header(a,l)})}}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=n(this.globalConfig.headers),t=s.headers?n(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=h((o,e)=>new f(o,e),"createMail");export{f as Mail,F as createMail};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var A=Object.defineProperty;var d=(n,e)=>A(n,"name",{value:e,configurable:!0});import{createRequire as b}from"node:module";import C from"ical-generator";import{readFileAsBuffer as u,detectMimeType as g,generateContentId as m}from"./detectMimeType-
|
|
1
|
+
var A=Object.defineProperty;var d=(n,e)=>A(n,"name",{value:e,configurable:!0});import{createRequire as b}from"node:module";import C from"ical-generator";import{readFileAsBuffer as u,detectMimeType as g,generateContentId as m}from"./detectMimeType-B4QMh7k8.js";import p from"../template-engines/html-to-text.js";import{c as E}from"./create-logger-BiWdqFNg.js";import{i as l}from"./headers-to-record-Qo124ImV.js";const T=b(import.meta.url),a=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,f=d(n=>{if(typeof a<"u"&&a.versions&&a.versions.node){const[e,t]=a.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return a.getBuiltinModule(n)}return T(n)},"__cjs_getBuiltinModule"),{basename:c}=f("node:path"),{fileURLToPath:x}=f("node:url");var w=Object.defineProperty,y=d((n,e)=>w(n,"name",{value:e,configurable:!0}),"l");const o=y(n=>Array.isArray(n)?n.map(e=>typeof e=="string"?{email:e}:e):typeof n=="string"?[{email:n}]:[n],"normalizeAddresses");class M{static{d(this,"MailMessage")}static{y(this,"MailMessage")}fromAddress;toAddresses=[];ccAddresses=[];bccAddresses=[];subjectText="";textContent;textCharset="utf8";autoTextEnabled=!0;htmlContent;htmlCharset="utf8";dateValue;returnPathAddress;senderAddress;headers={};attachments=[];replyToAddress;priorityValue;tagsValue=[];signer;encrypter;logger;icalEventData;from(e){return this.fromAddress=typeof e=="string"?{email:e}:e,this}to(e){return this.toAddresses.length=0,this.toAddresses.push(...o(e)),this}cc(e){return this.ccAddresses.length=0,this.ccAddresses.push(...o(e)),this}bcc(e){return this.bccAddresses.length=0,this.bccAddresses.push(...o(e)),this}subject(e){return this.subjectText=e,this}text(e,t="utf8"){return this.textContent=e,this.textCharset=t,this}html(e,t="utf8"){return this.htmlContent=e,this.htmlCharset=t,this}header(e,t){return this.headers[e]=t,this}setHeaders(e){const t=l(e);return Object.assign(this.headers,t),this}async attachFromPath(e,t){try{const s=await u(e),i=t?.filename??(c(e)||"attachment"),r=t?.contentType??g(i);this.attachments.push({cid:t?.cid,content:s,contentDisposition:t?.contentDisposition??"attachment",contentType:r,encoding:t?.encoding,filename:i,headers:t?.headers}),this.logger&&this.logger.debug(`Attachment added from path: ${e}`,{contentType:r,filename:i})}catch(s){throw this.logger&&this.logger.error(`Failed to attach file from path: ${e}`,s),s}return this}attachData(e,t){const s=t.contentType??g(t.filename);return this.attachments.push({cid:t.cid,content:e,contentDisposition:t.contentDisposition??"attachment",contentType:s,encoding:t.encoding,filename:t.filename,headers:t.headers}),this.logger&&this.logger.debug("Attachment added from data",{contentType:s,filename:t.filename}),this}async embedFromPath(e,t){try{const s=await u(e),i=t?.filename??(c(e)||"inline"),r=t?.contentType??g(i),h=m(i);return this.attachments.push({cid:h,content:s,contentDisposition:"inline",contentType:r,filename:i}),this.logger&&this.logger.debug(`Inline attachment embedded from path: ${e}`,{cid:h,contentType:r,filename:i}),h}catch(s){throw this.logger&&this.logger.error(`Failed to embed file from path: ${e}`,s),s}}embedData(e,t,s){const i=s?.contentType??g(t),r=m(t);return this.attachments.push({cid:r,content:e,contentDisposition:"inline",contentType:i,filename:t}),this.logger&&this.logger.debug("Inline attachment embedded from data",{cid:r,contentType:i,filename:t}),r}replyTo(e){return this.replyToAddress=typeof e=="string"?{email:e}:e,this}date(e){return this.dateValue=typeof e=="string"?new Date(e):e,this.logger&&this.logger.debug("Date header set",{date:this.dateValue.toISOString()}),this}returnPath(e){return this.returnPathAddress=typeof e=="string"?{email:e}:e,this.logger&&this.logger.debug("Return-path address set",{returnPath:this.returnPathAddress.email}),this}sender(e){return this.senderAddress=typeof e=="string"?{email:e}:e,this.logger&&this.logger.debug("Sender address set",{sender:this.senderAddress.email}),this}addTo(e){return this.toAddresses.push(...o(e)),this}addCc(e){return this.ccAddresses.push(...o(e)),this}addBcc(e){return this.bccAddresses.push(...o(e)),this}addReplyTo(e){const t=Array.isArray(e)?e:[e];if(t.length>0){const s=t[0];this.replyToAddress=typeof s=="string"?{email:s}:s}return this}addFrom(e){const t=Array.isArray(e)?e:[e];if(t.length>0){const s=t[0];this.fromAddress=typeof s=="string"?{email:s}:s}return this}priority(e){return this.priorityValue=e,this}tags(e){return this.tagsValue=Array.isArray(e)?e:[e],this}sign(e){return this.signer=e,this.logger&&this.logger.debug("Email signer configured"),this}encrypt(e){return this.encrypter=e,this.logger&&this.logger.debug("Email encrypter configured"),this}setLogger(e){return this.logger=E("MailMessage",e),this}icalEvent(e,t){if(typeof e=="function"){const s=C();e(s),this.icalEventData={content:s.toString(),...t}}else this.icalEventData={content:e,...t};return this.logger&&this.logger.debug("Calendar event attached",{method:t?.method}),this}icalEventFromFile(e,t){const s=typeof e=="string"?e:x(e);return this.icalEventData={path:s,...t},this.logger&&this.logger.debug(`Calendar event attached from file: ${s}`,{method:t?.method}),this}icalEventFromUrl(e,t){return this.icalEventData={href:e,...t},this.logger&&this.logger.debug(`Calendar event attached from URL: ${e}`,{method:t?.method}),this}async view(e,t,s,i){try{const r=i?.autoText!==!1;this.autoTextEnabled=r,this.logger&&this.logger.debug("Rendering template",{autoText:r});const h=await e(t,s,i);this.html(h),r&&h&&this.tryAutoGenerateText(h),this.logger&&this.logger.debug("Template rendered successfully")}catch(r){throw this.logger&&this.logger.error("Failed to render template",r),new Error(`Failed to render template: ${r.message}`)}return this}async viewText(e,t,s,i){try{this.logger&&this.logger.debug("Rendering text template");const r=await e(t,s,i);if(typeof r=="string")this.text(r),this.logger&&this.logger.debug("Text template rendered successfully");else throw new TypeError("Text renderer must return a string")}catch(r){throw this.logger&&this.logger.error("Failed to render text template",r),new Error(`Failed to render text template: ${r.message}`)}return this}async build(){if(this.logger&&this.logger.debug("Building email message"),this.fromAddress||this.throwAndLogError("From address is required","Build failed: from address is required"),this.toAddresses.length===0&&this.throwAndLogError("At least one recipient is required","Build failed: at least one recipient is required"),this.subjectText||this.throwAndLogError("Subject is required","Build failed: subject is required"),this.htmlContent&&!this.textContent&&this.autoTextEnabled)try{this.textContent=p(this.htmlContent),this.logger&&this.logger.debug("Auto-generated text content from HTML")}catch{this.logger&&this.logger.debug("Failed to convert HTML to text; proceeding without text content.")}!this.textContent&&!this.htmlContent&&this.throwAndLogError("Either text or html content is required","Build failed: either text or html content is required");let e={from:this.fromAddress,html:this.htmlContent,subject:this.subjectText,text:this.textContent,to:this.toAddresses.length===1?this.toAddresses[0]:this.toAddresses};return this.ccAddresses.length>0&&(e.cc=this.ccAddresses.length===1?this.ccAddresses[0]:this.ccAddresses),this.bccAddresses.length>0&&(e.bcc=this.bccAddresses.length===1?this.bccAddresses[0]:this.bccAddresses),Object.keys(this.headers).length>0&&(e.headers=this.headers),this.attachments.length>0&&(e.attachments=this.attachments,this.logger&&this.logger.debug(`Email includes ${this.attachments.length} attachment(s)`)),this.replyToAddress&&(e.replyTo=this.replyToAddress),this.priorityValue&&(e.priority=this.priorityValue),this.tagsValue.length>0&&(e.tags=this.tagsValue),this.icalEventData&&(e.icalEvent=this.icalEventData,this.logger&&this.logger.debug("Email includes calendar event")),this.dateValue&&(e.headers={...l(e.headers??{}),Date:this.dateValue.toUTCString()}),this.returnPathAddress&&(e.headers={...l(e.headers??{}),"Return-Path":this.returnPathAddress.email}),this.senderAddress&&(e.headers={...l(e.headers??{}),Sender:this.senderAddress.email}),this.signer&&(this.logger&&this.logger.debug("Signing email message"),e=await this.signer.sign(e),this.logger&&this.logger.debug("Email message signed successfully")),this.encrypter&&(this.logger&&this.logger.debug("Encrypting email message"),e=await this.encrypter.encrypt(e),this.logger&&this.logger.debug("Email message encrypted successfully")),this.logger&&this.logger.debug("Email message built successfully",{bcc:this.bccAddresses.length,cc:this.ccAddresses.length,hasHtml:!!this.htmlContent,hasText:!!this.textContent,to:this.toAddresses.length}),e}getSubject(){return this.subjectText}getFrom(){return this.fromAddress}getTo(){return[...this.toAddresses]}getCc(){return[...this.ccAddresses]}getBcc(){return[...this.bccAddresses]}getReplyTo(){return this.replyToAddress}getSender(){return this.senderAddress}getReturnPath(){return this.returnPathAddress}getDate(){return this.dateValue}getPriority(){return this.priorityValue}getTextBody(){return this.textContent}getTextCharset(){return this.textCharset}getHtmlBody(){return this.htmlContent}getHtmlCharset(){return this.htmlCharset}getAttachments(){return[...this.attachments]}tryAutoGenerateText(e){try{const t=p(e);t&&!this.textContent&&this.text(t),this.logger&&this.logger.debug("Auto-generated text content from HTML template")}catch(t){this.logger&&this.logger.warn("Failed to auto-generate text from HTML template",t)}}throwAndLogError(e,t){const s=new Error(e);throw this.logger&&this.logger.error(t??e),s}}export{M as MailMessage,M as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var g=Object.defineProperty;var s=(t,e)=>g(t,"name",{value:e,configurable:!0});var l=Object.defineProperty,m=s((t,e)=>l(t,"name",{value:e,configurable:!0}),"s");const r=m((t,e)=>t.timestamp.getTime()-e.timestamp.getTime(),"byTimestamp");class n{static{s(this,"i")}static{m(this,"MemoryEventStore")}static UNKEYED="__unkeyed";byMessage=new Map;append(e){const a=e.messageId??n.UNKEYED,i=this.byMessage.get(a);i?i.push(e):this.byMessage.set(a,[e])}timeline(e){return[...this.byMessage.get(e)??[]].toSorted(r)}all(){return[...this.byMessage.values()].flat().toSorted(r)}clear(){this.byMessage.clear()}}export{n as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n=Object.defineProperty;var o=(i,e)=>n(i,"name",{value:e,configurable:!0});var u=Object.defineProperty,d=o((i,e)=>u(i,"name",{value:e,configurable:!0}),"n");class h{static{o(this,"MemoryQueue")}static{d(this,"MemoryQueue")}jobs=new Map;visibilityTimeout;now;sequence=0;constructor(e={}){this.visibilityTimeout=e.visibilityTimeout??3e4,this.now=e.now??Date.now}enqueue(e,t={}){this.sequence+=1;const s=`job_${String(this.sequence)}`,r=t.scheduledAt instanceof Date?t.scheduledAt.getTime():t.scheduledAt??this.now();return this.jobs.set(s,{attempts:0,id:s,message:e,reservedUntil:0,scheduledAt:r}),s}reserve(){const e=this.now();for(const t of this.jobs.values())if(t.scheduledAt<=e&&t.reservedUntil<=e)return t.reservedUntil=e+this.visibilityTimeout,{attempts:t.attempts,id:t.id,message:t.message,scheduledAt:t.scheduledAt}}ack(e){this.jobs.delete(e)}retry(e,t=0){const s=this.jobs.get(e);s&&(s.attempts+=1,s.reservedUntil=0,s.scheduledAt=this.now()+t)}size(){return this.jobs.size}}export{h as MemoryQueue};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var d=Object.defineProperty;var n=(t,e)=>d(t,"name",{value:e,configurable:!0});var u=Object.defineProperty,o=n((t,e)=>u(t,"name",{value:e,configurable:!0}),"o");const s=o(t=>t.trim().toLowerCase(),"normalize");class h{static{n(this,"a")}static{o(this,"MemorySuppressionStore")}entries=new Map;constructor(e){if(e)for(const{address:a,metadata:i,reason:r}of e)this.add(a,r,i)}add(e,a,i){const r=s(e);this.entries.set(r,{address:r,createdAt:new Date,metadata:i,reason:a})}get(e){return this.entries.get(s(e))}has(e){return this.entries.has(s(e))}list(){return this.entries.values()}remove(e){return this.entries.delete(s(e))}get size(){return this.entries.size}}export{h as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var b=Object.defineProperty;var d=(e,t)=>b(e,"name",{value:t,configurable:!0});var f=Object.defineProperty,o=d((e,t)=>f(e,"name",{value:t,configurable:!0}),"o");const M=o(e=>new Promise(t=>{setTimeout(t,e)}),"defaultSleep"),v={"aws-ses":14,mailgun:100,postmark:100,resend:10,sendgrid:100},T=o(e=>{const{burst:t,now:c=Date.now,rate:a,sleep:w=M}=e;if(a<=0||Number.isNaN(a))throw new TypeError("rateLimitMiddleware: `rate` must be a positive number");const l=t??a;let i=l,m=c(),u=Promise.resolve();const p=o(async()=>{const n=o(()=>{const r=c(),s=(r-m)/1e3;i=Math.min(l,i+s*a),m=r},"refill");for(n();i<1;){const r=1-i;await w(Math.ceil(r/a*1e3)),n()}i-=1},"acquire");return async(n,r)=>{const s=u.then(()=>p());return u=s.catch(()=>{}),await s,r(n)}},"rateLimitMiddleware");export{v as RATE_LIMIT_PRESETS,T as rateLimitMiddleware};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var K=Object.defineProperty;var g=(s,e)=>K(s,"name",{value:e,configurable:!0});import{createRequire as U}from"node:module";import{
|
|
1
|
+
var K=Object.defineProperty;var g=(s,e)=>K(s,"name",{value:e,configurable:!0});import{createRequire as U}from"node:module";import{E as $}from"./readFile-BkNfutxp-BS8Q2183.js";import{fromBER as S,OctetString as T}from"asn1js";import{Certificate as j,EnvelopedData as z,EncryptedContentInfo as J,id_ContentType_Data as Q,RecipientInfo as W,KeyTransRecipientInfo as X,IssuerAndSerialNumber as Y,AlgorithmIdentifier as x,ContentInfo as Z,id_ContentType_EnvelopedData as ee}from"pkijs";const q=U(import.meta.url),h=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,H=g(s=>{if(typeof h<"u"&&h.versions&&h.versions.node){const[e,t]=h.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return h.getBuiltinModule(s)}return q(s)},"__cjs_getBuiltinModule"),{randomBytes:B,createCipheriv:L,createPublicKey:G,publicEncrypt:V}=H("node:crypto");var te=Object.defineProperty,y=g((s,e)=>te(s,"name",{value:e,configurable:!0}),"l");const w=globalThis.Buffer!==void 0,N=y(s=>{const e=s.replaceAll(/-----BEGIN[^-]+-----/g,"").replaceAll(/-----END[^-]+-----/g,"").replaceAll(/\s/g,"");if(w)return Buffer.from(e,"base64");const t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r+=1)n[r]=t.charCodeAt(r);return n},"pemToDer"),R=y((s,e)=>{let t;if(w)t=Buffer.from(s).toString("base64");else{const r=new Uint8Array(s);let u="";const o=8192;for(let i=0;i<r.length;i+=o){const m=r.subarray(i,Math.min(i+o,r.length));u+=String.fromCharCode(...m)}t=btoa(u)}const n=t.match(/.{1,64}/g)??[];return`-----BEGIN ${e}-----
|
|
2
2
|
${n.join(`
|
|
3
3
|
`)}
|
|
4
4
|
-----END ${e}-----
|
|
5
|
-
`},"derToPem");class a{static{g(this,"SmimeEncrypter")}static{y(this,"SmimeEncrypter")}static collectRecipients(e){const t=[],n=y(r=>{if(!r)return;const u=Array.isArray(r)?r:[r];for(const o of u){const i=typeof o=="string"?o:o.email;i&&t.push(i)}},"extractEmails");return n(e.to),n(e.cc),n(e.bcc),[...new Set(t)]}static formatAddress(e){return typeof e=="string"?e:e.name?`"${e.name}" <${e.email}>`:e.email}static formatAddresses(e){return(Array.isArray(e)?e:[e]).map(t=>a.formatAddress(t)).join(", ")}options;constructor(e){this.options=e}async encrypt(e){const t=a.collectRecipients(e),n=[];if(typeof this.options.certificates=="string"){const c=await
|
|
5
|
+
`},"derToPem");class a{static{g(this,"SmimeEncrypter")}static{y(this,"SmimeEncrypter")}static collectRecipients(e){const t=[],n=y(r=>{if(!r)return;const u=Array.isArray(r)?r:[r];for(const o of u){const i=typeof o=="string"?o:o.email;i&&t.push(i)}},"extractEmails");return n(e.to),n(e.cc),n(e.bcc),[...new Set(t)]}static formatAddress(e){return typeof e=="string"?e:e.name?`"${e.name}" <${e.email}>`:e.email}static formatAddresses(e){return(Array.isArray(e)?e:[e]).map(t=>a.formatAddress(t)).join(", ")}options;constructor(e){this.options=e}async encrypt(e){const t=a.collectRecipients(e),n=[];if(typeof this.options.certificates=="string"){const c=await $(this.options.certificates,{encoding:"utf8"}),f=N(c),l=S(f);if(l.offset===-1)throw new Error("Failed to parse certificate: Invalid ASN.1 structure");n.push(new j({schema:l.result}))}else{const c=t.map(async f=>{const l=this.options.certificates[f];if(!l)throw new Error(`No certificate found for recipient: ${f}`);const E=await $(l,{encoding:"utf8"}),v=N(E),p=S(v);if(p.offset===-1)throw new Error(`Failed to parse certificate for ${f}: Invalid ASN.1 structure`);return new j({schema:p.result})});n.push(...await Promise.all(c))}const r=await this.buildMessage(e),u=new TextEncoder().encode(r),o=new z({version:0});o.encryptedContentInfo=new J({contentType:Q});const i=(this.options.algorithm??"aes-256-cbc").toLowerCase();if(i==="3des"||i==="des-ede3-cbc")throw new Error("3DES/DES-EDE3-CBC is deprecated and insecure (Sweet32 vulnerability). Please use AES-256-CBC, AES-192-CBC, or AES-128-CBC instead.");let m,d;switch(i){case"aes128":case"aes-128-cbc":{m="2.16.840.1.101.3.4.1.2",d=16;break}case"aes192":case"aes-192-cbc":{m="2.16.840.1.101.3.4.1.22",d=24;break}default:{m="2.16.840.1.101.3.4.1.42",d=32;break}}const A=B(d),D=w?A:new Uint8Array(A),C=B(16),P=w?C:new Uint8Array(C),I=L(`aes-${d*8}-cbc`,A,C),_=Buffer.from(u),k=[I.update(_),I.final()],b=Buffer.concat(k);o.encryptedContentInfo.encryptedContent=new T({valueHex:b.buffer.slice(b.byteOffset,b.byteOffset+b.byteLength)});const M=await Promise.all(n.map(async c=>{const f=c.toSchema().toBER(!1),l=R(f,"CERTIFICATE"),E=G(l),v=Buffer.from(D),p=V({key:E,padding:1},v);return new W({value:new X({encryptedKey:new T({valueHex:p.buffer.slice(p.byteOffset,p.byteOffset+p.byteLength)}),keyEncryptionAlgorithm:new x({algorithmId:"1.2.840.113549.1.1.1"}),rid:new Y({issuer:c.issuer,serialNumber:c.serialNumber}),version:0}),variant:0})}));o.recipientInfos.push(...M),o.encryptedContentInfo.contentEncryptionAlgorithm=new x({algorithmId:m,algorithmParams:new T({valueHex:P.buffer})});const O=new Z({content:o.toSchema(),contentType:ee}).toSchema().toBER(!1),F=R(O,"PKCS7");return{...e,headers:{...e.headers,"Content-Disposition":"attachment; filename=smime.p7m","Content-Transfer-Encoding":"base64","Content-Type":"application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m"},html:void 0,text:F}}async buildMessage(e){const t=[`From: ${a.formatAddress(e.from)}`,`To: ${a.formatAddresses(e.to)}`,...e.cc?[`Cc: ${a.formatAddresses(e.cc)}`]:[]];if(e.replyTo&&t.push(`Reply-To: ${a.formatAddress(e.replyTo)}`),t.push(`Subject: ${e.subject}`,"MIME-Version: 1.0"),e.headers)for(const[n,r]of Object.entries(e.headers))t.push(`${n}: ${r}`);return e.html?t.push("Content-Type: text/html; charset=utf-8"):e.text&&t.push("Content-Type: text/plain; charset=utf-8"),t.push(""),e.html?t.push(e.html):e.text&&t.push(e.text),t.join(`\r
|
|
6
6
|
`)}}const ae=y(s=>new a(s),"createSmimeEncrypter");export{a as SmimeEncrypter,ae as createSmimeEncrypter};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var L=Object.defineProperty;var g=(n,e)=>L(n,"name",{value:e,configurable:!0});import{createRequire as V}from"node:module";import{
|
|
1
|
+
var L=Object.defineProperty;var g=(n,e)=>L(n,"name",{value:e,configurable:!0});import{createRequire as V}from"node:module";import{E as b}from"./readFile-BkNfutxp-BS8Q2183.js";import{fromBER as x,ObjectIdentifier as Y,OctetString as B,UTCTime as Z}from"asn1js";import{Certificate as N,SignedData as ee,EncapsulatedContentInfo as te,id_ContentType_Data as D,SignerInfo as re,AlgorithmIdentifier as P,IssuerAndSerialNumber as ne,id_sha256 as se,SignedAndUnsignedAttributes as oe,Attribute as A,ContentInfo as ie,id_ContentType_SignedData as ae}from"pkijs";import{a as ce}from"./generate-boundary-Cx8nXYS0.js";const z=V(import.meta.url),u=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,J=g(n=>{if(typeof u<"u"&&u.versions&&u.versions.node){const[e,t]=u.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return u.getBuiltinModule(n)}return z(n)},"__cjs_getBuiltinModule"),{createPrivateKey:I,createHash:Q,createSign:W,randomBytes:X}=J("node:crypto");var le=Object.defineProperty,y=g((n,e)=>le(n,"name",{value:e,configurable:!0}),"u");const pe="1.2.840.113549.1.9.3",ue="1.2.840.113549.1.9.4",fe="1.2.840.113549.1.9.5",me="1.2.840.113549.1.1.1",de={v1:1},he={v1:1},f=globalThis.Buffer!==void 0,M=y(n=>{const e=n.replaceAll(/-----BEGIN[^-]+-----/g,"").replaceAll(/-----END[^-]+-----/g,"").replaceAll(/\s/g,"");if(f)return Buffer.from(e,"base64");const t=atob(e),o=new Uint8Array(t.length);for(let r=0;r<t.length;r+=1)o[r]=t.codePointAt(r);return o},"pemToDer"),ge=y((n,e)=>{let t;if(f)t=Buffer.from(n).toString("base64");else{const r=new Uint8Array(n);let s="";const a=8192;for(let i=0;i<r.length;i+=a){const d=r.subarray(i,Math.min(i+a,r.length));s+=String.fromCharCode(...d)}t=btoa(s)}const o=t.match(/.{1,64}/g)??[];return`-----BEGIN ${e}-----
|
|
2
2
|
${o.join(`
|
|
3
3
|
`)}
|
|
4
4
|
-----END ${e}-----
|
|
5
|
-
`},"derToPem");class m{static{g(this,"SmimeSigner")}static{y(this,"SmimeSigner")}static formatAddress(e){return e.name?`"${e.name.replaceAll("\\","\\\\").replaceAll('"',String.raw`\"`)}" <${e.email}>`:e.email}options;constructor(e){this.options=e}async sign(e){const t=await b(this.options.certificate,{encoding:"utf8"}),o=await b(this.options.privateKey,{encoding:"utf8"}),r=M(t),s=
|
|
5
|
+
`},"derToPem");class m{static{g(this,"SmimeSigner")}static{y(this,"SmimeSigner")}static formatAddress(e){return e.name?`"${e.name.replaceAll("\\","\\\\").replaceAll('"',String.raw`\"`)}" <${e.email}>`:e.email}options;constructor(e){this.options=e}async sign(e){const t=await b(this.options.certificate,{encoding:"utf8"}),o=await b(this.options.privateKey,{encoding:"utf8"}),r=M(t),s=x(r);if(s.offset===-1)throw new Error("Failed to parse certificate: Invalid ASN.1 structure");const a=new N({schema:s.result});let i;try{i=this.options.passphrase?I({key:o,passphrase:this.options.passphrase}):I(o)}catch(c){throw new Error(`Failed to parse private key: ${c.message}`)}const d=[];if(this.options.intermediateCerts){const c=this.options.intermediateCerts.map(async j=>{const q=await b(j,{encoding:"utf8"}),G=M(q),E=x(G);if(E.offset===-1)throw new Error(`Failed to parse intermediate certificate ${j}: Invalid ASN.1 structure`);return new N({schema:E.result})});d.push(...await Promise.all(c))}const v=this.buildMessage(e),$=new TextEncoder().encode(v),h=new ee({version:de.v1});h.encapContentInfo=new te({eContentType:D});const w=new re({digestAlgorithm:new P({algorithmId:se}),sid:new ne({issuer:a.issuer,serialNumber:a.serialNumber}),signatureAlgorithm:new P({algorithmId:me}),version:he.v1}),C=Q("sha256");C.update(f?Buffer.from($):$);const R=C.digest(),U=new Uint8Array(R),T=new oe({attributes:[new A({type:pe,values:[new Y({value:D})]}),new A({type:ue,values:[new B({valueHex:U.buffer.slice(0)})]}),new A({type:fe,values:[new Z({valueDate:new Date})]})]});w.signedAttrs=T;const S=T.toSchema().toBER(!1),k=f?Buffer.from(S):new Uint8Array(S),_=W("RSA-SHA256");_.update(k);const l=_.sign(i),O=f?l.buffer.slice(l.byteOffset,l.byteOffset+l.byteLength):l.buffer;w.signature=new B({valueHex:O}),h.signerInfos.push(w),h.certificates=[a,...d];const F=new ie({content:h.toSchema(),contentType:ae}).toSchema().toBER(!1),H=ge(F,"PKCS7"),p=`----_=_NextPart_${Date.now()}_${X(8).toString("hex")}`,K=[`Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="${p}"`,"",`--${p}`,v,`--${p}`,"Content-Type: application/pkcs7-signature; name=smime.p7s","Content-Transfer-Encoding: base64","Content-Disposition: attachment; filename=smime.p7s","",H.split(`
|
|
6
6
|
`).filter(c=>c.trim()&&!c.includes("-----")).join(""),`--${p}--`].join(`\r
|
|
7
7
|
`);return{...e,headers:{...e.headers,"Content-Type":`multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="${p}"`},html:void 0,text:K}}buildMessage(e){const t=[`From: ${m.formatAddress(e.from)}`,`To: ${this.formatAddresses(e.to)}`];if(e.cc&&t.push(`Cc: ${this.formatAddresses(e.cc)}`),e.replyTo&&t.push(`Reply-To: ${m.formatAddress(e.replyTo)}`),t.push(`Subject: ${e.subject}`,"MIME-Version: 1.0"),e.headers)for(const[a,i]of Object.entries(e.headers))t.push(`${a}: ${i}`);const o=!!e.text,r=!!e.html;let s;return o&&r?(s=ce(),t.push(`Content-Type: multipart/alternative; boundary="${s}"`)):r?t.push("Content-Type: text/html; charset=utf-8"):t.push("Content-Type: text/plain; charset=utf-8"),t.push(""),o&&r&&s?t.push(`--${s}`,"Content-Type: text/plain; charset=utf-8","",e.text,"",`--${s}`,"Content-Type: text/html; charset=utf-8","",e.html,"",`--${s}--`):o?t.push(e.text):r&&t.push(e.html),t.join(`\r
|
|
8
8
|
`)}formatAddresses(e){return(Array.isArray(e)?e:[e]).map(t=>m.formatAddress(t)).join(", ")}}const Ce=y(n=>new m(n),"createSmimeSigner");export{m as SmimeSigner,Ce as createSmimeSigner};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var l=Object.defineProperty;var o=(e,t)=>l(e,"name",{value:t,configurable:!0});var i=Object.defineProperty,h=o((e,t)=>i(e,"name",{value:t,configurable:!0}),"r");const $=/<head[^<>]*>/i,m=/<html[^<>]*>/i,u=h((e,t={})=>{const s='<meta name="color-scheme" content="light dark"><meta name="supported-color-schemes" content="light dark">',d=t.styles?`<style>@media (prefers-color-scheme: dark){${t.styles}}</style>`:"",a=`${s}${d}`,c=$.exec(e);if(c){const r=c.index+c[0].length;return`${e.slice(0,r)}${a}${e.slice(r)}`}const n=m.exec(e);if(n){const r=n.index+n[0].length;return`${e.slice(0,r)}<head>${a}</head>${e.slice(r)}`}return`<head>${a}</head>${e}`},"addDarkModeSupport");export{u as addDarkModeSupport};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var t=Object.defineProperty;var r=(a,s)=>t(a,"name",{value:s,configurable:!0});import{f as A}from"./format-address-Cv6uWTS5.js";var o=Object.defineProperty,e=r((a,s)=>o(a,"name",{value:s,configurable:!0}),"t");const i=e(a=>A(a),"formatAddress"),l=e(a=>(Array.isArray(a)?a:[a]).map(s=>i(s)),"formatAddresses"),f=e(a=>{const s={email:a.email};return a.name&&(s.name=a.name),s},"formatSendGridAddress"),j=e(a=>(Array.isArray(a)?a:[a]).map(s=>f(s)),"formatSendGridAddresses"),P=e(a=>(Array.isArray(a)?a:[a]).map(s=>s.email),"formatAddressEmails"),n=e(a=>({email:a.email,...a.name&&{displayName:a.name}}),"formatAzureAddress"),z=e(a=>(Array.isArray(a)?a:[a]).map(s=>n(s)),"formatAzureAddresses"),y=e(a=>{const s={Email:a.email};return a.name&&(s.Name=a.name),s},"formatMailjetAddress"),G=e(a=>(Array.isArray(a)?a:[a]).map(s=>y(s)),"formatMailjetAddresses"),p=e((a,s="to")=>({email:a.email,...a.name&&{name:a.name},type:s}),"formatMandrillAddress"),S=e((a,s="to")=>(Array.isArray(a)?a:[a]).map(m=>p(m,s)),"formatMandrillAddresses"),d=e(a=>({address:a.email,...a.name&&{name:a.name}}),"formatPostalAddress"),b=e(a=>(Array.isArray(a)?a:[a]).map(s=>d(s)),"formatPostalAddresses"),v=e(a=>l(a),"formatMailpaceAddresses"),M=e(a=>d(a),"formatZeptomailAddress");e(a=>(Array.isArray(a)?a:[a]).map(s=>({email_address:M(s)})),"formatZeptomailAddresses");export{f as a,l as b,i as c,G as d,y as e,j as f,S as g,b as h,d as i,z as j,n as k,P as l,M as m,v as n};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var P=Object.defineProperty;var y=(i,r)=>P(i,"name",{value:r,configurable:!0});import{createRequire as I}from"node:module";import c from"./EmailError-zm2ffVav.js";import S from"./RequiredOptionError-CevW3u2K.js";import{s as _}from"./generate-message-id-D4uA8gkj.js";import{i as E}from"./headers-to-record-Qo124ImV.js";import{m as f}from"./make-request-CaT4d5oC.js";import{u as b}from"./retry-UPd8F62N.js";import{d as z}from"./validate-email-options-DPo3SgC0.js";import{defineProvider as k}from"./defineProvider-CtLH0VBE.js";import{c as q,h as w,P as K}from"./provider-base-BpHE_uK8.js";import{f as p,a as B}from"./address-formatter-CnPg51_n.js";const T=I(import.meta.url),m=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,$=y(i=>{if(typeof m<"u"&&m.versions&&m.versions.node){const[r,u]=m.versions.node.split(".").map(Number);if(r>22||r===22&&u>=3||r===20&&u>=16)return m.getBuiltinModule(i)}return T(i)},"__cjs_getBuiltinModule"),{Buffer:j}=$("node:buffer"),s="ahasend",C="https://api.ahasend.com",x=3e4,G=3,W=k((i={})=>{if(!i.apiKey)throw new S(s,"apiKey");const r={apiKey:i.apiKey,debug:i.debug??!1,endpoint:i.endpoint??C,retries:i.retries??G,timeout:i.timeout??x,...i.logger&&{logger:i.logger}},u=new K,n=q(s,i.logger);return{features:{attachments:!0,batchSending:!0,customHeaders:!0,html:!0,replyTo:!0,scheduling:!1,tagging:!0,templates:!0,tracking:!0},async getEmail(e){try{if(!e)return{error:new c(s,"Email ID is required to retrieve email details"),success:!1};await this.initialize();const o={Authorization:`Bearer ${r.apiKey}`,"Content-Type":"application/json"};n.debug("Retrieving email details",{id:e});const t=await b(async()=>f(`${r.endpoint}/emails/${e}`,{headers:o,method:"GET",timeout:r.timeout}),r.retries);return t.success?(n.debug("Email details retrieved successfully"),{data:t.data?.body,success:!0}):(n.debug("API request failed when retrieving email",t.error),{error:new c(s,`Failed to retrieve email: ${t.error instanceof Error?t.error.message:"Unknown error"}`,{cause:t.error}),success:!1})}catch(o){return{error:w(s,"retrieve email",o,n),success:!1}}},async initialize(){await u.ensureInitialized(async()=>{if(!await this.isAvailable())throw new c(s,"AhaSend API not available or invalid API key");n.debug("Provider initialized successfully")},s)},async isAvailable(){try{return n.debug("Checking AhaSend API availability"),!!(await f(`${r.endpoint}/v2/ping`,{headers:{Authorization:`Bearer ${r.apiKey}`,"Content-Type":"application/json"},method:"GET",timeout:r.timeout})).success}catch(e){return n.debug("Error checking availability:",e),!1}},name:s,options:r,async sendEmail(e){try{const o=z(e);if(o.length>0)return{error:new c(s,`Invalid email options: ${o.join(", ")}`),success:!1};await this.initialize();const t={from:{email:e.from.email,name:e.from.name},subject:e.subject,to:p(e.to)};if(e.html&&(t.html=e.html),e.text&&(t.text=e.text),e.cc&&(t.cc=p(e.cc)),e.bcc&&(t.bcc=p(e.bcc)),e.replyTo&&(t.replyTo=B(e.replyTo)),e.templateId&&(t.templateId=e.templateId,e.templateVariables&&(t.templateVariables=e.templateVariables)),e.tags&&e.tags.length>0&&(t.tags=e.tags),e.headers){const a=E(e.headers);t.headers=a}e.attachments&&e.attachments.length>0&&(t.attachments=await Promise.all(e.attachments.map(async a=>{let d;if(a.content)if(typeof a.content=="string")d=a.content;else if(a.content instanceof Promise){const A=await a.content;d=j.from(A).toString("base64")}else d=a.content.toString("base64");else if(a.raw)d=typeof a.raw=="string"?a.raw:a.raw.toString("base64");else throw new c(s,`Attachment ${a.filename} has no content`);return{content:d,contentType:a.contentType??"application/octet-stream",filename:a.filename,...a.cid&&{cid:a.cid}}}))),n.debug("Sending email via AhaSend API",{subject:t.subject,to:t.to});const v={Authorization:`Bearer ${r.apiKey}`,"Content-Type":"application/json"},l=await b(async()=>f(`${r.endpoint}/send`,{headers:v,method:"POST",timeout:r.timeout},JSON.stringify(t)),r.retries);if(!l.success)return n.debug("API request failed when sending email",l.error),{error:l.error??new c(s,"Failed to send email"),success:!1};const g=l.data?.body,h=g?.messageId??g?.id??_();return n.debug("Email sent successfully",{messageId:h}),{data:{messageId:h,provider:s,response:l.data,sent:!0,timestamp:new Date},success:!0}}catch(o){return{error:w(s,"send email",o,n),success:!1}}},async validateCredentials(){return this.isAvailable()}}});export{W as default};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var P=Object.defineProperty;var v=(a,e)=>P(a,"name",{value:e,configurable:!0});import{createRequire as q}from"node:module";import{E as G}from"./readFile-BkNfutxp-BS8Q2183.js";import{i as O}from"./headers-to-record-Qo124ImV.js";import{a as y}from"./format-address-Cv6uWTS5.js";const N=q(import.meta.url),p=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,x=v(a=>{if(typeof p<"u"&&p.versions&&p.versions.node){const[e,r]=p.versions.node.split(".").map(Number);if(e>22||e===22&&r>=3||e===20&&r>=16)return p.getBuiltinModule(a)}return N(a)},"__cjs_getBuiltinModule"),{Buffer:C}=x("node:buffer"),{createPublicKey:W,createHash:A,createPrivateKey:I,sign:V,createSign:F,verify:w}=x("node:crypto");var J=Object.defineProperty,c=v((a,e)=>J(a,"name",{value:e,configurable:!0}),"i");const k=/\s+/g,Q=/ $/,U=/^\s*i=(\d+)\s*;/,X=["from","to","cc","subject","date","message-id","mime-version"],m=c((a,e)=>`${a.toLowerCase()}:${e.replaceAll(k," ").trim()}`,"relaxedHeader"),z=c(a=>{let e=a.replaceAll(`\r
|
|
2
|
+
`,`
|
|
3
|
+
`).replaceAll("\r",`
|
|
4
|
+
`).split(`
|
|
5
|
+
`).map(r=>r.replaceAll(k," ").replace(Q,"")).join(`\r
|
|
6
|
+
`);for(;e.endsWith(`\r
|
|
7
|
+
`);)e=e.slice(0,-2);return e.length>0?`${e}\r
|
|
8
|
+
`:`\r
|
|
9
|
+
`},"relaxedBody"),E=c(a=>{const e={...a.headers?O(a.headers):{},From:y(a.from),Subject:a.subject,To:y(a.to)};return a.cc&&(e.Cc=y(a.cc)),e["MIME-Version"]??="1.0",e},"buildHeaders"),M=c(a=>{const e={};for(const r of a.split(";")){const s=r.indexOf("=");s!==-1&&(e[r.slice(0,s).trim()]=r.slice(s+1).trim())}return e},"parseArcTags"),B=c(a=>{const e=a.lastIndexOf("b=");return e===-1?a:a.slice(0,e+2)},"stripSignature"),K=c(a=>{const e=[a.text,a.html].filter(r=>r!==void 0).join(`
|
|
10
|
+
|
|
11
|
+
`);return A("sha256").update(z(e)).digest("base64")},"bodyHashOf"),_=c((a,e,r)=>r==="ed25519-sha256"?V(null,A("sha256").update(a).digest(),e).toString("base64"):F("RSA-SHA256").update(a).sign(e,"base64"),"signData"),H=c((a,e,r,s)=>{const t=C.from(e,"base64");try{return s==="ed25519-sha256"?w(null,A("sha256").update(a).digest(),r,t):w("RSA-SHA256",C.from(a),r,t)}catch{return!1}},"verifyData"),Y=c((a,e)=>{const r=e.instance??1,s=e.algorithm??"rsa-sha256",t=e.timestamp??Math.floor(Date.now()/1e3),n=E(a),d=(e.headersToSign??X).filter(i=>{const u=Object.keys(n).find(g=>g.toLowerCase()===i);return u!==void 0&&n[u]!==void 0&&n[u]!==""}),l=[`i=${String(r)}`,`a=${s}`,"c=relaxed/relaxed",`d=${e.domainName}`,`s=${e.keySelector}`,`t=${String(t)}`,`h=${d.join(":")}`,`bh=${K(a)}`,"b="].join("; "),o=`${d.map(i=>{const u=Object.keys(n).find(g=>g.toLowerCase()===i);return m(i,n[u]??"")}).join(`\r
|
|
12
|
+
`)}\r
|
|
13
|
+
${m("ARC-Message-Signature",l)}`;return{header:l,signBase:o}},"arcMessageSignatureBase"),Z=c((a,e,r)=>{const s=r.instance??1,t=r.algorithm??"rsa-sha256",n=r.timestamp??Math.floor(Date.now()/1e3),d=r.cv??"none",l=[`i=${String(s)}`,`a=${t}`,`cv=${d}`,`d=${r.domainName}`,`s=${r.keySelector}`,`t=${String(n)}`,"b="].join("; "),o=[m("ARC-Authentication-Results",a),m("ARC-Message-Signature",e),m("ARC-Seal",l)].join(`\r
|
|
14
|
+
`);return{header:l,signBase:o}},"arcSealBase"),ee=c(async(a,e)=>{let r=a;return r.startsWith("file://")&&(r=await G(r.slice(7),{encoding:"utf8"})),I({key:r,passphrase:e})},"loadPrivateKey"),ie=c(async(a,e)=>{const r=e.instance??1,s=e.cv??"none";if(r!==1)throw new Error(`signArc only supports an originating sealer (instance 1); received i=${String(r)}`);if(s!=="none")throw new Error(`signArc only supports cv=none for an originating sealer; received cv=${s}`);const t=e.algorithm??"rsa-sha256",n={...e,cv:"none",timestamp:e.timestamp??Math.floor(Date.now()/1e3)},d=await ee(e.privateKey,e.passphrase),l=`i=${String(r)}; ${e.authenticationResults}`,o=Y(a,n),i=`${o.header}${_(o.signBase,d,t)}`,u=Z(l,i,n),g=`${u.header}${_(u.signBase,d,t)}`,h={"ARC-Authentication-Results":l,"ARC-Message-Signature":i,"ARC-Seal":g};return{email:{...a,headers:{...a.headers?O(a.headers):{},...h}},headers:h}},"signArc"),oe=c((a,e,r)=>{const s=Object.fromEntries(Object.entries(e).map(([f,b])=>[f.toLowerCase(),b])),t=s["arc-message-signature"],n=s["arc-seal"],d=s["arc-authentication-results"];if(!t||!n||!d)return{components:{ams:!1,bodyHash:!1,seal:!1},reason:"missing-arc-headers",valid:!1};let l;try{l=typeof r.publicKey=="string"?W(r.publicKey):r.publicKey}catch{return{components:{ams:!1,bodyHash:!1,seal:!1},reason:"invalid-public-key",valid:!1}}const o=M(t),i=M(n);if(U.exec(d)?.[1]!=="1"||o.i!=="1"||i.i!=="1"||i.cv!=="none")return{components:{ams:!1,bodyHash:!1,seal:!1},cv:i.cv,reason:"unsupported-arc-instance",valid:!1};const u=o.a==="ed25519-sha256"?"ed25519-sha256":"rsa-sha256",g=i.a==="ed25519-sha256"?"ed25519-sha256":"rsa-sha256",h=o.bh!==void 0&&o.bh===K(a),$=E(a),T=`${(o.h??"").split(":").map(f=>f.trim().toLowerCase()).filter(Boolean).map(f=>{const b=Object.keys($).find(L=>L.toLowerCase()===f);return m(f,b?$[b]??"":"")}).join(`\r
|
|
15
|
+
`)}\r
|
|
16
|
+
${m("ARC-Message-Signature",B(t))}`,S=H(T,o.b??"",l,u),D=[m("ARC-Authentication-Results",d),m("ARC-Message-Signature",t),m("ARC-Seal",B(n))].join(`\r
|
|
17
|
+
`),j=H(D,i.b??"",l,g),R=S&&j&&h;return{components:{ams:S,bodyHash:h,seal:j},cv:i.cv,reason:R?void 0:"signature-mismatch",valid:R}},"verifyArc");export{Y as arcMessageSignatureBase,Z as arcSealBase,ie as signArc,oe as verifyArc};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var i=(e,t)=>s(e,"name",{value:t,configurable:!0});import{createRequire as m}from"node:module";import l from"./EmailError-zm2ffVav.js";const p=m(import.meta.url),a=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,d=i(e=>{if(typeof a<"u"&&a.versions&&a.versions.node){const[t,n]=a.versions.node.split(".").map(Number);if(t>22||t===22&&n>=3||t===20&&n>=16)return a.getBuiltinModule(e)}return p(e)},"__cjs_getBuiltinModule"),{Buffer:f}=d("node:buffer");var u=Object.defineProperty,o=i((e,t)=>u(e,"name",{value:t,configurable:!0}),"o");const c=o(async(e,t)=>{let n;if(e.content)if(typeof e.content=="string")n=e.content;else if(e.content instanceof Promise){const r=await e.content;n=f.from(r).toString("base64")}else n=e.content.toString("base64");else if(e.raw)n=typeof e.raw=="string"?e.raw:e.raw.toString("base64");else throw new l(t,`Attachment ${e.filename} has no content`);return n},"processAttachmentContent"),_=o(async(e,t)=>({content:await c(e,t),contentType:e.contentType??"application/octet-stream",disposition:e.contentDisposition??"attachment",filename:e.filename,...e.cid&&{contentId:e.cid}}),"createStandardAttachment"),b=o(async(e,t)=>({content:await c(e,t),disposition:e.contentDisposition??"attachment",filename:e.filename,type:e.contentType??"application/octet-stream",...e.cid&&{content_id:e.cid}}),"createSendGridAttachment"),w=o(async(e,t)=>({Content:await c(e,t),ContentType:e.contentType??"application/octet-stream",Name:e.filename,...e.cid&&{ContentID:e.cid}}),"createPostmarkAttachment"),A=o(async(e,t,n)=>({content:await c(e,t),key:`attachment[${n}]`}),"createMailgunAttachment");export{A as a,w as b,b as c,_ as d};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var k=Object.defineProperty;var w=(n,l)=>k(n,"name",{value:l,configurable:!0});import{createRequire as z}from"node:module";import u from"./EmailError-zm2ffVav.js";import v from"./RequiredOptionError-CevW3u2K.js";import{s as j}from"./generate-message-id-D4uA8gkj.js";import{i as _}from"./headers-to-record-Qo124ImV.js";import{m as h}from"./make-request-CaT4d5oC.js";import{u as T}from"./retry-UPd8F62N.js";import{d as B}from"./validate-email-options-DPo3SgC0.js";import{defineProvider as C}from"./defineProvider-CtLH0VBE.js";import{c as E,P as q,h as S}from"./provider-base-BpHE_uK8.js";import{j as y,k as R}from"./address-formatter-CnPg51_n.js";const I=z(import.meta.url),f=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,P=w(n=>{if(typeof f<"u"&&f.versions&&f.versions.node){const[l,t]=f.versions.node.split(".").map(Number);if(l>22||l===22&&t>=3||l===20&&t>=16)return f.getBuiltinModule(n)}return I(n)},"__cjs_getBuiltinModule"),{Buffer:p}=P("node:buffer"),i="azure",x=3e4,O=3,V=C((n={})=>{if(!n.region)throw new v(i,"region");if(!n.connectionString&&!n.accessToken)throw new v(i,"connectionString or accessToken");const l=n.endpoint??`https://${n.region}.communication.azure.com`,t={debug:n.debug??!1,endpoint:l,region:n.region,retries:n.retries??O,timeout:n.timeout??x,...n.connectionString&&{connectionString:n.connectionString},...n.accessToken&&{accessToken:n.accessToken},...n.logger&&{logger:n.logger}},g=new q,a=E(i,n.logger);return{features:{attachments:!0,batchSending:!1,customHeaders:!0,html:!0,replyTo:!0,scheduling:!1,tagging:!1,templates:!0,tracking:!1},async getEmail(e){try{if(!e)return{error:new u(i,"Email ID is required to retrieve email details"),success:!1};await g.ensureInitialized(()=>this.initialize(),i);const o={"Content-Type":"application/json"};if(t.accessToken)o.Authorization=`Bearer ${t.accessToken}`;else if(t.connectionString){const c=t.connectionString.match(/endpoint=([^;]+);accesskey=([^;]+)/);c&&(o.Authorization=`Bearer ${c[2]}`)}a.debug("Retrieving email details",{id:e});const r=await T(async()=>h(`${t.endpoint}/emails/${e}`,{headers:o,method:"GET",timeout:t.timeout}),t.retries);return r.success?(a.debug("Email details retrieved successfully"),{data:r.data?.body,success:!0}):(a.debug("API request failed when retrieving email",r.error),{error:new u(i,`Failed to retrieve email: ${r.error instanceof Error?r.error.message:"Unknown error"}`,{cause:r.error}),success:!1})}catch(o){return{error:S(i,"retrieve email",o,a),success:!1}}},async initialize(){await g.ensureInitialized(async()=>{if(!await this.isAvailable())throw new u(i,"Azure Communication Services API not available or invalid credentials");a.debug("Provider initialized successfully")},i)},async isAvailable(){try{const e={"Content-Type":"application/json"};if(t.accessToken)e.Authorization=`Bearer ${t.accessToken}`;else if(t.connectionString){const c=t.connectionString.match(/endpoint=([^;]+);accesskey=([^;]+)/);if(c)e.Authorization=`Bearer ${c[2]}`;else return!1}else return!1;a.debug("Checking Azure Communication Services API availability");const o=await h(`${t.endpoint}/emails:send`,{headers:e,method:"POST",timeout:t.timeout},JSON.stringify({}));if(o.success)return!0;const r=o.data?.statusCode;return r===401||r===403?!1:r===400}catch(e){if(a.debug("Error checking availability:",e),e instanceof Error){const o=e.message;if(o.includes("401")||o.includes("403"))return!1}return!1}},name:i,options:t,async sendEmail(e){try{const o=B(e);if(o.length>0)return{error:new u(i,`Invalid email options: ${o.join(", ")}`),success:!1};await g.ensureInitialized(()=>this.initialize(),i);const r={content:{subject:e.subject},recipients:{to:y(e.to)},senderAddress:e.from.email};if(e.html&&(r.content.html=e.html),e.text&&(r.content.plainText=e.text),e.cc&&(r.recipients.cc=y(e.cc)),e.bcc&&(r.recipients.bcc=y(e.bcc)),e.replyTo&&(r.replyTo=R(e.replyTo).email),e.importance&&(r.importance=e.importance),e.headers){const s=_(e.headers);r.headers=s}e.attachments&&e.attachments.length>0&&(r.attachments=await Promise.all(e.attachments.map(async s=>{let d;if(s.content)if(typeof s.content=="string")d=p.from(s.content,"utf8").toString("base64");else if(s.content&&typeof s.content.then=="function"){const A=await s.content;d=p.from(A).toString("base64")}else d=s.content.toString("base64");else if(s.raw)d=typeof s.raw=="string"?p.from(s.raw,"utf8").toString("base64"):s.raw.toString("base64");else throw new u(i,`Attachment ${s.filename} has no content`);return{contentInBase64:d,contentType:s.contentType??"application/octet-stream",name:s.filename}}))),a.debug("Sending email via Azure Communication Services API",{subject:r.content.subject,to:r.recipients.to});const c={"Content-Type":"application/json"};if(t.accessToken)c.Authorization=`Bearer ${t.accessToken}`;else if(t.connectionString){const s=t.connectionString.match(/endpoint=([^;]+);accesskey=([^;]+)/);if(s)c.Authorization=`Bearer ${s[2]}`;else return{error:new u(i,"Invalid connection string format"),success:!1}}const m=await T(async()=>h(`${t.endpoint}/emails:send`,{headers:c,method:"POST",timeout:t.timeout},JSON.stringify(r)),t.retries);if(!m.success)return a.debug("API request failed when sending email",m.error),{error:m.error??new u(i,"Failed to send email"),success:!1};const b=m.data?.body?.messageId??j();return a.debug("Email sent successfully",{messageId:b}),{data:{messageId:b,provider:i,response:m.data,sent:!0,timestamp:new Date},success:!0}}catch(o){return{error:S(i,"send email",o,a),success:!1}}},async validateCredentials(){return this.isAvailable()}}});export{V as default};
|