sently 0.5.1 → 0.5.2

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.
Files changed (86) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/adapters/bun.js +1 -1
  3. package/dist/adapters/cf.js +2 -2
  4. package/dist/adapters/cf.js.map +1 -1
  5. package/dist/adapters/deno.js +1 -1
  6. package/dist/adapters/node.js +1 -1
  7. package/dist/auth/oauth2.js +2 -2
  8. package/dist/auth/oauth2.js.map +1 -1
  9. package/dist/{chunk-pjzsvsm6.js → chunk-9ea4hx7m.js} +3 -3
  10. package/dist/{chunk-pjzsvsm6.js.map → chunk-9ea4hx7m.js.map} +1 -1
  11. package/dist/{chunk-m2njnxre.js → chunk-9p4vev6j.js} +3 -3
  12. package/dist/{chunk-m2njnxre.js.map → chunk-9p4vev6j.js.map} +1 -1
  13. package/dist/{chunk-nhec1319.js → chunk-aeqxkeh3.js} +3 -3
  14. package/dist/{chunk-nhec1319.js.map → chunk-aeqxkeh3.js.map} +1 -1
  15. package/dist/{chunk-kdqxhybf.js → chunk-b0qkndv9.js} +3 -3
  16. package/dist/{chunk-kdqxhybf.js.map → chunk-b0qkndv9.js.map} +1 -1
  17. package/dist/{chunk-nj3wmg69.js → chunk-c8ya9em0.js} +2 -2
  18. package/dist/{chunk-nj3wmg69.js.map → chunk-c8ya9em0.js.map} +1 -1
  19. package/dist/{chunk-32dj0v9g.js → chunk-gxq2aamv.js} +2 -2
  20. package/dist/{chunk-32dj0v9g.js.map → chunk-gxq2aamv.js.map} +1 -1
  21. package/dist/{chunk-cvmk9h1r.js → chunk-k0gw3qmb.js} +3 -3
  22. package/dist/{chunk-cvmk9h1r.js.map → chunk-k0gw3qmb.js.map} +1 -1
  23. package/dist/{chunk-rhade81v.js → chunk-mg8m26nr.js} +2 -2
  24. package/dist/{chunk-rhade81v.js.map → chunk-mg8m26nr.js.map} +1 -1
  25. package/dist/chunk-pqp843mh.js +4 -0
  26. package/dist/chunk-pqp843mh.js.map +10 -0
  27. package/dist/chunk-q8k3m6qe.js +4 -0
  28. package/dist/chunk-q8k3m6qe.js.map +10 -0
  29. package/dist/{chunk-zwm5bfa4.js → chunk-qp4y0kp2.js} +2 -2
  30. package/dist/{chunk-zwm5bfa4.js.map → chunk-qp4y0kp2.js.map} +1 -1
  31. package/dist/{chunk-ntqmn6pe.js → chunk-vws105eb.js} +2 -2
  32. package/dist/{chunk-ntqmn6pe.js.map → chunk-vws105eb.js.map} +1 -1
  33. package/dist/chunk-zkczgj2c.js +4 -0
  34. package/dist/{chunk-j5m37k1c.js.map → chunk-zkczgj2c.js.map} +2 -2
  35. package/dist/core/smtp.js +2 -2
  36. package/dist/core/smtp.js.map +1 -1
  37. package/dist/detect.js +2 -2
  38. package/dist/detect.js.map +1 -1
  39. package/dist/dkim.js +2 -2
  40. package/dist/dkim.js.map +2 -2
  41. package/dist/idempotency.js +2 -2
  42. package/dist/idempotency.js.map +1 -1
  43. package/dist/mailer.js +2 -2
  44. package/dist/mailer.js.map +1 -1
  45. package/dist/plugins/react.js +2 -2
  46. package/dist/plugins/react.js.map +1 -1
  47. package/dist/plugins/template.js +1 -1
  48. package/dist/pool/pool.js +2 -2
  49. package/dist/pool/pool.js.map +1 -1
  50. package/dist/react.js +4 -3
  51. package/dist/transports/brevo.js +2 -2
  52. package/dist/transports/brevo.js.map +1 -1
  53. package/dist/transports/mailgun.js +2 -2
  54. package/dist/transports/mailgun.js.map +1 -1
  55. package/dist/transports/postmark.js +2 -2
  56. package/dist/transports/postmark.js.map +1 -1
  57. package/dist/transports/preview.js +2 -2
  58. package/dist/transports/preview.js.map +1 -1
  59. package/dist/transports/resend.js +2 -2
  60. package/dist/transports/resend.js.map +1 -1
  61. package/dist/transports/retry.js +2 -2
  62. package/dist/transports/retry.js.map +1 -1
  63. package/dist/transports/sendgrid.js +2 -2
  64. package/dist/transports/sendgrid.js.map +1 -1
  65. package/dist/transports/ses.js +2 -2
  66. package/dist/transports/ses.js.map +1 -1
  67. package/dist/transports/smtp.js +2 -2
  68. package/dist/transports/smtp.js.map +1 -1
  69. package/dist/webhooks/brevo.js +3 -0
  70. package/dist/webhooks/brevo.js.map +10 -0
  71. package/dist/webhooks/mailgun.js +3 -0
  72. package/dist/webhooks/mailgun.js.map +10 -0
  73. package/dist/webhooks/postmark.js +3 -0
  74. package/dist/webhooks/postmark.js.map +10 -0
  75. package/dist/webhooks/resend.js +3 -0
  76. package/dist/webhooks/resend.js.map +10 -0
  77. package/dist/webhooks/sendgrid.js +3 -0
  78. package/dist/webhooks/sendgrid.js.map +10 -0
  79. package/dist/webhooks/ses.js +3 -0
  80. package/dist/webhooks/ses.js.map +10 -0
  81. package/dist/webhooks/timing-safe-equal.js +3 -0
  82. package/dist/{react.js.map → webhooks/timing-safe-equal.js.map} +1 -1
  83. package/dist/webhooks.js +13 -3
  84. package/package.json +1 -1
  85. package/dist/chunk-j5m37k1c.js +0 -4
  86. package/dist/webhooks.js.map +0 -9
@@ -1,3 +1,3 @@
1
- import{l as N}from"../chunk-cvmk9h1r.js";import{n as F,p as J}from"../chunk-kdqxhybf.js";import{G as M}from"../chunk-32dj0v9g.js";import"../chunk-rhade81v.js";class L extends Error{statusCode;apiError;constructor(q,z,C){super(q);this.statusCode=z;this.apiError=C;this.name="SendGridError"}}class O{apiKey;constructor(q){this.apiKey=q.apiKey}buildPersonalization(q){return{to:F(q.to).map((z)=>({email:z.address,name:z.name})),...q.cc?{cc:F(q.cc).map((z)=>({email:z.address,name:z.name}))}:{},...q.bcc?{bcc:F(q.bcc).map((z)=>({email:z.address,name:z.name}))}:{},subject:q.subject,...q.headers?{headers:q.headers}:{}}}buildContent(q){return[...q.text?[{type:"text/plain",value:q.text}]:[],...q.html?[{type:"text/html",value:q.html}]:[]]}toSendResult(q,z,C="Accepted"){let H=F(q.from)[0];return{messageId:z,accepted:J(q.to),rejected:[],response:C,envelope:{from:H?.address??"",to:[...J(q.to),...q.cc?J(q.cc):[],...q.bcc?J(q.bcc):[]]}}}async send(q){let z=await N(q.attachments),C=F(q.from)[0],H={personalizations:[this.buildPersonalization(q)],from:C?{email:C.address,...C.name?{name:C.name}:{}}:{email:""},...q.replyTo?{reply_to:F(q.replyTo).map((w)=>({email:w.address,name:w.name}))[0]}:{},content:this.buildContent(q),...z.length>0?{attachments:z.map((w)=>({filename:w.filename,type:w.contentType??"application/octet-stream",content:w.content instanceof Uint8Array?M(w.content).replace(/\r\n/g,""):w.content,...w.contentId?{content_id:w.contentId}:{},disposition:w.inline?"inline":"attachment"}))}:{}},D=await fetch("https://api.sendgrid.com/v3/mail/send",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(H)});if(!D.ok){let w=await D.text();throw new L("SendGrid API error",D.status,w)}let K=D.headers.get("x-message-id")??q.messageId??"";return this.toSendResult(q,K)}async sendBatch(q){if(q.length===0)return[];let z=q[0],C=F(z.from)[0],H={personalizations:q.map((w)=>this.buildPersonalization(w)),from:C?{email:C.address,...C.name?{name:C.name}:{}}:{email:""},...z.replyTo?{reply_to:F(z.replyTo).map((w)=>({email:w.address,name:w.name}))[0]}:{},content:this.buildContent(z)},D=await fetch("https://api.sendgrid.com/v3/mail/send",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(H)});if(!D.ok){let w=await D.text();throw new L("SendGrid API error",D.status,w)}let K=D.headers.get("x-message-id")??"";return q.map((w)=>this.toSendResult(w,K||w.messageId||""))}async verify(){try{let q=await fetch("https://api.sendgrid.com/v3/user/profile",{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!q.ok)return{ok:!1,provider:"sendgrid",message:await q.text().catch(()=>"")||`HTTP ${q.status}`};let z=await q.json();return{ok:!0,provider:"sendgrid",...z.username?{message:z.username}:{}}}catch(q){return{ok:!1,provider:"sendgrid",message:q instanceof Error?q.message:String(q)}}}}export{O as SendGridTransport,L as SendGridError};
1
+ import{s as N}from"../chunk-k0gw3qmb.js";import{u as F,w as J}from"../chunk-b0qkndv9.js";import{N as M}from"../chunk-gxq2aamv.js";import"../chunk-mg8m26nr.js";class L extends Error{statusCode;apiError;constructor(q,z,C){super(q);this.statusCode=z;this.apiError=C;this.name="SendGridError"}}class O{apiKey;constructor(q){this.apiKey=q.apiKey}buildPersonalization(q){return{to:F(q.to).map((z)=>({email:z.address,name:z.name})),...q.cc?{cc:F(q.cc).map((z)=>({email:z.address,name:z.name}))}:{},...q.bcc?{bcc:F(q.bcc).map((z)=>({email:z.address,name:z.name}))}:{},subject:q.subject,...q.headers?{headers:q.headers}:{}}}buildContent(q){return[...q.text?[{type:"text/plain",value:q.text}]:[],...q.html?[{type:"text/html",value:q.html}]:[]]}toSendResult(q,z,C="Accepted"){let H=F(q.from)[0];return{messageId:z,accepted:J(q.to),rejected:[],response:C,envelope:{from:H?.address??"",to:[...J(q.to),...q.cc?J(q.cc):[],...q.bcc?J(q.bcc):[]]}}}async send(q){let z=await N(q.attachments),C=F(q.from)[0],H={personalizations:[this.buildPersonalization(q)],from:C?{email:C.address,...C.name?{name:C.name}:{}}:{email:""},...q.replyTo?{reply_to:F(q.replyTo).map((w)=>({email:w.address,name:w.name}))[0]}:{},content:this.buildContent(q),...z.length>0?{attachments:z.map((w)=>({filename:w.filename,type:w.contentType??"application/octet-stream",content:w.content instanceof Uint8Array?M(w.content).replace(/\r\n/g,""):w.content,...w.contentId?{content_id:w.contentId}:{},disposition:w.inline?"inline":"attachment"}))}:{}},D=await fetch("https://api.sendgrid.com/v3/mail/send",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(H)});if(!D.ok){let w=await D.text();throw new L("SendGrid API error",D.status,w)}let K=D.headers.get("x-message-id")??q.messageId??"";return this.toSendResult(q,K)}async sendBatch(q){if(q.length===0)return[];let z=q[0],C=F(z.from)[0],H={personalizations:q.map((w)=>this.buildPersonalization(w)),from:C?{email:C.address,...C.name?{name:C.name}:{}}:{email:""},...z.replyTo?{reply_to:F(z.replyTo).map((w)=>({email:w.address,name:w.name}))[0]}:{},content:this.buildContent(z)},D=await fetch("https://api.sendgrid.com/v3/mail/send",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(H)});if(!D.ok){let w=await D.text();throw new L("SendGrid API error",D.status,w)}let K=D.headers.get("x-message-id")??"";return q.map((w)=>this.toSendResult(w,K||w.messageId||""))}async verify(){try{let q=await fetch("https://api.sendgrid.com/v3/user/profile",{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!q.ok)return{ok:!1,provider:"sendgrid",message:await q.text().catch(()=>"")||`HTTP ${q.status}`};let z=await q.json();return{ok:!0,provider:"sendgrid",...z.username?{message:z.username}:{}}}catch(q){return{ok:!1,provider:"sendgrid",message:q instanceof Error?q.message:String(q)}}}}export{O as SendGridTransport,L as SendGridError};
2
2
 
