shipmail 0.1.5 → 0.1.19
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/README.md +3 -7
- package/dist/index.cjs +226 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +204 -54
- package/dist/index.d.ts +204 -54
- package/dist/index.js +220 -86
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { timingSafeEqual, createHmac } from 'crypto';
|
|
2
|
-
|
|
3
1
|
// src/errors.ts
|
|
4
2
|
var ShipMailError = class extends Error {
|
|
5
3
|
constructor(message, options) {
|
|
@@ -35,6 +33,12 @@ var ValidationError = class extends ShipMailError {
|
|
|
35
33
|
this.details = options?.details;
|
|
36
34
|
}
|
|
37
35
|
};
|
|
36
|
+
var QuotaExceededError = class extends ShipMailError {
|
|
37
|
+
constructor(message, requestId) {
|
|
38
|
+
super(message, { status: 403, type: "quota_exceeded", requestId, retryable: false });
|
|
39
|
+
this.name = "QuotaExceededError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
38
42
|
var NotFoundError = class extends ShipMailError {
|
|
39
43
|
constructor(message, requestId) {
|
|
40
44
|
super(message, { status: 404, type: "not_found", requestId, retryable: false });
|
|
@@ -85,6 +89,8 @@ function mapErrorFromResponse(status, body, requestId) {
|
|
|
85
89
|
return new AuthenticationError(error.message, rid);
|
|
86
90
|
case "authorization_error":
|
|
87
91
|
return new AuthorizationError(error.message, rid);
|
|
92
|
+
case "quota_exceeded":
|
|
93
|
+
return new QuotaExceededError(error.message, rid);
|
|
88
94
|
case "validation_error":
|
|
89
95
|
return new ValidationError(error.message, { requestId: rid, details: error.details });
|
|
90
96
|
case "not_found":
|
|
@@ -138,21 +144,23 @@ var ApiResource = class {
|
|
|
138
144
|
|
|
139
145
|
// src/resources/domains.ts
|
|
140
146
|
var Domains = class extends ApiResource {
|
|
141
|
-
create(params) {
|
|
147
|
+
create(params, options) {
|
|
142
148
|
return this.client.request({
|
|
143
149
|
method: "POST",
|
|
144
150
|
path: "/domains",
|
|
145
|
-
body: params
|
|
151
|
+
body: params,
|
|
152
|
+
methodOptions: options
|
|
146
153
|
});
|
|
147
154
|
}
|
|
148
|
-
list(params) {
|
|
155
|
+
list(params, options) {
|
|
149
156
|
return this.client.request({
|
|
150
157
|
method: "GET",
|
|
151
158
|
path: "/domains",
|
|
152
159
|
query: {
|
|
153
160
|
cursor: params?.cursor,
|
|
154
161
|
limit: params?.limit
|
|
155
|
-
}
|
|
162
|
+
},
|
|
163
|
+
methodOptions: options
|
|
156
164
|
});
|
|
157
165
|
}
|
|
158
166
|
listAutoPaginating(params) {
|
|
@@ -160,43 +168,64 @@ var Domains = class extends ApiResource {
|
|
|
160
168
|
limit: params?.limit
|
|
161
169
|
});
|
|
162
170
|
}
|
|
163
|
-
get(id) {
|
|
171
|
+
get(id, options) {
|
|
164
172
|
return this.client.request({
|
|
165
173
|
method: "GET",
|
|
166
|
-
path: `/domains/${id}
|
|
174
|
+
path: `/domains/${encodeURIComponent(id)}`,
|
|
175
|
+
methodOptions: options
|
|
167
176
|
});
|
|
168
177
|
}
|
|
169
|
-
update(id, params) {
|
|
178
|
+
update(id, params, options) {
|
|
170
179
|
return this.client.request({
|
|
171
180
|
method: "PATCH",
|
|
172
|
-
path: `/domains/${id}`,
|
|
173
|
-
body: params
|
|
181
|
+
path: `/domains/${encodeURIComponent(id)}`,
|
|
182
|
+
body: params,
|
|
183
|
+
methodOptions: options
|
|
174
184
|
});
|
|
175
185
|
}
|
|
176
|
-
delete(id) {
|
|
186
|
+
delete(id, options) {
|
|
177
187
|
return this.client.request({
|
|
178
188
|
method: "DELETE",
|
|
179
|
-
path: `/domains/${id}
|
|
189
|
+
path: `/domains/${encodeURIComponent(id)}`,
|
|
190
|
+
methodOptions: options
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
verify(id, options) {
|
|
194
|
+
return this.client.request({
|
|
195
|
+
method: "POST",
|
|
196
|
+
path: `/domains/${encodeURIComponent(id)}/verification`,
|
|
197
|
+
methodOptions: options
|
|
180
198
|
});
|
|
181
199
|
}
|
|
182
|
-
|
|
200
|
+
search(params, options) {
|
|
183
201
|
return this.client.request({
|
|
184
202
|
method: "POST",
|
|
185
|
-
path:
|
|
203
|
+
path: "/domains/search",
|
|
204
|
+
body: params,
|
|
205
|
+
methodOptions: options
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
register(params, options) {
|
|
209
|
+
return this.client.request({
|
|
210
|
+
method: "POST",
|
|
211
|
+
path: "/domains/register",
|
|
212
|
+
body: params,
|
|
213
|
+
methodOptions: options
|
|
186
214
|
});
|
|
187
215
|
}
|
|
188
216
|
};
|
|
189
217
|
|
|
190
218
|
// src/resources/mailboxes.ts
|
|
191
219
|
var Mailboxes = class extends ApiResource {
|
|
192
|
-
create(params) {
|
|
220
|
+
create(params, options) {
|
|
193
221
|
return this.client.request({
|
|
194
222
|
method: "POST",
|
|
195
223
|
path: "/mailboxes",
|
|
196
|
-
body: params
|
|
224
|
+
body: params,
|
|
225
|
+
methodOptions: options
|
|
197
226
|
});
|
|
198
227
|
}
|
|
199
|
-
list(params) {
|
|
228
|
+
list(params, options) {
|
|
200
229
|
return this.client.request({
|
|
201
230
|
method: "GET",
|
|
202
231
|
path: "/mailboxes",
|
|
@@ -204,7 +233,8 @@ var Mailboxes = class extends ApiResource {
|
|
|
204
233
|
domain_id: params?.domain_id,
|
|
205
234
|
cursor: params?.cursor,
|
|
206
235
|
limit: params?.limit
|
|
207
|
-
}
|
|
236
|
+
},
|
|
237
|
+
methodOptions: options
|
|
208
238
|
});
|
|
209
239
|
}
|
|
210
240
|
listAutoPaginating(params) {
|
|
@@ -213,71 +243,124 @@ var Mailboxes = class extends ApiResource {
|
|
|
213
243
|
limit: params?.limit
|
|
214
244
|
});
|
|
215
245
|
}
|
|
216
|
-
get(id) {
|
|
246
|
+
get(id, options) {
|
|
217
247
|
return this.client.request({
|
|
218
248
|
method: "GET",
|
|
219
|
-
path: `/mailboxes/${id}
|
|
249
|
+
path: `/mailboxes/${encodeURIComponent(id)}`,
|
|
250
|
+
methodOptions: options
|
|
220
251
|
});
|
|
221
252
|
}
|
|
222
|
-
update(id, params) {
|
|
253
|
+
update(id, params, options) {
|
|
223
254
|
return this.client.request({
|
|
224
255
|
method: "PATCH",
|
|
225
|
-
path: `/mailboxes/${id}`,
|
|
226
|
-
body: params
|
|
256
|
+
path: `/mailboxes/${encodeURIComponent(id)}`,
|
|
257
|
+
body: params,
|
|
258
|
+
methodOptions: options
|
|
227
259
|
});
|
|
228
260
|
}
|
|
229
|
-
delete(id) {
|
|
261
|
+
delete(id, options) {
|
|
230
262
|
return this.client.request({
|
|
231
263
|
method: "DELETE",
|
|
232
|
-
path: `/mailboxes/${id}
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
uploadAvatar(id, data, contentType) {
|
|
236
|
-
return this.client.request({
|
|
237
|
-
method: "PUT",
|
|
238
|
-
path: `/mailboxes/${id}/avatar`,
|
|
239
|
-
rawBody: data,
|
|
240
|
-
contentType
|
|
264
|
+
path: `/mailboxes/${encodeURIComponent(id)}`,
|
|
265
|
+
methodOptions: options
|
|
241
266
|
});
|
|
242
267
|
}
|
|
243
|
-
|
|
268
|
+
updateAutoReply(id, params, options) {
|
|
244
269
|
return this.client.request({
|
|
245
|
-
method: "
|
|
246
|
-
path: `/mailboxes/${id}/
|
|
270
|
+
method: "PATCH",
|
|
271
|
+
path: `/mailboxes/${encodeURIComponent(id)}/auto-reply`,
|
|
272
|
+
body: params,
|
|
273
|
+
methodOptions: options
|
|
247
274
|
});
|
|
248
275
|
}
|
|
249
276
|
};
|
|
250
277
|
|
|
251
278
|
// src/resources/messages.ts
|
|
252
279
|
var Messages = class extends ApiResource {
|
|
253
|
-
send(params) {
|
|
280
|
+
send(params, options) {
|
|
254
281
|
return this.client.request({
|
|
255
282
|
method: "POST",
|
|
256
283
|
path: "/messages",
|
|
257
|
-
body: params
|
|
284
|
+
body: params,
|
|
285
|
+
methodOptions: options
|
|
258
286
|
});
|
|
259
287
|
}
|
|
260
|
-
|
|
288
|
+
list(params, options) {
|
|
261
289
|
return this.client.request({
|
|
262
290
|
method: "GET",
|
|
263
|
-
path:
|
|
291
|
+
path: "/messages",
|
|
292
|
+
query: {
|
|
293
|
+
mailbox_id: params.mailbox_id,
|
|
294
|
+
cursor: params.cursor,
|
|
295
|
+
limit: params.limit
|
|
296
|
+
},
|
|
297
|
+
methodOptions: options
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
listAutoPaginating(params) {
|
|
301
|
+
return new Page(this.client, "/messages", {
|
|
302
|
+
mailbox_id: params.mailbox_id,
|
|
303
|
+
limit: params.limit
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
get(id, options) {
|
|
307
|
+
return this.client.request({
|
|
308
|
+
method: "GET",
|
|
309
|
+
path: `/messages/${encodeURIComponent(id)}`,
|
|
310
|
+
methodOptions: options
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
reply(id, params, options) {
|
|
314
|
+
return this.client.request({
|
|
315
|
+
method: "POST",
|
|
316
|
+
path: `/messages/${encodeURIComponent(id)}/reply`,
|
|
317
|
+
body: params,
|
|
318
|
+
methodOptions: options
|
|
264
319
|
});
|
|
265
320
|
}
|
|
266
321
|
};
|
|
267
322
|
|
|
268
323
|
// src/resources/status.ts
|
|
269
324
|
var Status = class extends ApiResource {
|
|
270
|
-
get() {
|
|
325
|
+
get(options) {
|
|
326
|
+
return this.client.request({
|
|
327
|
+
method: "GET",
|
|
328
|
+
path: "/status",
|
|
329
|
+
methodOptions: options
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
// src/resources/suppressions.ts
|
|
335
|
+
var Suppressions = class extends ApiResource {
|
|
336
|
+
list(params, options) {
|
|
271
337
|
return this.client.request({
|
|
272
338
|
method: "GET",
|
|
273
|
-
path: "/
|
|
339
|
+
path: "/suppressions",
|
|
340
|
+
query: {
|
|
341
|
+
cursor: params?.cursor,
|
|
342
|
+
limit: params?.limit
|
|
343
|
+
},
|
|
344
|
+
methodOptions: options
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
listAutoPaginating(params) {
|
|
348
|
+
return new Page(this.client, "/suppressions", {
|
|
349
|
+
limit: params?.limit
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
remove(email, options) {
|
|
353
|
+
return this.client.request({
|
|
354
|
+
method: "DELETE",
|
|
355
|
+
path: `/suppressions/${encodeURIComponent(email)}`,
|
|
356
|
+
methodOptions: options
|
|
274
357
|
});
|
|
275
358
|
}
|
|
276
359
|
};
|
|
277
360
|
|
|
278
361
|
// src/resources/threads.ts
|
|
279
362
|
var Threads = class extends ApiResource {
|
|
280
|
-
list(params) {
|
|
363
|
+
list(params, options) {
|
|
281
364
|
return this.client.request({
|
|
282
365
|
method: "GET",
|
|
283
366
|
path: "/threads",
|
|
@@ -285,7 +368,8 @@ var Threads = class extends ApiResource {
|
|
|
285
368
|
mailbox_id: params.mailbox_id,
|
|
286
369
|
cursor: params.cursor,
|
|
287
370
|
limit: params.limit
|
|
288
|
-
}
|
|
371
|
+
},
|
|
372
|
+
methodOptions: options
|
|
289
373
|
});
|
|
290
374
|
}
|
|
291
375
|
listAutoPaginating(params) {
|
|
@@ -294,42 +378,46 @@ var Threads = class extends ApiResource {
|
|
|
294
378
|
limit: params.limit
|
|
295
379
|
});
|
|
296
380
|
}
|
|
297
|
-
get(id, params) {
|
|
381
|
+
get(id, params, options) {
|
|
298
382
|
return this.client.request({
|
|
299
383
|
method: "GET",
|
|
300
|
-
path: `/threads/${id}`,
|
|
384
|
+
path: `/threads/${encodeURIComponent(id)}`,
|
|
301
385
|
query: {
|
|
302
386
|
cursor: params?.cursor,
|
|
303
387
|
limit: params?.limit
|
|
304
|
-
}
|
|
388
|
+
},
|
|
389
|
+
methodOptions: options
|
|
305
390
|
});
|
|
306
391
|
}
|
|
307
|
-
reply(id, params) {
|
|
392
|
+
reply(id, params, options) {
|
|
308
393
|
return this.client.request({
|
|
309
394
|
method: "POST",
|
|
310
|
-
path: `/threads/${id}/reply`,
|
|
311
|
-
body: params
|
|
395
|
+
path: `/threads/${encodeURIComponent(id)}/reply`,
|
|
396
|
+
body: params,
|
|
397
|
+
methodOptions: options
|
|
312
398
|
});
|
|
313
399
|
}
|
|
314
400
|
};
|
|
315
401
|
|
|
316
402
|
// src/resources/webhooks.ts
|
|
317
403
|
var Webhooks = class extends ApiResource {
|
|
318
|
-
create(params) {
|
|
404
|
+
create(params, options) {
|
|
319
405
|
return this.client.request({
|
|
320
406
|
method: "POST",
|
|
321
407
|
path: "/webhooks",
|
|
322
|
-
body: params
|
|
408
|
+
body: params,
|
|
409
|
+
methodOptions: options
|
|
323
410
|
});
|
|
324
411
|
}
|
|
325
|
-
list(params) {
|
|
412
|
+
list(params, options) {
|
|
326
413
|
return this.client.request({
|
|
327
414
|
method: "GET",
|
|
328
415
|
path: "/webhooks",
|
|
329
416
|
query: {
|
|
330
417
|
cursor: params?.cursor,
|
|
331
418
|
limit: params?.limit
|
|
332
|
-
}
|
|
419
|
+
},
|
|
420
|
+
methodOptions: options
|
|
333
421
|
});
|
|
334
422
|
}
|
|
335
423
|
listAutoPaginating(params) {
|
|
@@ -337,69 +425,82 @@ var Webhooks = class extends ApiResource {
|
|
|
337
425
|
limit: params?.limit
|
|
338
426
|
});
|
|
339
427
|
}
|
|
340
|
-
get(id) {
|
|
428
|
+
get(id, options) {
|
|
341
429
|
return this.client.request({
|
|
342
430
|
method: "GET",
|
|
343
|
-
path: `/webhooks/${id}
|
|
431
|
+
path: `/webhooks/${encodeURIComponent(id)}`,
|
|
432
|
+
methodOptions: options
|
|
344
433
|
});
|
|
345
434
|
}
|
|
346
|
-
update(id, params) {
|
|
435
|
+
update(id, params, options) {
|
|
347
436
|
return this.client.request({
|
|
348
437
|
method: "PATCH",
|
|
349
|
-
path: `/webhooks/${id}`,
|
|
350
|
-
body: params
|
|
438
|
+
path: `/webhooks/${encodeURIComponent(id)}`,
|
|
439
|
+
body: params,
|
|
440
|
+
methodOptions: options
|
|
351
441
|
});
|
|
352
442
|
}
|
|
353
|
-
delete(id) {
|
|
443
|
+
delete(id, options) {
|
|
354
444
|
return this.client.request({
|
|
355
445
|
method: "DELETE",
|
|
356
|
-
path: `/webhooks/${id}
|
|
446
|
+
path: `/webhooks/${encodeURIComponent(id)}`,
|
|
447
|
+
methodOptions: options
|
|
357
448
|
});
|
|
358
449
|
}
|
|
359
|
-
rotateSecret(id) {
|
|
450
|
+
rotateSecret(id, options) {
|
|
360
451
|
return this.client.request({
|
|
361
452
|
method: "POST",
|
|
362
|
-
path: `/webhooks/${id}/rotate-secret
|
|
453
|
+
path: `/webhooks/${encodeURIComponent(id)}/rotate-secret`,
|
|
454
|
+
methodOptions: options
|
|
363
455
|
});
|
|
364
456
|
}
|
|
365
|
-
test(id) {
|
|
457
|
+
test(id, options) {
|
|
366
458
|
return this.client.request({
|
|
367
459
|
method: "POST",
|
|
368
|
-
path: `/webhooks/${id}/test
|
|
460
|
+
path: `/webhooks/${encodeURIComponent(id)}/test`,
|
|
461
|
+
methodOptions: options
|
|
369
462
|
});
|
|
370
463
|
}
|
|
371
|
-
listDeliveries(id, params) {
|
|
464
|
+
listDeliveries(id, params, options) {
|
|
372
465
|
return this.client.request({
|
|
373
466
|
method: "GET",
|
|
374
|
-
path: `/webhooks/${id}/deliveries`,
|
|
467
|
+
path: `/webhooks/${encodeURIComponent(id)}/deliveries`,
|
|
375
468
|
query: {
|
|
376
469
|
status: params?.status,
|
|
377
470
|
event_type: params?.event_type,
|
|
378
471
|
cursor: params?.cursor,
|
|
379
472
|
limit: params?.limit
|
|
380
|
-
}
|
|
473
|
+
},
|
|
474
|
+
methodOptions: options
|
|
381
475
|
});
|
|
382
476
|
}
|
|
383
477
|
listDeliveriesAutoPaginating(id, params) {
|
|
384
|
-
return new Page(
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
478
|
+
return new Page(
|
|
479
|
+
this.client,
|
|
480
|
+
`/webhooks/${encodeURIComponent(id)}/deliveries`,
|
|
481
|
+
{
|
|
482
|
+
status: params?.status,
|
|
483
|
+
event_type: params?.event_type,
|
|
484
|
+
limit: params?.limit
|
|
485
|
+
}
|
|
486
|
+
);
|
|
389
487
|
}
|
|
390
488
|
};
|
|
391
489
|
|
|
392
490
|
// src/version.ts
|
|
393
|
-
var VERSION = "0.1.
|
|
491
|
+
var VERSION = "0.1.19";
|
|
394
492
|
|
|
395
493
|
// src/client.ts
|
|
396
|
-
var DEFAULT_BASE_URL = "https://
|
|
494
|
+
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
397
495
|
var DEFAULT_MAX_RETRIES = 2;
|
|
398
496
|
var DEFAULT_TIMEOUT = 3e4;
|
|
399
497
|
function isRetryableStatus(status) {
|
|
400
498
|
return status === 429 || status >= 500;
|
|
401
499
|
}
|
|
402
|
-
function calculateBackoff(attempt) {
|
|
500
|
+
function calculateBackoff(attempt, retryAfterMs) {
|
|
501
|
+
if (retryAfterMs !== void 0 && retryAfterMs > 0) {
|
|
502
|
+
return retryAfterMs;
|
|
503
|
+
}
|
|
403
504
|
const base = Math.min(2 ** attempt * 500, 8e3);
|
|
404
505
|
const jitter = Math.random() * base * 0.5;
|
|
405
506
|
return base + jitter;
|
|
@@ -412,6 +513,10 @@ function isApiErrorBody(value) {
|
|
|
412
513
|
return typeof error["type"] === "string" && typeof error["message"] === "string";
|
|
413
514
|
}
|
|
414
515
|
var ShipMailClient = class {
|
|
516
|
+
/**
|
|
517
|
+
* Create a new ShipMail client.
|
|
518
|
+
* @param config - API key string or full configuration object.
|
|
519
|
+
*/
|
|
415
520
|
constructor(config) {
|
|
416
521
|
if (typeof config === "string") {
|
|
417
522
|
this.apiKey = config;
|
|
@@ -419,16 +524,19 @@ var ShipMailClient = class {
|
|
|
419
524
|
this.maxRetries = DEFAULT_MAX_RETRIES;
|
|
420
525
|
this.timeout = DEFAULT_TIMEOUT;
|
|
421
526
|
this.fetchFn = globalThis.fetch;
|
|
527
|
+
this.defaultHeaders = {};
|
|
422
528
|
} else {
|
|
423
529
|
this.apiKey = config.apiKey;
|
|
424
530
|
this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
|
|
425
531
|
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
426
532
|
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
427
533
|
this.fetchFn = config.fetch ?? globalThis.fetch;
|
|
534
|
+
this.defaultHeaders = config.defaultHeaders ? { ...config.defaultHeaders } : {};
|
|
428
535
|
}
|
|
429
536
|
this.domains = new Domains(this);
|
|
430
537
|
this.mailboxes = new Mailboxes(this);
|
|
431
538
|
this.messages = new Messages(this);
|
|
539
|
+
this.suppressions = new Suppressions(this);
|
|
432
540
|
this.threads = new Threads(this);
|
|
433
541
|
this.webhooks = new Webhooks(this);
|
|
434
542
|
this.status = new Status(this);
|
|
@@ -436,18 +544,25 @@ var ShipMailClient = class {
|
|
|
436
544
|
async request(options) {
|
|
437
545
|
const url = this.buildUrl(options.path, options.query);
|
|
438
546
|
let lastError;
|
|
547
|
+
const methodOpts = options.methodOptions;
|
|
439
548
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
440
549
|
if (attempt > 0) {
|
|
441
|
-
const
|
|
550
|
+
const retryAfterMs = lastError instanceof RateLimitError && lastError.retryAfter !== void 0 ? lastError.retryAfter * 1e3 : void 0;
|
|
551
|
+
const delay = calculateBackoff(attempt - 1, retryAfterMs);
|
|
442
552
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
443
553
|
}
|
|
444
554
|
let response;
|
|
445
555
|
try {
|
|
446
556
|
const headers = {
|
|
557
|
+
...this.defaultHeaders,
|
|
447
558
|
Authorization: `Bearer ${this.apiKey}`,
|
|
448
559
|
"User-Agent": `shipmail-node/${VERSION}`,
|
|
449
|
-
Accept: "application/json"
|
|
560
|
+
Accept: "application/json",
|
|
561
|
+
...methodOpts?.headers
|
|
450
562
|
};
|
|
563
|
+
if (methodOpts?.idempotencyKey) {
|
|
564
|
+
headers["Idempotency-Key"] = methodOpts.idempotencyKey;
|
|
565
|
+
}
|
|
451
566
|
let body = null;
|
|
452
567
|
if (options.rawBody !== void 0) {
|
|
453
568
|
headers["Content-Type"] = options.contentType ?? "application/octet-stream";
|
|
@@ -456,11 +571,12 @@ var ShipMailClient = class {
|
|
|
456
571
|
headers["Content-Type"] = "application/json";
|
|
457
572
|
body = JSON.stringify(options.body);
|
|
458
573
|
}
|
|
574
|
+
const effectiveTimeout = methodOpts?.timeout ?? this.timeout;
|
|
459
575
|
response = await this.fetchFn(url, {
|
|
460
576
|
method: options.method,
|
|
461
577
|
headers,
|
|
462
578
|
body,
|
|
463
|
-
signal: AbortSignal.timeout(
|
|
579
|
+
signal: methodOpts?.signal ?? AbortSignal.timeout(effectiveTimeout)
|
|
464
580
|
});
|
|
465
581
|
} catch (err) {
|
|
466
582
|
lastError = new ConnectionError(err instanceof Error ? err.message : "Request failed");
|
|
@@ -509,15 +625,31 @@ var ShipMailClient = class {
|
|
|
509
625
|
// src/types/common.ts
|
|
510
626
|
var WEBHOOK_EVENT_TYPES = [
|
|
511
627
|
"message.received",
|
|
512
|
-
"message.queued",
|
|
513
628
|
"message.sent",
|
|
514
629
|
"message.delivered",
|
|
515
630
|
"message.bounced",
|
|
516
631
|
"message.complained",
|
|
517
632
|
"domain.verified",
|
|
518
633
|
"domain.verification_failed",
|
|
519
|
-
"domain.degraded"
|
|
634
|
+
"domain.degraded",
|
|
635
|
+
"org.reputation_warning",
|
|
636
|
+
"org.sending_throttled",
|
|
637
|
+
"org.sending_suspended",
|
|
638
|
+
"org.reputation_recovered"
|
|
520
639
|
];
|
|
640
|
+
var DOMAIN_STATUSES = ["pending", "verifying", "verified", "degraded", "failed"];
|
|
641
|
+
var MESSAGE_STATUSES = [
|
|
642
|
+
"queued",
|
|
643
|
+
"sent",
|
|
644
|
+
"delivered",
|
|
645
|
+
"bounced",
|
|
646
|
+
"complained",
|
|
647
|
+
"failed"
|
|
648
|
+
];
|
|
649
|
+
var MESSAGE_SOURCES = ["api", "dashboard", "inbound", "smtp"];
|
|
650
|
+
var WEBHOOK_DELIVERY_STATUSES = ["pending", "delivered", "failed"];
|
|
651
|
+
|
|
652
|
+
// src/webhook-verification.ts
|
|
521
653
|
var DEFAULT_TOLERANCE_SECONDS = 300;
|
|
522
654
|
function getHeader(headers, name) {
|
|
523
655
|
if (headers instanceof Headers) {
|
|
@@ -525,12 +657,13 @@ function getHeader(headers, name) {
|
|
|
525
657
|
}
|
|
526
658
|
return headers[name] ?? headers[name.toLowerCase()];
|
|
527
659
|
}
|
|
528
|
-
function signPayload(secret, timestamp, body) {
|
|
660
|
+
async function signPayload(secret, timestamp, body) {
|
|
661
|
+
const { createHmac } = await import('crypto');
|
|
529
662
|
const payload = `v1=${timestamp}
|
|
530
663
|
${body}`;
|
|
531
664
|
return createHmac("sha256", secret).update(payload).digest("hex");
|
|
532
665
|
}
|
|
533
|
-
function verifyWebhook(body, headers, secret, options) {
|
|
666
|
+
async function verifyWebhook(body, headers, secret, options) {
|
|
534
667
|
const signature = getHeader(headers, "x-shipmail-signature");
|
|
535
668
|
const timestampStr = getHeader(headers, "x-shipmail-timestamp");
|
|
536
669
|
if (!signature) {
|
|
@@ -548,7 +681,8 @@ function verifyWebhook(body, headers, secret, options) {
|
|
|
548
681
|
if (Math.abs(now - timestamp) > tolerance) {
|
|
549
682
|
throw new WebhookVerificationError("Webhook timestamp is outside tolerance window");
|
|
550
683
|
}
|
|
551
|
-
const expected = signPayload(secret, timestamp, body);
|
|
684
|
+
const expected = await signPayload(secret, timestamp, body);
|
|
685
|
+
const { timingSafeEqual } = await import('crypto');
|
|
552
686
|
const sigBuffer = Buffer.from(signature, "hex");
|
|
553
687
|
const expectedBuffer = Buffer.from(expected, "hex");
|
|
554
688
|
if (sigBuffer.length !== expectedBuffer.length || !timingSafeEqual(sigBuffer, expectedBuffer)) {
|
|
@@ -563,6 +697,6 @@ function verifyWebhook(body, headers, secret, options) {
|
|
|
563
697
|
return parsed;
|
|
564
698
|
}
|
|
565
699
|
|
|
566
|
-
export { AuthenticationError, AuthorizationError, ConflictError, ConnectionError, InternalServerError, NotFoundError, Page, RateLimitError, ShipMailClient, ShipMailError, ValidationError, WEBHOOK_EVENT_TYPES, WebhookVerificationError, ShipMailClient as default, verifyWebhook };
|
|
700
|
+
export { AuthenticationError, AuthorizationError, ConflictError, ConnectionError, DOMAIN_STATUSES, InternalServerError, MESSAGE_SOURCES, MESSAGE_STATUSES, NotFoundError, Page, QuotaExceededError, RateLimitError, ShipMailClient, ShipMailError, ValidationError, WEBHOOK_DELIVERY_STATUSES, WEBHOOK_EVENT_TYPES, WebhookVerificationError, ShipMailClient as default, verifyWebhook };
|
|
567
701
|
//# sourceMappingURL=index.js.map
|
|
568
702
|
//# sourceMappingURL=index.js.map
|