mailery 0.15.0 → 0.16.1

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.
@@ -1668,4 +1668,4 @@ declare class NullProvider implements MailProvider {
1668
1668
  reset(): void;
1669
1669
  }
1670
1670
 
1671
- export { ensureIndexes as $, type AdapterFilter as A, type BotFilterConfig as B, type ContactAdapter as C, type DeliveryWindow as D, type EventDoc as E, type FlowStep as F, type SenderDomainRegistry as G, type HealthDoc as H, type SenderDomainValidation as I, type SubscriptionDoc as J, type SubscriptionStatus as K, type LeadDoc as L, type MailProvider as M, type NormalizedEvent as N, type OutboxDoc as O, type Predicate as P, type SuppressionDoc as Q, type RunnerContext as R, type SendArgs as S, type TemplateDoc as T, type SuppressionReason as U, type TemplateKind as V, type TemplateVersionDoc as W, type VarsAdapter as X, type VarsResolveInfo as Y, type WebhookEventDoc as Z, defineVars as _, type Contact as a, getCollections as a0, validateSenderDomain as a1, varsJsonSchema as a2, type FlowTrigger as a3, type QueueDriverConfig as a4, type SendResult as b, type MailTesterFeedback as c, Mailer as d, type SuppressionScope as e, type SegmentFilter as f, type AuditLogDoc as g, type BroadcastDoc as h, type BroadcastStatus as i, type CircuitBreakerThresholds as j, type Collections as k, type ContactTagDoc as l, type FlowDoc as m, type FlowGoal as n, type FlowRunDoc as o, type FlowRunStatus as p, type FlowVersionDoc as q, type HealthStatus as r, type MailerConfig as s, NullProvider as t, RESERVED_VAR_KEYS as u, type RedisOptions as v, type SegmentDefinition as w, type SendDoc as x, type SendStatus as y, type SenderDomainConfig as z };
1671
+ export { ensureIndexes as $, type AdapterFilter as A, type BotFilterConfig as B, type ContactAdapter as C, type DeliveryWindow as D, type EventDoc as E, type FlowStep as F, type SenderDomainRegistry as G, type HealthDoc as H, type SenderDomainValidation as I, type SubscriptionDoc as J, type SubscriptionStatus as K, type LeadDoc as L, type MailProvider as M, type NormalizedEvent as N, type OutboxDoc as O, type Predicate as P, type SuppressionDoc as Q, type RunnerContext as R, type SendArgs as S, type TemplateDoc as T, type SuppressionReason as U, type TemplateKind as V, type TemplateVersionDoc as W, type VarsAdapter as X, type VarsResolveInfo as Y, type WebhookEventDoc as Z, defineVars as _, type Contact as a, getCollections as a0, validateSenderDomain as a1, varsJsonSchema as a2, type FlowTrigger as a3, type QueueDriverConfig as a4, type SendResult as b, type MailTesterFeedback as c, Mailer as d, type Collections as e, type FlowDoc as f, type SuppressionScope as g, type SegmentFilter as h, type AuditLogDoc as i, type BroadcastDoc as j, type BroadcastStatus as k, type CircuitBreakerThresholds as l, type ContactTagDoc as m, type FlowGoal as n, type FlowRunDoc as o, type FlowRunStatus as p, type FlowVersionDoc as q, type HealthStatus as r, type MailerConfig as s, NullProvider as t, RESERVED_VAR_KEYS as u, type RedisOptions as v, type SegmentDefinition as w, type SendDoc as x, type SendStatus as y, type SenderDomainConfig as z };
@@ -1668,4 +1668,4 @@ declare class NullProvider implements MailProvider {
1668
1668
  reset(): void;
1669
1669
  }
1670
1670
 