3
- //# debugId=86CABED9282C733164756E2164756E21
3
+ //# debugId=3B8238DEEE4DDF3C64756E2164756E21
@@ -5,6 +5,6 @@
5
5
  "/**\n * @module\n * SendGrid v3 HTTP API transport for sending email via api.sendgrid.com.\n *\n * @example\n * ```ts\n * import { SendGridTransport } from \"sently/transports/sendgrid\";\n * import { createMailer } from \"sently\";\n *\n * const mailer = await createMailer({\n * transport: new SendGridTransport({ apiKey: process.env.SENDGRID_API_KEY! }),\n * });\n *\n * await mailer.send({\n * from: \"sender@example.com\",\n * to: \"recipient@example.com\",\n * subject: \"Hello\",\n * text: \"Plain text body\",\n * });\n * ```\n */\nimport { extractEmails, parseAddresses } from \"../core/address.js\";\nimport { encodeBase64 } from \"../core/base64.js\";\nimport type { MailOptions, SendResult, Transport, VerifyResult } from \"../core/types.js\";\nimport { resolveAttachments } from \"./resolve-attachments.js\";\n\n/** SendGrid API configuration. */\nexport interface SendGridConfig {\n /** SendGrid API key (Bearer token). */\n apiKey: string;\n}\n\n/** Error thrown when the SendGrid API returns a non-success response. */\nexport class SendGridError extends Error {\n /** Creates a SendGrid API error with status code and response payload. */\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly apiError: unknown,\n ) {\n super(message);\n this.name = \"SendGridError\";\n }\n}\n\n/**\n * SendGrid v3 HTTP API transport.\n */\nexport class SendGridTransport implements Transport {\n /** SendGrid API key for Bearer authentication. */\n private readonly apiKey: string;\n\n /** Creates a SendGrid transport with the given API key. */\n constructor(config: SendGridConfig) {\n this.apiKey = config.apiKey;\n }\n\n /** Build a SendGrid personalization for one message. */\n private buildPersonalization(options: MailOptions): Record<string, unknown> {\n return {\n to: parseAddresses(options.to).map((addr) => ({ email: addr.address, name: addr.name })),\n ...(options.cc\n ? {\n cc: parseAddresses(options.cc).map((addr) => ({\n email: addr.address,\n name: addr.name,\n })),\n }\n : {}),\n ...(options.bcc\n ? {\n bcc: parseAddresses(options.bcc).map((addr) => ({\n email: addr.address,\n name: addr.name,\n })),\n }\n : {}),\n subject: options.subject,\n ...(options.headers ? { headers: options.headers } : {}),\n };\n }\n\n /** Build SendGrid content parts from text/html options. */\n private buildContent(options: MailOptions): Array<{ type: string; value: string }> {\n return [\n ...(options.text ? [{ type: \"text/plain\", value: options.text }] : []),\n ...(options.html ? [{ type: \"text/html\", value: options.html }] : []),\n ];\n }\n\n /** Map a SendGrid response to a normalized SendResult for one message. */\n private toSendResult(\n options: MailOptions,\n messageId: string,\n responseText = \"Accepted\",\n ): SendResult {\n const from = parseAddresses(options.from)[0];\n return {\n messageId,\n accepted: extractEmails(options.to),\n rejected: [],\n response: responseText,\n envelope: {\n from: from?.address ?? \"\",\n to: [\n ...extractEmails(options.to),\n ...(options.cc ? extractEmails(options.cc) : []),\n ...(options.bcc ? extractEmails(options.bcc) : []),\n ],\n },\n };\n }\n\n /** Sends an email via the SendGrid v3 HTTP API. */\n async send(options: MailOptions): Promise<SendResult> {\n const attachments = await resolveAttachments(options.attachments);\n const from = parseAddresses(options.from)[0];\n\n const body = {\n personalizations: [this.buildPersonalization(options)],\n from: from\n ? { email: from.address, ...(from.name ? { name: from.name } : {}) }\n : { email: \"\" },\n ...(options.replyTo\n ? {\n reply_to: parseAddresses(options.replyTo).map((addr) => ({\n email: addr.address,\n name: addr.name,\n }))[0],\n }\n : {}),\n content: this.buildContent(options),\n ...(attachments.length > 0\n ? {\n attachments: attachments.map((att) => ({\n filename: att.filename,\n type: att.contentType ?? \"application/octet-stream\",\n content:\n att.content instanceof Uint8Array\n ? encodeBase64(att.content).replace(/\\r\\n/g, \"\")\n : att.content,\n ...(att.contentId ? { content_id: att.contentId } : {}),\n disposition: att.inline ? \"inline\" : \"attachment\",\n })),\n }\n : {}),\n };\n\n const response = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const apiError = await response.text();\n throw new SendGridError(\"SendGrid API error\", response.status, apiError);\n }\n\n const messageId = response.headers.get(\"x-message-id\") ?? options.messageId ?? \"\";\n\n return this.toSendResult(options, messageId);\n }\n\n /** Send multiple messages in one request using SendGrid personalizations. */\n async sendBatch(messages: MailOptions[]): Promise<SendResult[]> {\n if (messages.length === 0) {\n return [];\n }\n\n const first = messages[0] as MailOptions;\n const from = parseAddresses(first.from)[0];\n\n const body = {\n personalizations: messages.map((message) => this.buildPersonalization(message)),\n from: from\n ? { email: from.address, ...(from.name ? { name: from.name } : {}) }\n : { email: \"\" },\n ...(first.replyTo\n ? {\n reply_to: parseAddresses(first.replyTo).map((addr) => ({\n email: addr.address,\n name: addr.name,\n }))[0],\n }\n : {}),\n content: this.buildContent(first),\n };\n\n const response = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const apiError = await response.text();\n throw new SendGridError(\"SendGrid API error\", response.status, apiError);\n }\n\n const messageId = response.headers.get(\"x-message-id\") ?? \"\";\n return messages.map((message) =>\n this.toSendResult(message, messageId || message.messageId || \"\"),\n );\n }\n\n /** Verifies the SendGrid API key by fetching the user profile. */\n async verify(): Promise<VerifyResult> {\n try {\n const response = await fetch(\"https://api.sendgrid.com/v3/user/profile\", {\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const apiError = await response.text().catch(() => \"\");\n return {\n ok: false,\n provider: \"sendgrid\",\n message: apiError || `HTTP ${response.status}`,\n };\n }\n\n const payload = (await response.json()) as { username?: string };\n return {\n ok: true,\n provider: \"sendgrid\",\n ...(payload.username ? { message: payload.username } : {}),\n };\n } catch (err) {\n return {\n ok: false,\n provider: \"sendgrid\",\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n"
6
6
  ],
7
7
  "mappings": "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",
