mailery 0.16.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.
- package/dist/index.cjs +39 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +39 -6
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +37 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +37 -4
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -190,7 +190,15 @@ type WebhookToleranceOption = number | false;
|
|
|
190
190
|
|
|
191
191
|
interface SendGridProviderOptions {
|
|
192
192
|
apiKey: string;
|
|
193
|
-
/**
|
|
193
|
+
/**
|
|
194
|
+
* ECDSA public key from SendGrid → Settings → Mail Settings → Signed Event
|
|
195
|
+
* Webhook. Either form SendGrid hands out is accepted: the single-line
|
|
196
|
+
* base64 string its dashboard shows and its API returns as `public_key`
|
|
197
|
+
* (what `mailery setup-sendgrid` prints), or the same key as a PEM block.
|
|
198
|
+
* A PEM whose newlines were escaped to `\n` for an .env line is unescaped.
|
|
199
|
+
* Anything that does not parse as a public key throws at construction —
|
|
200
|
+
* a key that silently verifies nothing is the failure this replaces.
|
|
201
|
+
*/
|
|
194
202
|
webhookVerificationKey?: string;
|
|
195
203
|
/**
|
|
196
204
|
* Replay window for the signed webhook timestamp, in seconds.
|
|
@@ -213,6 +221,8 @@ declare class SendGridProvider implements MailProvider {
|
|
|
213
221
|
readonly sendRatePerSecond: number;
|
|
214
222
|
/** Resolved replay window in seconds; `0` means the check is disabled. */
|
|
215
223
|
readonly webhookToleranceSeconds: number;
|
|
224
|
+
/** The verification key as PEM, whatever shape it was configured in. */
|
|
225
|
+
private readonly verificationKeyPem;
|
|
216
226
|
constructor(opts: SendGridProviderOptions);
|
|
217
227
|
send(args: SendArgs): Promise<SendResult>;
|
|
218
228
|
verifyWebhook(rawBody: Buffer, headers: Record<string, string>): Promise<boolean>;
|
package/dist/index.d.ts
CHANGED
|
@@ -190,7 +190,15 @@ type WebhookToleranceOption = number | false;
|
|
|
190
190
|
|
|
191
191
|
interface SendGridProviderOptions {
|
|
192
192
|
apiKey: string;
|
|
193
|
-
/**
|
|
193
|
+
/**
|
|
194
|
+
* ECDSA public key from SendGrid → Settings → Mail Settings → Signed Event
|
|
195
|
+
* Webhook. Either form SendGrid hands out is accepted: the single-line
|
|
196
|
+
* base64 string its dashboard shows and its API returns as `public_key`
|
|
197
|
+
* (what `mailery setup-sendgrid` prints), or the same key as a PEM block.
|
|
198
|
+
* A PEM whose newlines were escaped to `\n` for an .env line is unescaped.
|
|
199
|
+
* Anything that does not parse as a public key throws at construction —
|
|
200
|
+
* a key that silently verifies nothing is the failure this replaces.
|
|
201
|
+
*/
|
|
194
202
|
webhookVerificationKey?: string;
|
|
195
203
|
/**
|
|
196
204
|
* Replay window for the signed webhook timestamp, in seconds.
|
|
@@ -213,6 +221,8 @@ declare class SendGridProvider implements MailProvider {
|
|
|
213
221
|
readonly sendRatePerSecond: number;
|
|
214
222
|
/** Resolved replay window in seconds; `0` means the check is disabled. */
|
|
215
223
|
readonly webhookToleranceSeconds: number;
|
|
224
|
+
/** The verification key as PEM, whatever shape it was configured in. */
|
|
225
|
+
private readonly verificationKeyPem;
|
|
216
226
|
constructor(opts: SendGridProviderOptions);
|
|
217
227
|
send(args: SendArgs): Promise<SendResult>;
|
|
218
228
|
verifyWebhook(rawBody: Buffer, headers: Record<string, string>): Promise<boolean>;
|
package/dist/index.js
CHANGED
|
@@ -268,8 +268,36 @@ var init_webhook_tolerance = __esm({
|
|
|
268
268
|
// src/server/providers/sendgrid.ts
|
|
269
269
|
var sendgrid_exports = {};
|
|
270
270
|
__export(sendgrid_exports, {
|
|
271
|
-
SendGridProvider: () => SendGridProvider
|
|
271
|
+
SendGridProvider: () => SendGridProvider,
|
|
272
|
+
normalizeWebhookVerificationKey: () => normalizeWebhookVerificationKey
|
|
272
273
|
});
|
|
274
|
+
function normalizeWebhookVerificationKey(input) {
|
|
275
|
+
let key = String(input ?? "").trim().replace(/^["']|["']$/g, "");
|
|
276
|
+
if (key.includes("\\n")) key = key.replace(/\\n/g, "\n");
|
|
277
|
+
let pem;
|
|
278
|
+
if (key.includes(PEM_HEADER)) {
|
|
279
|
+
pem = key;
|
|
280
|
+
} else {
|
|
281
|
+
const b64 = key.replace(/\s+/g, "");
|
|
282
|
+
if (!b64 || !/^[A-Za-z0-9+/=]+$/.test(b64)) {
|
|
283
|
+
throw new Error(
|
|
284
|
+
"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."
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
pem = `${PEM_HEADER}
|
|
288
|
+
${b64.match(/.{1,64}/g).join("\n")}
|
|
289
|
+
${PEM_FOOTER}
|
|
290
|
+
`;
|
|
291
|
+
}
|
|
292
|
+
try {
|
|
293
|
+
crypto2.createPublicKey(pem);
|
|
294
|
+
} catch (err) {
|
|
295
|
+
throw new Error(
|
|
296
|
+
`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.`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return pem;
|
|
300
|
+
}
|
|
273
301
|
function normalizeSendGridEvent(e) {
|
|
274
302
|
const type = mapEventType(e.event);
|
|
275
303
|
if (!type) return null;
|
|
@@ -308,24 +336,29 @@ function mapEventType(sgEvent) {
|
|
|
308
336
|
return null;
|
|
309
337
|
}
|
|
310
338
|
}
|
|
311
|
-
var SG_SIG_HEADER, SG_TS_HEADER, SendGridProvider;
|
|
339
|
+
var SG_SIG_HEADER, SG_TS_HEADER, PEM_HEADER, PEM_FOOTER, SendGridProvider;
|
|
312
340
|
var init_sendgrid = __esm({
|
|
313
341
|
"src/server/providers/sendgrid.ts"() {
|
|
314
342
|
init_webhook_tolerance();
|
|
315
343
|
SG_SIG_HEADER = "x-twilio-email-event-webhook-signature";
|
|
316
344
|
SG_TS_HEADER = "x-twilio-email-event-webhook-timestamp";
|
|
345
|
+
PEM_HEADER = "-----BEGIN PUBLIC KEY-----";
|
|
346
|
+
PEM_FOOTER = "-----END PUBLIC KEY-----";
|
|
317
347
|
SendGridProvider = class {
|
|
318
348
|
constructor(opts) {
|
|
319
349
|
this.opts = opts;
|
|
320
350
|
sgMail.setApiKey(opts.apiKey);
|
|
321
351
|
this.sendRatePerSecond = opts.sendRatePerSecond ?? 10;
|
|
322
352
|
this.webhookToleranceSeconds = resolveWebhookToleranceSeconds(opts.webhookToleranceSeconds);
|
|
353
|
+
this.verificationKeyPem = opts.webhookVerificationKey ? normalizeWebhookVerificationKey(opts.webhookVerificationKey) : null;
|
|
323
354
|
}
|
|
324
355
|
opts;
|
|
325
356
|
name = "sendgrid";
|
|
326
357
|
sendRatePerSecond;
|
|
327
358
|
/** Resolved replay window in seconds; `0` means the check is disabled. */
|
|
328
359
|
webhookToleranceSeconds;
|
|
360
|
+
/** The verification key as PEM, whatever shape it was configured in. */
|
|
361
|
+
verificationKeyPem;
|
|
329
362
|
async send(args) {
|
|
330
363
|
const msg = {
|
|
331
364
|
to: args.to,
|
|
@@ -357,7 +390,7 @@ var init_sendgrid = __esm({
|
|
|
357
390
|
};
|
|
358
391
|
}
|
|
359
392
|
async verifyWebhook(rawBody, headers) {
|
|
360
|
-
if (!this.
|
|
393
|
+
if (!this.verificationKeyPem) return false;
|
|
361
394
|
const sig = headers[SG_SIG_HEADER];
|
|
362
395
|
const ts = headers[SG_TS_HEADER];
|
|
363
396
|
if (!sig || !ts) return false;
|
|
@@ -365,7 +398,7 @@ var init_sendgrid = __esm({
|
|
|
365
398
|
try {
|
|
366
399
|
const verifier = crypto2.createVerify("sha256");
|
|
367
400
|
verifier.update(payload);
|
|
368
|
-
if (!verifier.verify(this.
|
|
401
|
+
if (!verifier.verify(this.verificationKeyPem, sig, "base64")) return false;
|
|
369
402
|
} catch {
|
|
370
403
|
return false;
|
|
371
404
|
}
|
|
@@ -8205,7 +8238,7 @@ function unitToMs2(value, unit) {
|
|
|
8205
8238
|
}
|
|
8206
8239
|
|
|
8207
8240
|
// src/server/api/agent.ts
|
|
8208
|
-
var VERSION = "0.16.
|
|
8241
|
+
var VERSION = "0.16.1" ;
|
|
8209
8242
|
var MIN_AGENT_TOKEN_LENGTH = 24;
|
|
8210
8243
|
function createAgentRouter(mailer, opts) {
|
|
8211
8244
|
if (!opts || !Array.isArray(opts.tokens) || opts.tokens.length === 0) {
|
|
@@ -9905,7 +9938,7 @@ var DEDUPE_POLICIES = [
|
|
|
9905
9938
|
];
|
|
9906
9939
|
|
|
9907
9940
|
// src/server/index.ts
|
|
9908
|
-
var VERSION2 = "0.16.
|
|
9941
|
+
var VERSION2 = "0.16.1" ;
|
|
9909
9942
|
|
|
9910
9943
|
export { DEDUPE_POLICIES, DEFAULT_BOT_UA_RE, FLOW_STEP_KINDS, FlowOperationError, MIN_AGENT_TOKEN_LENGTH, Mailer, MongoContactAdapter, NullProvider, PREDICATE_KINDS, RESERVED_VAR_KEYS, SEGMENT_FILTER_KINDS, SendGridProvider, TRACKING_SIG_LENGTH, VERSION2 as VERSION, applyTracking, applyWebhookEvent, armFlow, compileMailyTemplate, compileTemplate, computeDeliveryTime, createAdminApiRouter, createAdminRouter, createAgentRouter, createPublicRouter, defaultFlowStep, defaultPredicate, defaultSegmentFilter, defineVars, derivePlaintext, disarmFlow, dispatchSend, drainPendingUnsubscribes, ensureIndexes, gateFlow, getCollections, isCanaryGate, predicateKind, processNewlyFiredEventTriggers, processOneRunStep, referencedPaths, renderForContact, renderTemplate, runTick, sendgridInboundParser, sha256Hex, signTrackingToken, signUnsubscribeToken, simulateFlow, stampWatermarkIfNull, sweepStrandedFlowRuns, ungateFlow, validateSenderDomain, varsJsonSchema, verifyTemplate, verifyTrackingToken, verifyUnsubscribeToken };
|
|
9911
9944
|
//# sourceMappingURL=index.js.map
|