1671
- export { ensureIndexes as $, type AdapterFilter as A, type BotFilterConfig as B, type ContactAdapter as C, type DeliveryWindow as D, type EventDoc as E, type FlowStep as F, type SenderDomainRegistry as G, type HealthDoc as H, type SenderDomainValidation as I, type SubscriptionDoc as J, type SubscriptionStatus as K, type LeadDoc as L, type MailProvider as M, type NormalizedEvent as N, type OutboxDoc as O, type Predicate as P, type SuppressionDoc as Q, type RunnerContext as R, type SendArgs as S, type TemplateDoc as T, type SuppressionReason as U, type TemplateKind as V, type TemplateVersionDoc as W, type VarsAdapter as X, type VarsResolveInfo as Y, type WebhookEventDoc as Z, defineVars as _, type Contact as a, getCollections as a0, validateSenderDomain as a1, varsJsonSchema as a2, type FlowTrigger as a3, type QueueDriverConfig as a4, type SendResult as b, type MailTesterFeedback as c, Mailer as d, type SuppressionScope as e, type SegmentFilter as f, type AuditLogDoc as g, type BroadcastDoc as h, type BroadcastStatus as i, type CircuitBreakerThresholds as j, type Collections as k, type ContactTagDoc as l, type FlowDoc as m, type FlowGoal as n, type FlowRunDoc as o, type FlowRunStatus as p, type FlowVersionDoc as q, type HealthStatus as r, type MailerConfig as s, NullProvider as t, RESERVED_VAR_KEYS as u, type RedisOptions as v, type SegmentDefinition as w, type SendDoc as x, type SendStatus as y, type SenderDomainConfig as z };
1671
+ export { ensureIndexes as $, type AdapterFilter as A, type BotFilterConfig as B, type ContactAdapter as C, type DeliveryWindow as D, type EventDoc as E, type FlowStep as F, type SenderDomainRegistry as G, type HealthDoc as H, type SenderDomainValidation as I, type SubscriptionDoc as J, type SubscriptionStatus as K, type LeadDoc as L, type MailProvider as M, type NormalizedEvent as N, type OutboxDoc as O, type Predicate as P, type SuppressionDoc as Q, type RunnerContext as R, type SendArgs as S, type TemplateDoc as T, type SuppressionReason as U, type TemplateKind as V, type TemplateVersionDoc as W, type VarsAdapter as X, type VarsResolveInfo as Y, type WebhookEventDoc as Z, defineVars as _, type Contact as a, getCollections as a0, validateSenderDomain as a1, varsJsonSchema as a2, type FlowTrigger as a3, type QueueDriverConfig as a4, type SendResult as b, type MailTesterFeedback as c, Mailer as d, type Collections as e, type FlowDoc as f, type SuppressionScope as g, type SegmentFilter as h, type AuditLogDoc as i, type BroadcastDoc as j, type BroadcastStatus as k, type CircuitBreakerThresholds as l, type ContactTagDoc as m, type FlowGoal as n, type FlowRunDoc as o, type FlowRunStatus as p, type FlowVersionDoc as q, type HealthStatus as r, type MailerConfig as s, NullProvider as t, RESERVED_VAR_KEYS as u, type RedisOptions as v, type SegmentDefinition as w, type SendDoc as x, type SendStatus as y, type SenderDomainConfig as z };
package/dist/testing.cjs CHANGED
@@ -314,8 +314,36 @@ var init_webhook_tolerance = __esm({
314
314
  // src/server/providers/sendgrid.ts
315
315
  var sendgrid_exports = {};
316
316
  __export(sendgrid_exports, {
317
- SendGridProvider: () => SendGridProvider
317
+ SendGridProvider: () => SendGridProvider,
318
+ normalizeWebhookVerificationKey: () => normalizeWebhookVerificationKey
318
319
  });
320
+ function normalizeWebhookVerificationKey(input) {
321
+ let key = String(input ?? "").trim().replace(/^["']|["']$/g, "");
322
+ if (key.includes("\\n")) key = key.replace(/\\n/g, "\n");
323
+ let pem;
324
+ if (key.includes(PEM_HEADER)) {
325
+ pem = key;
326
+ } else {
327
+ const b64 = key.replace(/\s+/g, "");
328
+ if (!b64 || !/^[A-Za-z0-9+/=]+$/.test(b64)) {
329
+ throw new Error(
330
+ "SendGridProvider: webhookVerificationKey is neither a PEM public key nor a base64 SPKI key. Copy the Verification Key from SendGrid \u2192 Settings \u2192 Mail Settings \u2192 Signed Event Webhook."
331
+ );
332
+ }
333
+ pem = `${PEM_HEADER}
334
+ ${b64.match(/.{1,64}/g).join("\n")}
335
+ ${PEM_FOOTER}
336
+ `;
337
+ }
338
+ try {
339
+ crypto2__default.default.createPublicKey(pem);
340
+ } catch (err) {
341
+ throw new Error(
342
+ `SendGridProvider: webhookVerificationKey did not parse as a public key (${String(err?.message ?? err)}). Copy the Verification Key from SendGrid \u2192 Settings \u2192 Mail Settings \u2192 Signed Event Webhook.`
343
+ );
344
+ }
345
+ return pem;
346
+ }
319
347
  function normalizeSendGridEvent(e) {
320
348
  const type = mapEventType(e.event);
321
349
  if (!type) return null;
@@ -354,24 +382,29 @@ function mapEventType(sgEvent) {
354
382
  return null;
355
383
  }
356
384
  }
357
- var SG_SIG_HEADER, SG_TS_HEADER, SendGridProvider;
385
+ var SG_SIG_HEADER, SG_TS_HEADER, PEM_HEADER, PEM_FOOTER, SendGridProvider;
358
386
  var init_sendgrid = __esm({
359
387
  "src/server/providers/sendgrid.ts"() {
360
388
  init_webhook_tolerance();
361
389
  SG_SIG_HEADER = "x-twilio-email-event-webhook-signature";
362
390
  SG_TS_HEADER = "x-twilio-email-event-webhook-timestamp";
391
+ PEM_HEADER = "-----BEGIN PUBLIC KEY-----";
392
+ PEM_FOOTER = "-----END PUBLIC KEY-----";
363
393
  SendGridProvider = class {
364
394
  constructor(opts) {
365
395
  this.opts = opts;
366
396
  sgMail__default.default.setApiKey(opts.apiKey);
367
397
  this.sendRatePerSecond = opts.sendRatePerSecond ?? 10;
368
398
  this.webhookToleranceSeconds = resolveWebhookToleranceSeconds(opts.webhookToleranceSeconds);
399
+ this.verificationKeyPem = opts.webhookVerificationKey ? normalizeWebhookVerificationKey(opts.webhookVerificationKey) : null;
369
400
  }
370
401
  opts;
371
402
  name = "sendgrid";
372
403
  sendRatePerSecond;
373
404
  /** Resolved replay window in seconds; `0` means the check is disabled. */
374
405
  webhookToleranceSeconds;
406
+ /** The verification key as PEM, whatever shape it was configured in. */
407
+ verificationKeyPem;
375
408
  async send(args) {
376
409
  const msg = {
377
410
  to: args.to,
@@ -403,7 +436,7 @@ var init_sendgrid = __esm({
403
436
  };
404
437
  }
405
438
  async verifyWebhook(rawBody, headers) {
406
- if (!this.opts.webhookVerificationKey) return false;
439
+ if (!this.verificationKeyPem) return false;
407
440
  const sig = headers[SG_SIG_HEADER];
408
441
  const ts = headers[SG_TS_HEADER];
409
442
  if (!sig || !ts) return false;
@@ -411,7 +444,7 @@ var init_sendgrid = __esm({
411
444
  try {
412
445
  const verifier = crypto2__default.default.createVerify("sha256");
413
446
  verifier.update(payload);
414
- if (!verifier.verify(this.opts.webhookVerificationKey, sig, "base64")) return false;
447
+ if (!verifier.verify(this.verificationKeyPem, sig, "base64")) return false;
415
448
  } catch {
416
449
  return false;
417
450
  }