8
- "debugId": "86CABED9282C733164756E2164756E21",
8
+ "debugId": "3B8238DEEE4DDF3C64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,7 +1,7 @@
1
- import{k as A}from"../chunk-nhec1319.js";import{l as k}from"../chunk-cvmk9h1r.js";import{n as x,o as R,p as P}from"../chunk-kdqxhybf.js";import{G as T}from"../chunk-32dj0v9g.js";import"../chunk-rhade81v.js";var M=new TextEncoder;async function z(C){let F=await crypto.subtle.digest("SHA-256",M.encode(C));return K(new Uint8Array(F))}async function W(C,F){let J=typeof C==="string"?M.encode(C):new Uint8Array(C),L=await crypto.subtle.importKey("raw",J,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),G=await crypto.subtle.sign("HMAC",L,M.encode(F));return new Uint8Array(G)}async function j(C){let{method:F,url:J,body:L,credentials:G}=C,X=new URL(J),Y=C._date??`${new Date().toISOString().replace(/[-:]/g,"").slice(0,15)}Z`,U=Y.slice(0,8),Z={...Object.fromEntries(Object.entries(C.headers).map(([O,E])=>[O.toLowerCase(),E.trim()])),host:X.host,"x-amz-date":Y};if(G.sessionToken)Z["x-amz-security-token"]=G.sessionToken;let $=Object.keys(Z).map((O)=>O.toLowerCase()).sort(),N=$.join(";"),_=`${$.map((O)=>`${O}:${Z[O]}`).join(`
1
+ import{r as A}from"../chunk-aeqxkeh3.js";import{s as k}from"../chunk-k0gw3qmb.js";import{u as x,v as R,w as P}from"../chunk-b0qkndv9.js";import{N as T}from"../chunk-gxq2aamv.js";import"../chunk-mg8m26nr.js";var M=new TextEncoder;async function z(C){let F=await crypto.subtle.digest("SHA-256",M.encode(C));return K(new Uint8Array(F))}async function W(C,F){let J=typeof C==="string"?M.encode(C):new Uint8Array(C),L=await crypto.subtle.importKey("raw",J,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),G=await crypto.subtle.sign("HMAC",L,M.encode(F));return new Uint8Array(G)}async function j(C){let{method:F,url:J,body:L,credentials:G}=C,X=new URL(J),Y=C._date??`${new Date().toISOString().replace(/[-:]/g,"").slice(0,15)}Z`,U=Y.slice(0,8),Z={...Object.fromEntries(Object.entries(C.headers).map(([O,E])=>[O.toLowerCase(),E.trim()])),host:X.host,"x-amz-date":Y};if(G.sessionToken)Z["x-amz-security-token"]=G.sessionToken;let $=Object.keys(Z).map((O)=>O.toLowerCase()).sort(),N=$.join(";"),_=`${$.map((O)=>`${O}:${Z[O]}`).join(`
2
2
  `)}
3
3
  `,D=h(X.searchParams),w=await z(L),Q=[F.toUpperCase(),S(X.pathname),D,_,N,w].join(`
4
4
  `),V=`${U}/${G.region}/${G.service}/aws4_request`,I=["AWS4-HMAC-SHA256",Y,V,await z(Q)].join(`
5
5
  `),b=await f(G.secretAccessKey,U,G.region,G.service),q=K(await W(b,I)),H=[`AWS4-HMAC-SHA256 Credential=${G.accessKeyId}/${V}`,`SignedHeaders=${N}`,`Signature=${q}`].join(", ");return{headers:{...Z,Authorization:H}}}async function f(C,F,J,L){let G=await W(`AWS4${C}`,F),X=await W(G,J),Y=await W(X,L);return W(Y,"aws4_request")}function S(C){if(!C||C==="/")return"/";return C.split("/").map((F)=>encodeURIComponent(decodeURIComponent(F))).join("/")}function h(C){let F=[];for(let[J,L]of C.entries())F.push(`${B(J)}=${B(L)}`);return F.sort(),F.join("&")}function B(C){return encodeURIComponent(C).replace(/[!'()*]/g,(F)=>`%${F.charCodeAt(0).toString(16).toUpperCase()}`)}function K(C){return Array.from(C,(F)=>F.toString(16).padStart(2,"0")).join("")}class v extends Error{statusCode;code;requestId;constructor(C,F,J,L){super(C);this.statusCode=F;this.code=J;this.requestId=L;this.name="SESError"}}class u{accessKeyId;secretAccessKey;region;sessionToken;dkim;constructor(C){this.accessKeyId=C.accessKeyId,this.secretAccessKey=C.secretAccessKey,this.region=C.region??"us-east-1",this.sessionToken=C.sessionToken,this.dkim=C.dkim}async send(C){let F=await k(C.attachments),J={...C,attachments:F},L=x(C.from)[0],G=L?R(L):"",X=P(C.to),Y=C.cc?P(C.cc):[],U=C.bcc?P(C.bcc):[],Z={ToAddresses:X,CcAddresses:Y,BccAddresses:U},$;if(F.length>0){let I=await A(J,this.dkim);$={FromEmailAddress:G,Destination:Z,Content:{Raw:{Data:T(I.raw).replace(/\r\n/g,"")}}}}else $={FromEmailAddress:G,Destination:Z,Content:{Simple:{Subject:{Data:C.subject,Charset:"UTF-8"},Body:{...C.text?{Text:{Data:C.text,Charset:"UTF-8"}}:{},...C.html?{Html:{Data:C.html,Charset:"UTF-8"}}:{}}}}};let N=JSON.stringify($),_=`https://email.${this.region}.amazonaws.com/v2/email/outbound-emails`,D=await j({method:"POST",url:_,headers:{"content-type":"application/json"},body:N,credentials:{accessKeyId:this.accessKeyId,secretAccessKey:this.secretAccessKey,region:this.region,service:"ses",...this.sessionToken?{sessionToken:this.sessionToken}:{}}}),w=await fetch(_,{method:"POST",headers:D.headers,body:N}),Q=await w.json();if(!w.ok)throw new v(Q.message??"SES API error",w.status,Q.Code??"",w.headers.get("x-amzn-requestid")??"");let V=Q.MessageId??"";return{messageId:V,accepted:[...X,...Y,...U],rejected:[],response:`MessageId: ${V}`,envelope:{from:L?.address??"",to:X}}}async verify(){try{let C=`https://email.${this.region}.amazonaws.com/v2/email/configuration-sets`,F=await j({method:"GET",url:C,headers:{},body:"",credentials:{accessKeyId:this.accessKeyId,secretAccessKey:this.secretAccessKey,region:this.region,service:"ses",...this.sessionToken?{sessionToken:this.sessionToken}:{}}}),J=await fetch(C,{method:"GET",headers:F.headers}),L=await J.json().catch(()=>({}));if(!J.ok)return{ok:!1,provider:"ses",message:L.message??`HTTP ${J.status}`};return{ok:!0,provider:"ses",message:"Credentials are valid"}}catch(C){return{ok:!1,provider:"ses",message:C instanceof Error?C.message:String(C)}}}}export{u as SESTransport,v as SESError};
6
6
 
7
- //# debugId=40DB8C49111C4E7964756E2164756E21
7
+ //# debugId=E0F0667425B3ED3764756E2164756E21
@@ -6,6 +6,6 @@
6
6
  "/**\n * @module\n * AWS SES v2 HTTP transport for sently.\n * Signs requests with AWS Signature Version 4 using Web Crypto.\n * Works on Node.js, Bun, Deno, and Cloudflare Workers.\n *\n * @example\n * ```ts\n * import { SESTransport } from \"sently/transports/ses\";\n * import { createMailer } from \"sently\";\n *\n * const mailer = await createMailer({\n * transport: new SESTransport({\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID!,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,\n * region: \"us-east-1\",\n * }),\n * });\n * ```\n */\nimport { extractEmails, parseAddresses, toMIMEHeader } from \"../core/address.js\";\nimport { encodeBase64 } from \"../core/base64.js\";\nimport { buildMIME } from \"../core/mime.js\";\nimport { signRequest } from \"../core/sigv4.js\";\nimport type { MailOptions, SESConfig, SendResult, Transport, VerifyResult } from \"../core/types.js\";\nimport { resolveAttachments } from \"./resolve-attachments.js\";\n\n/** Error thrown when the AWS SES API returns a non-success response. */\nexport class SESError extends Error {\n /** Creates an AWS SES API error with status code, error code, and request ID. */\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly code: string,\n public readonly requestId: string,\n ) {\n super(message);\n this.name = \"SESError\";\n }\n}\n\n/**\n * AWS SES v2 HTTP API transport.\n */\nexport class SESTransport implements Transport {\n /** AWS access key ID for SigV4 signing. */\n private readonly accessKeyId: string;\n /** AWS secret access key for SigV4 signing. */\n private readonly secretAccessKey: string;\n /** AWS region for the SES endpoint. */\n private readonly region: string;\n /** Optional STS session token for temporary credentials. */\n private readonly sessionToken: string | undefined;\n /** Optional DKIM config for raw MIME attachment sends. */\n private readonly dkim: SESConfig[\"dkim\"];\n\n /** Creates an SES transport with AWS credentials. */\n constructor(config: SESConfig) {\n this.accessKeyId = config.accessKeyId;\n this.secretAccessKey = config.secretAccessKey;\n this.region = config.region ?? \"us-east-1\";\n this.sessionToken = config.sessionToken;\n this.dkim = config.dkim;\n }\n\n /** Sends an email via the AWS SES v2 HTTP API. */\n async send(options: MailOptions): Promise<SendResult> {\n const attachments = await resolveAttachments(options.attachments);\n const resolvedOptions = { ...options, attachments };\n const from = parseAddresses(options.from)[0];\n const fromEmail = from ? toMIMEHeader(from) : \"\";\n const toEmails = extractEmails(options.to);\n const ccEmails = options.cc ? extractEmails(options.cc) : [];\n const bccEmails = options.bcc ? extractEmails(options.bcc) : [];\n\n const destination = {\n ToAddresses: toEmails,\n CcAddresses: ccEmails,\n BccAddresses: bccEmails,\n };\n\n let requestBody: Record<string, unknown>;\n\n if (attachments.length > 0) {\n const mime = await buildMIME(resolvedOptions, this.dkim);\n requestBody = {\n FromEmailAddress: fromEmail,\n Destination: destination,\n Content: {\n Raw: {\n Data: encodeBase64(mime.raw).replace(/\\r\\n/g, \"\"),\n },\n },\n };\n } else {\n requestBody = {\n FromEmailAddress: fromEmail,\n Destination: destination,\n Content: {\n Simple: {\n Subject: { Data: options.subject, Charset: \"UTF-8\" },\n Body: {\n ...(options.text ? { Text: { Data: options.text, Charset: \"UTF-8\" } } : {}),\n ...(options.html ? { Html: { Data: options.html, Charset: \"UTF-8\" } } : {}),\n },\n },\n },\n };\n }\n\n const body = JSON.stringify(requestBody);\n const url = `https://email.${this.region}.amazonaws.com/v2/email/outbound-emails`;\n const signed = await signRequest({\n method: \"POST\",\n url,\n headers: {\n \"content-type\": \"application/json\",\n },\n body,\n credentials: {\n accessKeyId: this.accessKeyId,\n secretAccessKey: this.secretAccessKey,\n region: this.region,\n service: \"ses\",\n ...(this.sessionToken ? { sessionToken: this.sessionToken } : {}),\n },\n });\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: signed.headers,\n body,\n });\n\n const payload = (await response.json()) as {\n MessageId?: string;\n message?: string;\n Code?: string;\n };\n\n if (!response.ok) {\n throw new SESError(\n payload.message ?? \"SES API error\",\n response.status,\n payload.Code ?? \"\",\n response.headers.get(\"x-amzn-requestid\") ?? \"\",\n );\n }\n\n const messageId = payload.MessageId ?? \"\";\n return {\n messageId,\n accepted: [...toEmails, ...ccEmails, ...bccEmails],\n rejected: [],\n response: `MessageId: ${messageId}`,\n envelope: {\n from: from?.address ?? \"\",\n to: toEmails,\n },\n };\n }\n\n /** Verifies AWS credentials by listing SES configuration sets. */\n async verify(): Promise<VerifyResult> {\n try {\n const url = `https://email.${this.region}.amazonaws.com/v2/email/configuration-sets`;\n const signed = await signRequest({\n method: \"GET\",\n url,\n headers: {},\n body: \"\",\n credentials: {\n accessKeyId: this.accessKeyId,\n secretAccessKey: this.secretAccessKey,\n region: this.region,\n service: \"ses\",\n ...(this.sessionToken ? { sessionToken: this.sessionToken } : {}),\n },\n });\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: signed.headers,\n });\n\n const payload = (await response.json().catch(() => ({}))) as { message?: string };\n\n if (!response.ok) {\n return {\n ok: false,\n provider: \"ses\",\n message: payload.message ?? `HTTP ${response.status}`,\n };\n }\n\n return { ok: true, provider: \"ses\", message: \"Credentials are valid\" };\n } catch (err) {\n return {\n ok: false,\n provider: \"ses\",\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n"
7
7
  ],
8
8
  "mappings": "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",
9
- "debugId": "40DB8C49111C4E7964756E2164756E21",
9
+ "debugId": "E0F0667425B3ED3764756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -1,3 +1,3 @@
1
- import{a as b,b as c,c as d,d as e,e as f,f as g}from"../chunk-nj3wmg69.js";import"../chunk-j5m37k1c.js";import"../chunk-nhec1319.js";import"../chunk-cvmk9h1r.js";import"../chunk-kdqxhybf.js";import{F as a}from"../chunk-m2njnxre.js";import"../chunk-32dj0v9g.js";import"../chunk-rhade81v.js";export{c as resolveSMTPConfig,g as readSMTPResponse,d as openSMTPSession,a as encodeLine,e as deliverSMTPMessage,f as closeSMTPSession,b as SMTPTransport};
1
+ import{h as b,i as c,j as d,k as e,l as f,m as g}from"../chunk-c8ya9em0.js";import"../chunk-zkczgj2c.js";import"../chunk-aeqxkeh3.js";import"../chunk-k0gw3qmb.js";import"../chunk-b0qkndv9.js";import{M as a}from"../chunk-9p4vev6j.js";import"../chunk-gxq2aamv.js";import"../chunk-mg8m26nr.js";export{c as resolveSMTPConfig,g as readSMTPResponse,d as openSMTPSession,a as encodeLine,e as deliverSMTPMessage,f as closeSMTPSession,b as SMTPTransport};
2
2
 
3
- //# debugId=6A679298EBA4014164756E2164756E21
3
+ //# debugId=24C99E47C629756A64756E2164756E21
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "6A679298EBA4014164756E2164756E21",
7
+ "debugId": "24C99E47C629756A64756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -0,0 +1,3 @@
1
+ import{d as F,e as u,f as G,g as H}from"../chunk-q8k3m6qe.js";import"../chunk-mg8m26nr.js";var K={delivered:"delivered",hard_bounce:"bounced",hardBounce:"bounced",soft_bounce:"bounced",soft_bounced:"bounced",softBounce:"bounced",blocked:"bounced",invalid:"bounced",invalid_email:"bounced",deferred:"deferred",spam:"complained",opened:"opened",unique_opened:"opened",uniqueOpened:"opened",click:"clicked",clicked:"clicked",unique_click:"clicked",uniqueClicked:"clicked",sent:"unknown",request:"unknown",unsubscribe:"complained",unsubscribed:"complained"};function L(f){return u(f.ts_event)??u(f.ts)??u(f.date_event)??u(f.date)??u(f.ts_epoch!==void 0?Number(f.ts_epoch):void 0)}function Q(f){if(typeof f["message-id"]==="string")return f["message-id"];if(typeof f.messageId==="string")return f.messageId;return}function U(f){return G(f).flatMap((x)=>{if(typeof x!=="object"||x===null)return[];let q=x,J=typeof q.event==="string"?q.event:"",C=L(q),D=Q(q);return[H({provider:"brevo",type:F(J,K),...D!==void 0?{messageId:D}:{},...typeof q.email==="string"?{recipient:q.email}:{},...C!==void 0?{timestamp:C}:{},raw:x})]})}export{U as parse};
2
+
3
+ //# debugId=916BC5D0AADEB5C764756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/webhooks/brevo.ts"],
4
+ "sourcesContent": [
5
+ "import type { EmailEvent } from \"./types.js\";\nimport { asArray, emailEvent, mapEventType, parseTimestamp } from \"./types.js\";\n\nconst BREVO_EVENT_MAP: Record<string, EmailEvent[\"type\"]> = {\n delivered: \"delivered\",\n hard_bounce: \"bounced\",\n hardBounce: \"bounced\",\n soft_bounce: \"bounced\",\n soft_bounced: \"bounced\",\n softBounce: \"bounced\",\n blocked: \"bounced\",\n invalid: \"bounced\",\n invalid_email: \"bounced\",\n deferred: \"deferred\",\n spam: \"complained\",\n opened: \"opened\",\n unique_opened: \"opened\",\n uniqueOpened: \"opened\",\n click: \"clicked\",\n clicked: \"clicked\",\n unique_click: \"clicked\",\n uniqueClicked: \"clicked\",\n sent: \"unknown\",\n request: \"unknown\",\n unsubscribe: \"complained\",\n unsubscribed: \"complained\",\n};\n\nfunction resolveBrevoTimestamp(record: Record<string, unknown>): Date | undefined {\n return (\n parseTimestamp(record.ts_event) ??\n parseTimestamp(record.ts) ??\n parseTimestamp(record.date_event) ??\n parseTimestamp(record.date) ??\n parseTimestamp(record.ts_epoch !== undefined ? Number(record.ts_epoch) : undefined)\n );\n}\n\nfunction resolveBrevoMessageId(record: Record<string, unknown>): string | undefined {\n if (typeof record[\"message-id\"] === \"string\") {\n return record[\"message-id\"];\n }\n if (typeof record.messageId === \"string\") {\n return record.messageId;\n }\n return undefined;\n}\n\n/** Parse a Brevo webhook payload into normalized {@link EmailEvent} records. */\nexport function parse(payload: unknown): EmailEvent[] {\n return asArray(payload).flatMap((item) => {\n if (typeof item !== \"object\" || item === null) {\n return [];\n }\n\n const record = item as Record<string, unknown>;\n const event = typeof record.event === \"string\" ? record.event : \"\";\n const timestamp = resolveBrevoTimestamp(record);\n const messageId = resolveBrevoMessageId(record);\n\n return [\n emailEvent({\n provider: \"brevo\",\n type: mapEventType(event, BREVO_EVENT_MAP),\n ...(messageId !== undefined ? { messageId } : {}),\n ...(typeof record.email === \"string\" ? { recipient: record.email } : {}),\n ...(timestamp !== undefined ? { timestamp } : {}),\n raw: item,\n }),\n ];\n });\n}\n"
6
+ ],
7
+ "mappings": "gGAGA,DAAM,EAAsD,CAC1D,UAAW,YACX,YAAa,UACb,WAAY,UACZ,YAAa,UACb,aAAc,UACd,WAAY,UACZ,QAAS,UACT,QAAS,UACT,cAAe,UACf,SAAU,WACV,KAAM,aACN,OAAQ,SACR,cAAe,SACf,aAAc,SACd,MAAO,UACP,QAAS,UACT,aAAc,UACd,cAAe,UACf,KAAM,UACN,QAAS,UACT,YAAa,aACb,aAAc,YAChB,EAEA,SAAS,CAAqB,CAAC,EAAmD,CAChF,OACE,EAAe,EAAO,QAAQ,GAC9B,EAAe,EAAO,EAAE,GACxB,EAAe,EAAO,UAAU,GAChC,EAAe,EAAO,IAAI,GAC1B,EAAe,EAAO,WAAa,OAAY,OAAO,EAAO,QAAQ,EAAI,MAAS,EAItF,SAAS,CAAqB,CAAC,EAAqD,CAClF,GAAI,OAAO,EAAO,gBAAkB,SAClC,OAAO,EAAO,cAEhB,GAAI,OAAO,EAAO,YAAc,SAC9B,OAAO,EAAO,UAEhB,OAIK,SAAS,CAAK,CAAC,EAAgC,CACpD,OAAO,EAAQ,CAAO,EAAE,QAAQ,CAAC,IAAS,CACxC,GAAI,OAAO,IAAS,UAAY,IAAS,KACvC,MAAO,CAAC,EAGV,IAAM,EAAS,EACT,EAAQ,OAAO,EAAO,QAAU,SAAW,EAAO,MAAQ,GAC1D,EAAY,EAAsB,CAAM,EACxC,EAAY,EAAsB,CAAM,EAE9C,MAAO,CACL,EAAW,CACT,SAAU,QACV,KAAM,EAAa,EAAO,CAAe,KACrC,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,KAC3C,OAAO,EAAO,QAAU,SAAW,CAAE,UAAW,EAAO,KAAM,EAAI,CAAC,KAClE,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,EAC/C,IAAK,CACP,CAAC,CACH,EACD",
8
+ "debugId": "916BC5D0AADEB5C764756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,3 @@
1
+ import{a as G,c as H}from"../chunk-pqp843mh.js";import{d as Y,e as Z,g as $}from"../chunk-q8k3m6qe.js";import"../chunk-mg8m26nr.js";var R={accepted:"unknown",delivered:"delivered",rejected:"bounced",complained:"complained",opened:"opened",clicked:"clicked",stored:"unknown",unsubscribed:"unknown"};function U(z){let J=typeof z.event==="string"?z.event:"";if(J==="failed")return z.severity==="temporary"?"deferred":"bounced";return Y(J,R)}function b(z){if(!z)return;let J=z.headers;if(typeof J==="object"&&J!==null){let C=J["message-id"];if(typeof C==="string")return C}return typeof z["message-id"]==="string"?z["message-id"]:void 0}function N(z){if(typeof z!=="object"||z===null)return[];let J=z,C=typeof J["event-data"]==="object"&&J["event-data"]!==null?J["event-data"]:J,O=typeof C.message==="object"&&C.message!==null?C.message:void 0,Q=b(O),W=Z(C.timestamp);return[$({provider:"mailgun",type:U(C),...Q!==void 0?{messageId:Q}:{},...typeof C.recipient==="string"?{recipient:C.recipient}:{},...W!==void 0?{timestamp:W}:{},raw:z})]}async function q(z,J,C,O){let Q=await crypto.subtle.importKey("raw",new TextEncoder().encode(O),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),W=new TextEncoder().encode(z+J),L=await crypto.subtle.sign("HMAC",Q,W),P=new Uint8Array(L),X=H(C);if(X===null)return!1;return G(P,X)}async function S(z,J){if(typeof z!=="object"||z===null)return!1;let C=z.signature;if(typeof C!=="object"||C===null)return!1;let O=C;if(typeof O.timestamp!=="string"||typeof O.token!=="string"||typeof O.signature!=="string")return!1;return q(O.timestamp,O.token,O.signature,J)}export{q as verifySignature,S as verifyPayload,N as parse};
2
+
3
+ //# debugId=7FB21CD9E29B4FE264756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/webhooks/mailgun.ts"],
4
+ "sourcesContent": [
5
+ "import { decodeHexBytes, timingSafeEqual } from \"./timing-safe-equal.js\";\nimport type { EmailEvent } from \"./types.js\";\nimport { emailEvent, mapEventType, parseTimestamp } from \"./types.js\";\n\nconst MAILGUN_EVENT_MAP: Record<string, EmailEvent[\"type\"]> = {\n accepted: \"unknown\",\n delivered: \"delivered\",\n rejected: \"bounced\",\n complained: \"complained\",\n opened: \"opened\",\n clicked: \"clicked\",\n stored: \"unknown\",\n unsubscribed: \"unknown\",\n};\n\n/** Map a Mailgun event (and failed severity) to a normalized type. */\nfunction mapMailgunType(eventData: Record<string, unknown>): EmailEvent[\"type\"] {\n const event = typeof eventData.event === \"string\" ? eventData.event : \"\";\n if (event === \"failed\") {\n return eventData.severity === \"temporary\" ? \"deferred\" : \"bounced\";\n }\n return mapEventType(event, MAILGUN_EVENT_MAP);\n}\n\nfunction extractMailgunMessageId(message: Record<string, unknown> | undefined): string | undefined {\n if (!message) {\n return undefined;\n }\n const headers = message.headers;\n if (typeof headers === \"object\" && headers !== null) {\n const messageId = (headers as Record<string, unknown>)[\"message-id\"];\n if (typeof messageId === \"string\") {\n return messageId;\n }\n }\n return typeof message[\"message-id\"] === \"string\" ? message[\"message-id\"] : undefined;\n}\n\n/** Parse a Mailgun webhook payload into normalized {@link EmailEvent} records. */\nexport function parse(payload: unknown): EmailEvent[] {\n if (typeof payload !== \"object\" || payload === null) {\n return [];\n }\n\n const record = payload as Record<string, unknown>;\n const eventData =\n typeof record[\"event-data\"] === \"object\" && record[\"event-data\"] !== null\n ? (record[\"event-data\"] as Record<string, unknown>)\n : record;\n\n const message =\n typeof eventData.message === \"object\" && eventData.message !== null\n ? (eventData.message as Record<string, unknown>)\n : undefined;\n\n const messageId = extractMailgunMessageId(message);\n const timestamp = parseTimestamp(eventData.timestamp);\n\n return [\n emailEvent({\n provider: \"mailgun\",\n type: mapMailgunType(eventData),\n ...(messageId !== undefined ? { messageId } : {}),\n ...(typeof eventData.recipient === \"string\" ? { recipient: eventData.recipient } : {}),\n ...(timestamp !== undefined ? { timestamp } : {}),\n raw: payload,\n }),\n ];\n}\n\n/**\n * Verify a Mailgun webhook signature using HMAC-SHA256 (Web Crypto).\n * signingKey is the Mailgun webhook signing key.\n */\nexport async function verifySignature(\n timestamp: string,\n token: string,\n signature: string,\n signingKey: string,\n): Promise<boolean> {\n const key = await crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(signingKey),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const data = new TextEncoder().encode(timestamp + token);\n const expected = await crypto.subtle.sign(\"HMAC\", key, data);\n const expectedBytes = new Uint8Array(expected);\n const providedBytes = decodeHexBytes(signature);\n\n if (providedBytes === null) {\n return false;\n }\n\n return timingSafeEqual(expectedBytes, providedBytes);\n}\n\n/**\n * Verify a Mailgun webhook payload using the nested `signature` object.\n * Returns false when the payload shape is invalid.\n */\nexport async function verifyPayload(payload: unknown, signingKey: string): Promise<boolean> {\n if (typeof payload !== \"object\" || payload === null) {\n return false;\n }\n\n const signatureField = (payload as Record<string, unknown>).signature;\n if (typeof signatureField !== \"object\" || signatureField === null) {\n return false;\n }\n\n const signature = signatureField as Record<string, unknown>;\n if (\n typeof signature.timestamp !== \"string\" ||\n typeof signature.token !== \"string\" ||\n typeof signature.signature !== \"string\"\n ) {\n return false;\n }\n\n return verifySignature(signature.timestamp, signature.token, signature.signature, signingKey);\n}\n"
6
+ ],
7
+ "mappings": "8IAIA,DAAM,HAAwD,CAC5D,SAAU,UACV,UAAW,YACX,SAAU,UACV,WAAY,aACZ,OAAQ,SACR,QAAS,UACT,OAAQ,UACR,aAAc,SAChB,EAGA,SAAS,CAAc,CAAC,EAAwD,CAC9E,IAAM,EAAQ,OAAO,EAAU,QAAU,SAAW,EAAU,MAAQ,GACtE,GAAI,IAAU,SACZ,OAAO,EAAU,WAAa,YAAc,WAAa,UAE3D,OAAO,EAAa,EAAO,CAAiB,EAG9C,SAAS,CAAuB,CAAC,EAAkE,CACjG,GAAI,CAAC,EACH,OAEF,IAAM,EAAU,EAAQ,QACxB,GAAI,OAAO,IAAY,UAAY,IAAY,KAAM,CACnD,IAAM,EAAa,EAAoC,cACvD,GAAI,OAAO,IAAc,SACvB,OAAO,EAGX,OAAO,OAAO,EAAQ,gBAAkB,SAAW,EAAQ,cAAgB,OAItE,SAAS,CAAK,CAAC,EAAgC,CACpD,GAAI,OAAO,IAAY,UAAY,IAAY,KAC7C,MAAO,CAAC,EAGV,IAAM,EAAS,EACT,EACJ,OAAO,EAAO,gBAAkB,UAAY,EAAO,gBAAkB,KAChE,EAAO,cACR,EAEA,EACJ,OAAO,EAAU,UAAY,UAAY,EAAU,UAAY,KAC1D,EAAU,QACX,OAEA,EAAY,EAAwB,CAAO,EAC3C,EAAY,EAAe,EAAU,SAAS,EAEpD,MAAO,CACL,EAAW,CACT,SAAU,UACV,KAAM,EAAe,CAAS,KAC1B,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,KAC3C,OAAO,EAAU,YAAc,SAAW,CAAE,UAAW,EAAU,SAAU,EAAI,CAAC,KAChF,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,EAC/C,IAAK,CACP,CAAC,CACH,EAOF,eAAsB,CAAe,CACnC,EACA,EACA,EACA,EACkB,CAClB,IAAM,EAAM,MAAM,OAAO,OAAO,UAC9B,MACA,IAAI,YAAY,EAAE,OAAO,CAAU,EACnC,CAAE,KAAM,OAAQ,KAAM,SAAU,EAChC,GACA,CAAC,MAAM,CACT,EAEM,EAAO,IAAI,YAAY,EAAE,OAAO,EAAY,CAAK,EACjD,EAAW,MAAM,OAAO,OAAO,KAAK,OAAQ,EAAK,CAAI,EACrD,EAAgB,IAAI,WAAW,CAAQ,EACvC,EAAgB,EAAe,CAAS,EAE9C,GAAI,IAAkB,KACpB,MAAO,GAGT,OAAO,EAAgB,EAAe,CAAa,EAOrD,eAAsB,CAAa,CAAC,EAAkB,EAAsC,CAC1F,GAAI,OAAO,IAAY,UAAY,IAAY,KAC7C,MAAO,GAGT,IAAM,EAAkB,EAAoC,UAC5D,GAAI,OAAO,IAAmB,UAAY,IAAmB,KAC3D,MAAO,GAGT,IAAM,EAAY,EAClB,GACE,OAAO,EAAU,YAAc,UAC/B,OAAO,EAAU,QAAU,UAC3B,OAAO,EAAU,YAAc,SAE/B,MAAO,GAGT,OAAO,EAAgB,EAAU,UAAW,EAAU,MAAO,EAAU,UAAW,CAAU",
8
+ "debugId": "7FB21CD9E29B4FE264756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,3 @@
1
+ import{d as u,e as q,g as x}from"../chunk-q8k3m6qe.js";import"../chunk-mg8m26nr.js";var C={Delivery:"delivered",Bounce:"bounced",SpamComplaint:"complained",Open:"opened",Click:"clicked",SubscriptionChange:"unknown",Inbound:"unknown"};function F(g){if(typeof g!=="object"||g===null)return[];let f=g,B=typeof f.RecordType==="string"?f.RecordType:"";return[x({provider:"postmark",type:u(B,C),...typeof f.MessageID==="string"?{messageId:f.MessageID}:{},...typeof f.Recipient==="string"?{recipient:f.Recipient}:typeof f.Email==="string"?{recipient:f.Email}:{},...q(f.DeliveredAt??f.BouncedAt??f.ReceivedAt??f.ChangedAt)!==void 0?{timestamp:q(f.DeliveredAt??f.BouncedAt??f.ReceivedAt??f.ChangedAt)}:{},raw:g})]}export{F as parse};
2
+
3
+ //# debugId=7CD05BB54D484C3864756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/webhooks/postmark.ts"],
4
+ "sourcesContent": [
5
+ "import type { EmailEvent } from \"./types.js\";\nimport { emailEvent, mapEventType, parseTimestamp } from \"./types.js\";\n\nconst POSTMARK_EVENT_MAP: Record<string, EmailEvent[\"type\"]> = {\n Delivery: \"delivered\",\n Bounce: \"bounced\",\n SpamComplaint: \"complained\",\n Open: \"opened\",\n Click: \"clicked\",\n SubscriptionChange: \"unknown\",\n Inbound: \"unknown\",\n};\n\n/** Parse a Postmark webhook payload into normalized {@link EmailEvent} records. */\nexport function parse(payload: unknown): EmailEvent[] {\n if (typeof payload !== \"object\" || payload === null) {\n return [];\n }\n\n const record = payload as Record<string, unknown>;\n const recordType = typeof record.RecordType === \"string\" ? record.RecordType : \"\";\n\n return [\n emailEvent({\n provider: \"postmark\",\n type: mapEventType(recordType, POSTMARK_EVENT_MAP),\n ...(typeof record.MessageID === \"string\" ? { messageId: record.MessageID } : {}),\n ...(typeof record.Recipient === \"string\"\n ? { recipient: record.Recipient }\n : typeof record.Email === \"string\"\n ? { recipient: record.Email }\n : {}),\n ...(parseTimestamp(\n record.DeliveredAt ?? record.BouncedAt ?? record.ReceivedAt ?? record.ChangedAt,\n ) !== undefined\n ? {\n timestamp: parseTimestamp(\n record.DeliveredAt ?? record.BouncedAt ?? record.ReceivedAt ?? record.ChangedAt,\n ),\n }\n : {}),\n raw: payload,\n }),\n ];\n}\n"
6
+ ],
7
+ "mappings": "yFAGA,DAAM,EAAyD,CAC7D,SAAU,YACV,OAAQ,UACR,cAAe,aACf,KAAM,SACN,MAAO,UACP,mBAAoB,UACpB,QAAS,SACX,EAGO,SAAS,CAAK,CAAC,EAAgC,CACpD,GAAI,OAAO,IAAY,UAAY,IAAY,KAC7C,MAAO,CAAC,EAGV,IAAM,EAAS,EACT,EAAa,OAAO,EAAO,aAAe,SAAW,EAAO,WAAa,GAE/E,MAAO,CACL,EAAW,CACT,SAAU,WACV,KAAM,EAAa,EAAY,CAAkB,KAC7C,OAAO,EAAO,YAAc,SAAW,CAAE,UAAW,EAAO,SAAU,EAAI,CAAC,KAC1E,OAAO,EAAO,YAAc,SAC5B,CAAE,UAAW,EAAO,SAAU,EAC9B,OAAO,EAAO,QAAU,SACtB,CAAE,UAAW,EAAO,KAAM,EAC1B,CAAC,KACH,EACF,EAAO,aAAe,EAAO,WAAa,EAAO,YAAc,EAAO,SACxE,IAAM,OACF,CACE,UAAW,EACT,EAAO,aAAe,EAAO,WAAa,EAAO,YAAc,EAAO,SACxE,CACF,EACA,CAAC,EACL,IAAK,CACP,CAAC,CACH",
8
+ "debugId": "7CD05BB54D484C3864756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,3 @@
1
+ import{a as $,b as A}from"../chunk-pqp843mh.js";import{d as X,e as Y,g as Z}from"../chunk-q8k3m6qe.js";import"../chunk-mg8m26nr.js";var j={"email.sent":"unknown","email.scheduled":"unknown","email.delivered":"delivered","email.delivery_delayed":"deferred","email.bounced":"bounced","email.failed":"bounced","email.complained":"complained","email.opened":"opened","email.clicked":"clicked","email.received":"unknown","email.suppressed":"unknown"};function k(G){let F=G.startsWith("whsec_")?G.slice(6):G,K=atob(F),J=new Uint8Array(K.length);for(let z=0;z<K.length;z++)J[z]=K.charCodeAt(z);return J.buffer}function H(G){if(typeof G!=="object"||G===null)return[];let F=G,K=typeof F.type==="string"?F.type:"",J=typeof F.data==="object"&&F.data!==null?F.data:{},z=J.to,L=Array.isArray(z)?typeof z[0]==="string"?z[0]:void 0:typeof z==="string"?z:void 0,O=Y(F.created_at??J.created_at);return[Z({provider:"resend",type:X(K,j),...typeof J.email_id==="string"?{messageId:J.email_id}:{},...L!==void 0?{recipient:L}:{},...O!==void 0?{timestamp:O}:{},raw:G})]}async function I(G,F,K){let J=F["svix-id"],z=F["svix-timestamp"],L=F["svix-signature"];if(!J||!z||!L)return!1;let O=`${J}.${z}.${G}`,D=await crypto.subtle.importKey("raw",k(K),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),M=await crypto.subtle.sign("HMAC",D,new TextEncoder().encode(O)),P=new Uint8Array(M);for(let W of L.split(" ")){let Q=W.split(",",2)[1];if(Q===void 0)continue;let U=A(Q);if(U===null)continue;if($(P,U))return!0}return!1}export{I as verifySignature,H as parse};
2
+
3
+ //# debugId=2EA62D07463E258664756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/webhooks/resend.ts"],
4
+ "sourcesContent": [
5
+ "import { decodeBase64Bytes, timingSafeEqual } from \"./timing-safe-equal.js\";\nimport type { EmailEvent } from \"./types.js\";\nimport { emailEvent, mapEventType, parseTimestamp } from \"./types.js\";\n\nconst RESEND_EVENT_MAP: Record<string, EmailEvent[\"type\"]> = {\n \"email.sent\": \"unknown\",\n \"email.scheduled\": \"unknown\",\n \"email.delivered\": \"delivered\",\n \"email.delivery_delayed\": \"deferred\",\n \"email.bounced\": \"bounced\",\n \"email.failed\": \"bounced\",\n \"email.complained\": \"complained\",\n \"email.opened\": \"opened\",\n \"email.clicked\": \"clicked\",\n \"email.received\": \"unknown\",\n \"email.suppressed\": \"unknown\",\n};\n\n/** Decode a Svix signing secret (`whsec_…`) to raw key bytes. */\nfunction decodeSvixSecret(secret: string): ArrayBuffer {\n const encoded = secret.startsWith(\"whsec_\") ? secret.slice(6) : secret;\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n/** Parse a Resend webhook payload into normalized {@link EmailEvent} records. */\nexport function parse(payload: unknown): EmailEvent[] {\n if (typeof payload !== \"object\" || payload === null) {\n return [];\n }\n\n const record = payload as Record<string, unknown>;\n const type = typeof record.type === \"string\" ? record.type : \"\";\n const data =\n typeof record.data === \"object\" && record.data !== null\n ? (record.data as Record<string, unknown>)\n : {};\n\n const to = data.to;\n const recipient = Array.isArray(to)\n ? typeof to[0] === \"string\"\n ? to[0]\n : undefined\n : typeof to === \"string\"\n ? to\n : undefined;\n\n const timestamp = parseTimestamp(record.created_at ?? data.created_at);\n\n return [\n emailEvent({\n provider: \"resend\",\n type: mapEventType(type, RESEND_EVENT_MAP),\n ...(typeof data.email_id === \"string\" ? { messageId: data.email_id } : {}),\n ...(recipient !== undefined ? { recipient } : {}),\n ...(timestamp !== undefined ? { timestamp } : {}),\n raw: payload,\n }),\n ];\n}\n\n/**\n * Verify a Resend webhook signature (Svix-style) using Web Crypto.\n * Returns false when verification cannot be performed or the signature is invalid.\n */\nexport async function verifySignature(\n payload: string,\n headers: { \"svix-id\"?: string; \"svix-timestamp\"?: string; \"svix-signature\"?: string },\n secret: string,\n): Promise<boolean> {\n const msgId = headers[\"svix-id\"];\n const timestamp = headers[\"svix-timestamp\"];\n const signatureHeader = headers[\"svix-signature\"];\n\n if (!msgId || !timestamp || !signatureHeader) {\n return false;\n }\n\n const signedContent = `${msgId}.${timestamp}.${payload}`;\n const key = await crypto.subtle.importKey(\n \"raw\",\n decodeSvixSecret(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const expected = await crypto.subtle.sign(\"HMAC\", key, new TextEncoder().encode(signedContent));\n const expectedBytes = new Uint8Array(expected);\n\n for (const part of signatureHeader.split(\" \")) {\n const versioned = part.split(\",\", 2);\n const sig = versioned[1];\n if (sig === undefined) {\n continue;\n }\n const providedBytes = decodeBase64Bytes(sig);\n if (providedBytes === null) {\n continue;\n }\n if (timingSafeEqual(expectedBytes, providedBytes)) {\n return true;\n }\n }\n\n return false;\n}\n"
6
+ ],
7
+ "mappings": "8IAIA,DAAM,HAAuD,CAC3D,aAAc,UACd,kBAAmB,UACnB,kBAAmB,YACnB,yBAA0B,WAC1B,gBAAiB,UACjB,eAAgB,UAChB,mBAAoB,aACpB,eAAgB,SAChB,gBAAiB,UACjB,iBAAkB,UAClB,mBAAoB,SACtB,EAGA,SAAS,CAAgB,CAAC,EAA6B,CACrD,IAAM,EAAU,EAAO,WAAW,QAAQ,EAAI,EAAO,MAAM,CAAC,EAAI,EAC1D,EAAS,KAAK,CAAO,EACrB,EAAQ,IAAI,WAAW,EAAO,MAAM,EAC1C,QAAS,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAM,GAAK,EAAO,WAAW,CAAC,EAEhC,OAAO,EAAM,OAIR,SAAS,CAAK,CAAC,EAAgC,CACpD,GAAI,OAAO,IAAY,UAAY,IAAY,KAC7C,MAAO,CAAC,EAGV,IAAM,EAAS,EACT,EAAO,OAAO,EAAO,OAAS,SAAW,EAAO,KAAO,GACvD,EACJ,OAAO,EAAO,OAAS,UAAY,EAAO,OAAS,KAC9C,EAAO,KACR,CAAC,EAED,EAAK,EAAK,GACV,EAAY,MAAM,QAAQ,CAAE,EAC9B,OAAO,EAAG,KAAO,SACf,EAAG,GACH,OACF,OAAO,IAAO,SACZ,EACA,OAEA,EAAY,EAAe,EAAO,YAAc,EAAK,UAAU,EAErE,MAAO,CACL,EAAW,CACT,SAAU,SACV,KAAM,EAAa,EAAM,CAAgB,KACrC,OAAO,EAAK,WAAa,SAAW,CAAE,UAAW,EAAK,QAAS,EAAI,CAAC,KACpE,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,KAC3C,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,EAC/C,IAAK,CACP,CAAC,CACH,EAOF,eAAsB,CAAe,CACnC,EACA,EACA,EACkB,CAClB,IAAM,EAAQ,EAAQ,WAChB,EAAY,EAAQ,kBACpB,EAAkB,EAAQ,kBAEhC,GAAI,CAAC,GAAS,CAAC,GAAa,CAAC,EAC3B,MAAO,GAGT,IAAM,EAAgB,GAAG,KAAS,KAAa,IACzC,EAAM,MAAM,OAAO,OAAO,UAC9B,MACA,EAAiB,CAAM,EACvB,CAAE,KAAM,OAAQ,KAAM,SAAU,EAChC,GACA,CAAC,MAAM,CACT,EAEM,EAAW,MAAM,OAAO,OAAO,KAAK,OAAQ,EAAK,IAAI,YAAY,EAAE,OAAO,CAAa,CAAC,EACxF,EAAgB,IAAI,WAAW,CAAQ,EAE7C,QAAW,KAAQ,EAAgB,MAAM,GAAG,EAAG,CAE7C,IAAM,EADY,EAAK,MAAM,IAAK,CAAC,EACb,GACtB,GAAI,IAAQ,OACV,SAEF,IAAM,EAAgB,EAAkB,CAAG,EAC3C,GAAI,IAAkB,KACpB,SAEF,GAAI,EAAgB,EAAe,CAAa,EAC9C,MAAO,GAIX,MAAO",
8
+ "debugId": "2EA62D07463E258664756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,3 @@
1
+ import{d as w,e as x,f as B,g as C}from"../chunk-q8k3m6qe.js";import"../chunk-mg8m26nr.js";var F={processed:"unknown",delivered:"delivered",deferred:"deferred",bounce:"bounced",dropped:"bounced",spamreport:"complained",unsubscribe:"complained",group_unsubscribe:"complained",group_resubscribe:"unknown",open:"opened",click:"clicked"};function H(q){let g=typeof q.event==="string"?q.event:"";if(g==="bounce"&&q.type==="blocked")return"deferred";return w(g,F)}function K(q){return B(q).flatMap((g)=>{if(typeof g!=="object"||g===null)return[];let f=g,u=x(f.timestamp);return[C({provider:"sendgrid",type:H(f),...typeof f.sg_message_id==="string"?{messageId:f.sg_message_id}:typeof f["smtp-id"]==="string"?{messageId:f["smtp-id"]}:{},...typeof f.email==="string"?{recipient:f.email}:{},...u!==void 0?{timestamp:u}:{},raw:g})]})}export{K as parse};
2
+
3
+ //# debugId=D4C7DDEE719D449764756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/webhooks/sendgrid.ts"],
4
+ "sourcesContent": [
5
+ "import type { EmailEvent } from \"./types.js\";\nimport { asArray, emailEvent, mapEventType, parseTimestamp } from \"./types.js\";\n\nconst SENDGRID_EVENT_MAP: Record<string, EmailEvent[\"type\"]> = {\n processed: \"unknown\",\n delivered: \"delivered\",\n deferred: \"deferred\",\n bounce: \"bounced\",\n dropped: \"bounced\",\n spamreport: \"complained\",\n unsubscribe: \"complained\",\n group_unsubscribe: \"complained\",\n group_resubscribe: \"unknown\",\n open: \"opened\",\n click: \"clicked\",\n};\n\n/** Map a SendGrid event name (and bounce subtype) to a normalized type. */\nfunction mapSendGridType(record: Record<string, unknown>): EmailEvent[\"type\"] {\n const event = typeof record.event === \"string\" ? record.event : \"\";\n if (event === \"bounce\" && record.type === \"blocked\") {\n return \"deferred\";\n }\n return mapEventType(event, SENDGRID_EVENT_MAP);\n}\n\n/** Parse a SendGrid Event Webhook payload into normalized {@link EmailEvent} records. */\nexport function parse(payload: unknown): EmailEvent[] {\n return asArray(payload).flatMap((item) => {\n if (typeof item !== \"object\" || item === null) {\n return [];\n }\n\n const record = item as Record<string, unknown>;\n const timestamp = parseTimestamp(record.timestamp);\n\n return [\n emailEvent({\n provider: \"sendgrid\",\n type: mapSendGridType(record),\n ...(typeof record.sg_message_id === \"string\"\n ? { messageId: record.sg_message_id }\n : typeof record[\"smtp-id\"] === \"string\"\n ? { messageId: record[\"smtp-id\"] }\n : {}),\n ...(typeof record.email === \"string\" ? { recipient: record.email } : {}),\n ...(timestamp !== undefined ? { timestamp } : {}),\n raw: item,\n }),\n ];\n });\n}\n"
6
+ ],
7
+ "mappings": "gGAGA,DAAM,EAAyD,CAC7D,UAAW,UACX,UAAW,YACX,SAAU,WACV,OAAQ,UACR,QAAS,UACT,WAAY,aACZ,YAAa,aACb,kBAAmB,aACnB,kBAAmB,UACnB,KAAM,SACN,MAAO,SACT,EAGA,SAAS,CAAe,CAAC,EAAqD,CAC5E,IAAM,EAAQ,OAAO,EAAO,QAAU,SAAW,EAAO,MAAQ,GAChE,GAAI,IAAU,UAAY,EAAO,OAAS,UACxC,MAAO,WAET,OAAO,EAAa,EAAO,CAAkB,EAIxC,SAAS,CAAK,CAAC,EAAgC,CACpD,OAAO,EAAQ,CAAO,EAAE,QAAQ,CAAC,IAAS,CACxC,GAAI,OAAO,IAAS,UAAY,IAAS,KACvC,MAAO,CAAC,EAGV,IAAM,EAAS,EACT,EAAY,EAAe,EAAO,SAAS,EAEjD,MAAO,CACL,EAAW,CACT,SAAU,WACV,KAAM,EAAgB,CAAM,KACxB,OAAO,EAAO,gBAAkB,SAChC,CAAE,UAAW,EAAO,aAAc,EAClC,OAAO,EAAO,aAAe,SAC3B,CAAE,UAAW,EAAO,UAAW,EAC/B,CAAC,KACH,OAAO,EAAO,QAAU,SAAW,CAAE,UAAW,EAAO,KAAM,EAAI,CAAC,KAClE,IAAc,OAAY,CAAE,WAAU,EAAI,CAAC,EAC/C,IAAK,CACP,CAAC,CACH,EACD",
8
+ "debugId": "D4C7DDEE719D449764756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,3 @@
1
+ import{d as Q,e as U,g as X}from"../chunk-q8k3m6qe.js";import"../chunk-mg8m26nr.js";var $={Delivery:"delivered",Bounce:"bounced",Complaint:"complained",Open:"opened",Click:"clicked",DeliveryDelay:"deferred",Send:"unknown",Reject:"bounced","Rendering Failure":"bounced",Subscription:"unknown"};function h(q){if(typeof q.eventType==="string")return q.eventType;if(typeof q.notificationType==="string")return q.notificationType;return""}function j(q){let J=typeof q.delivery==="object"&&q.delivery!==null?q.delivery:void 0;if(J&&Array.isArray(J.recipients)&&typeof J.recipients[0]==="string")return J.recipients[0];let K=typeof q.bounce==="object"&&q.bounce!==null?q.bounce:void 0;if(K&&Array.isArray(K.bouncedRecipients)){let I=K.bouncedRecipients[0];if(typeof I==="object"&&I!==null&&typeof I.emailAddress==="string")return I.emailAddress}let B=typeof q.complaint==="object"&&q.complaint!==null?q.complaint:void 0;if(B&&Array.isArray(B.complainedRecipients)){let I=B.complainedRecipients[0];if(typeof I==="object"&&I!==null&&typeof I.emailAddress==="string")return I.emailAddress}let G=typeof q.mail==="object"&&q.mail!==null?q.mail:void 0;if(Array.isArray(G?.destination)&&typeof G.destination[0]==="string")return G.destination[0];return}function w(q){let J=h(q),K=typeof q.mail==="object"&&q.mail!==null?q.mail:void 0,B=typeof q.bounce==="object"&&q.bounce!==null?q.bounce:void 0,G=typeof q.complaint==="object"&&q.complaint!==null?q.complaint:void 0,I=typeof q.open==="object"&&q.open!==null?q.open:void 0,Y=typeof q.click==="object"&&q.click!==null?q.click:void 0,Z=typeof q.deliveryDelay==="object"&&q.deliveryDelay!==null?q.deliveryDelay:void 0,L=j(q),O=U(q.timestamp??B?.timestamp??G?.timestamp??I?.timestamp??Y?.timestamp??Z?.timestamp??K?.timestamp);return[X({provider:"ses",type:Q(J,$),...typeof K?.messageId==="string"?{messageId:K.messageId}:{},...L!==void 0?{recipient:L}:{},...O!==void 0?{timestamp:O}:{},raw:q})]}function z(q){if(typeof q!=="object"||q===null)return[];let J=q,K=typeof J.Type==="string"?J.Type:"";if(K==="SubscriptionConfirmation")return[];if(K!=="Notification")return[];let B=J.Message,G;if(typeof B==="string")try{G=JSON.parse(B)}catch{return[{provider:"ses",type:"unknown",raw:q}]}else if(typeof B==="object"&&B!==null)G=B;else return[];if(typeof G!=="object"||G===null)return[{provider:"ses",type:"unknown",raw:q}];return w(G)}export{z as parse};
2
+
3
+ //# debugId=C5FC4A2C6082819B64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/webhooks/ses.ts"],
4
+ "sourcesContent": [
5
+ "import type { EmailEvent } from \"./types.js\";\nimport { emailEvent, mapEventType, parseTimestamp } from \"./types.js\";\n\nconst SES_EVENT_MAP: Record<string, EmailEvent[\"type\"]> = {\n Delivery: \"delivered\",\n Bounce: \"bounced\",\n Complaint: \"complained\",\n Open: \"opened\",\n Click: \"clicked\",\n DeliveryDelay: \"deferred\",\n Send: \"unknown\",\n Reject: \"bounced\",\n \"Rendering Failure\": \"bounced\",\n Subscription: \"unknown\",\n};\n\nfunction resolveSesEventType(record: Record<string, unknown>): string {\n if (typeof record.eventType === \"string\") {\n return record.eventType;\n }\n if (typeof record.notificationType === \"string\") {\n return record.notificationType;\n }\n return \"\";\n}\n\nfunction extractSesRecipient(record: Record<string, unknown>): string | undefined {\n const delivery =\n typeof record.delivery === \"object\" && record.delivery !== null\n ? (record.delivery as Record<string, unknown>)\n : undefined;\n if (\n delivery &&\n Array.isArray(delivery.recipients) &&\n typeof delivery.recipients[0] === \"string\"\n ) {\n return delivery.recipients[0];\n }\n\n const bounce =\n typeof record.bounce === \"object\" && record.bounce !== null\n ? (record.bounce as Record<string, unknown>)\n : undefined;\n if (bounce && Array.isArray(bounce.bouncedRecipients)) {\n const first = bounce.bouncedRecipients[0];\n if (\n typeof first === \"object\" &&\n first !== null &&\n typeof (first as Record<string, unknown>).emailAddress === \"string\"\n ) {\n return (first as Record<string, unknown>).emailAddress as string;\n }\n }\n\n const complaint =\n typeof record.complaint === \"object\" && record.complaint !== null\n ? (record.complaint as Record<string, unknown>)\n : undefined;\n if (complaint && Array.isArray(complaint.complainedRecipients)) {\n const first = complaint.complainedRecipients[0];\n if (\n typeof first === \"object\" &&\n first !== null &&\n typeof (first as Record<string, unknown>).emailAddress === \"string\"\n ) {\n return (first as Record<string, unknown>).emailAddress as string;\n }\n }\n\n const mail =\n typeof record.mail === \"object\" && record.mail !== null\n ? (record.mail as Record<string, unknown>)\n : undefined;\n if (Array.isArray(mail?.destination) && typeof mail.destination[0] === \"string\") {\n return mail.destination[0];\n }\n\n return undefined;\n}\n\nfunction parseSesEvent(record: Record<string, unknown>): EmailEvent[] {\n const eventType = resolveSesEventType(record);\n const mail =\n typeof record.mail === \"object\" && record.mail !== null\n ? (record.mail as Record<string, unknown>)\n : undefined;\n\n const bounce =\n typeof record.bounce === \"object\" && record.bounce !== null\n ? (record.bounce as Record<string, unknown>)\n : undefined;\n const complaint =\n typeof record.complaint === \"object\" && record.complaint !== null\n ? (record.complaint as Record<string, unknown>)\n : undefined;\n const open =\n typeof record.open === \"object\" && record.open !== null\n ? (record.open as Record<string, unknown>)\n : undefined;\n const click =\n typeof record.click === \"object\" && record.click !== null\n ? (record.click as Record<string, unknown>)\n : undefined;\n const deliveryDelay =\n typeof record.deliveryDelay === \"object\" && record.deliveryDelay !== null\n ? (record.deliveryDelay as Record<string, unknown>)\n : undefined;\n\n const recipient = extractSesRecipient(record);\n const timestamp = parseTimestamp(\n record.timestamp ??\n bounce?.timestamp ??\n complaint?.timestamp ??\n open?.timestamp ??\n click?.timestamp ??\n deliveryDelay?.timestamp ??\n mail?.timestamp,\n );\n\n return [\n emailEvent({\n provider: \"ses\",\n type: mapEventType(eventType, SES_EVENT_MAP),\n ...(typeof mail?.messageId === \"string\" ? { messageId: mail.messageId } : {}),\n ...(recipient !== undefined ? { recipient } : {}),\n ...(timestamp !== undefined ? { timestamp } : {}),\n raw: record,\n }),\n ];\n}\n\n/**\n * Parse an AWS SES webhook payload (SNS envelope) into normalized {@link EmailEvent} records.\n * Handles SubscriptionConfirmation (returns `[]`) and double-encoded Notification messages.\n */\nexport function parse(payload: unknown): EmailEvent[] {\n if (typeof payload !== \"object\" || payload === null) {\n return [];\n }\n\n const envelope = payload as Record<string, unknown>;\n const snsType = typeof envelope.Type === \"string\" ? envelope.Type : \"\";\n\n if (snsType === \"SubscriptionConfirmation\") {\n return [];\n }\n\n if (snsType !== \"Notification\") {\n return [];\n }\n\n const messageField = envelope.Message;\n let inner: unknown;\n\n if (typeof messageField === \"string\") {\n try {\n inner = JSON.parse(messageField);\n } catch {\n return [\n {\n provider: \"ses\",\n type: \"unknown\" as const,\n raw: payload,\n },\n ];\n }\n } else if (typeof messageField === \"object\" && messageField !== null) {\n inner = messageField;\n } else {\n return [];\n }\n\n if (typeof inner !== \"object\" || inner === null) {\n return [\n {\n provider: \"ses\",\n type: \"unknown\" as const,\n raw: payload,\n },\n ];\n }\n\n return parseSesEvent(inner as Record<string, unknown>);\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "C5FC4A2C6082819B64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,3 @@
1
+ import{a,b,c}from"../chunk-pqp843mh.js";import"../chunk-mg8m26nr.js";export{a as timingSafeEqual,c as decodeHexBytes,b as decodeBase64Bytes};
2
+
3
+ //# debugId=CA7D50FE7388E14864756E2164756E21
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "AB3248C3DD5B9EFC64756E2164756E21",
7
+ "debugId": "CA7D50FE7388E14864756E2164756E21",
8
8
  "names": []
9
9
  }
package/dist/webhooks.js CHANGED
@@ -1,3 +1,13 @@
1
- import"./chunk-rhade81v.js";export{v as verifyResendSignature,t as verifyMailgunSignature,n as verifyMailgunPayload,k as parseSesWebhook,m as parseSendGridWebhook,l as parseResendWebhook,p as parsePostmarkWebhook,s as parseMailgunWebhook,o as parseBrevoWebhook};
2
-
3
- //# debugId=0ADA81CFDCA8B16A64756E2164756E21
1
+ export { parse as parseBrevoWebhook } from "./webhooks/brevo.js";
2
+ export {
3
+ parse as parseMailgunWebhook,
4
+ verifyPayload as verifyMailgunPayload,
5
+ verifySignature as verifyMailgunSignature,
6
+ } from "./webhooks/mailgun.js";
7
+ export { parse as parsePostmarkWebhook } from "./webhooks/postmark.js";
8
+ export {
9
+ parse as parseResendWebhook,
10
+ verifySignature as verifyResendSignature,
11
+ } from "./webhooks/resend.js";
12
+ export { parse as parseSendGridWebhook } from "./webhooks/sendgrid.js";
13
+ export { parse as parseSesWebhook } from "./webhooks/ses.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sently",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Runtime-agnostic email library for Node.js, Bun, Deno, and Cloudflare Workers. ESM-native Nodemailer alternative with zero dependencies.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1,4 +0,0 @@
1
- import{G as D,J}from"./chunk-32dj0v9g.js";var Q="https://oauth2.googleapis.com/token",$="https://login.microsoftonline.com/common/oauth2/v2.0/token",V=30000;class W{config;cachedToken=null;expiresAt=0;refreshPromise=null;constructor(m){if(this.config=m,m.accessToken)this.cachedToken=m.accessToken,this.expiresAt=Date.now()+3600000}async getAccessToken(){if(this.config.getToken)return this.config.getToken();if(this.cachedToken&&Date.now()<this.expiresAt-V)return this.cachedToken;if(!this.refreshPromise)this.refreshPromise=this.refreshAccessToken().finally(()=>{this.refreshPromise=null});return this.refreshPromise}async refreshAccessToken(){if(this.config.getToken){let v=await this.config.getToken();return this.cachedToken=v,this.expiresAt=Date.now()+3600000,v}let m=this.config.tokenUrl??Q,z=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token"}),q=await fetch(m,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:z.toString()});if(!q.ok){let v=await q.text();throw Error(`OAuth2 token refresh failed (${q.status}): ${v}`)}let C=await q.json();return this.cachedToken=C.access_token,this.expiresAt=Date.now()+C.expires_in*1000,C.access_token}async buildXOAUTH2(){let m=await this.getAccessToken(),z=`user=${this.config.user}\x01auth=Bearer ${m}\x01\x01`;return D(J(z)).replace(/\r\n/g,"")}}
2
- export{Q as g,$ as h,W as i};
3
-
4
- //# debugId=92611D4BB94BFF7B64756E2164756E21
@@ -1,9 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [
5
- ],
6
- "mappings": "",
7
- "debugId": "0ADA81CFDCA8B16A64756E2164756E21",
8
- "names": []
9
- }