mailchannels-sdk 1.2.0 → 1.3.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/.agents/skills/mailchannels-js/resources/attachments.md +1 -3
- package/.agents/skills/mailchannels-js/resources/sub-accounts.md +0 -2
- package/.agents/skills/mailchannels-js/resources/suppressions.md +7 -7
- package/README.md +2 -2
- package/dist/_chunks/{simulator.mjs → simulate.mjs} +65 -10
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.mjs +15 -0
- package/dist/mailchannels.d.mts +48 -27
- package/dist/mailchannels.mjs +13 -12
- package/package.json +9 -9
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +0 -50
|
@@ -45,12 +45,11 @@ const attachment = await Attachment.fromBlob(blob, { filename: 'hello.txt' })
|
|
|
45
45
|
|
|
46
46
|
### Inline Images (CID References)
|
|
47
47
|
|
|
48
|
-
Pass
|
|
48
|
+
Pass a `contentId` to embed an image inside the HTML body:
|
|
49
49
|
|
|
50
50
|
```ts
|
|
51
51
|
const logo = Attachment.fromBytes(bytes, {
|
|
52
52
|
filename: 'logo.png',
|
|
53
|
-
disposition: 'inline',
|
|
54
53
|
contentId: 'company-logo'
|
|
55
54
|
})
|
|
56
55
|
|
|
@@ -72,7 +71,6 @@ Both `fromBytes` and `fromBlob` accept an `AttachmentOptions` object:
|
|
|
72
71
|
| `filename` | `string` | Required. MIME type is inferred from it when `type` is omitted. |
|
|
73
72
|
| `type` | `string` | MIME type. Inferred from `filename` if omitted. For `fromBlob`, defaults to the Blob's own `type`. |
|
|
74
73
|
| `contentId` | `string` | For `cid:` inline image references. |
|
|
75
|
-
| `disposition` | `'attachment' \| 'inline'` | Defaults to `'attachment'`. |
|
|
76
74
|
|
|
77
75
|
### Awaiting Attachments Lazily
|
|
78
76
|
|
|
@@ -4,8 +4,6 @@ Sub-accounts are first-class on MailChannels. Use them for tenants, customers, o
|
|
|
4
4
|
senders so that one customer's reputation, limits, and bad traffic don't contaminate the
|
|
5
5
|
parent account or other tenants.
|
|
6
6
|
|
|
7
|
-
> Sub-accounts are only available on parent accounts on the 100K and higher plans.
|
|
8
|
-
|
|
9
7
|
### Handles
|
|
10
8
|
|
|
11
9
|
A handle uniquely identifies a sub-account. Rules:
|
|
@@ -10,8 +10,8 @@ import { MailChannels } from 'mailchannels-sdk'
|
|
|
10
10
|
|
|
11
11
|
const mc = new MailChannels('YOUR-API-KEY')
|
|
12
12
|
|
|
13
|
-
const { success, error } = await mc.suppressions.create(
|
|
14
|
-
|
|
13
|
+
const { success, error } = await mc.suppressions.create(
|
|
14
|
+
[
|
|
15
15
|
{
|
|
16
16
|
recipient: 'out@example.net',
|
|
17
17
|
types: ['non-transactional'], // optional; defaults to non-transactional
|
|
@@ -22,8 +22,8 @@ const { success, error } = await mc.suppressions.create({
|
|
|
22
22
|
types: ['transactional', 'non-transactional']
|
|
23
23
|
}
|
|
24
24
|
],
|
|
25
|
-
addToSubAccounts: true // parent only; copies entries to every sub-account
|
|
26
|
-
|
|
25
|
+
{ addToSubAccounts: true } // parent only; copies entries to every sub-account
|
|
26
|
+
)
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Constraints:
|
|
@@ -83,9 +83,9 @@ that recipient regardless of origin.
|
|
|
83
83
|
|
|
84
84
|
### Patterns
|
|
85
85
|
|
|
86
|
-
- **Preference center opt-out**: set `
|
|
87
|
-
emails, `transactional` for order updates, and so on.
|
|
86
|
+
- **Preference center opt-out**: set `types` according to the email category, e.g. `non-transactional` for marketing
|
|
87
|
+
emails, `transactional` for order updates, and so on.
|
|
88
88
|
Configure `addToSubAccounts` depending on whether the preference applies to all sub-accounts or just the parent account.
|
|
89
89
|
Add a note to indicate the source, e.g. "Opted out via preference center".
|
|
90
|
-
- **Migrating from another ESP**: bulk-create with `addToSubAccounts: true` so every tenant
|
|
90
|
+
- **Migrating from another ESP**: bulk-create with option `addToSubAccounts: true` so every tenant
|
|
91
91
|
inherits the list.
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[![TypeScript][typescript-src]][typescript-href]
|
|
10
10
|
[![Node.js][node-src]][node-href]
|
|
11
11
|
|
|
12
|
-
> Built and tested against Email API `1.
|
|
12
|
+
> Built and tested against Email API `1.6.0`
|
|
13
13
|
|
|
14
14
|
Node.js SDK to integrate [MailChannels Email API](https://docs.mailchannels.com/email-api) into your JavaScript or TypeScript server-side applications.
|
|
15
15
|
|
|
@@ -273,7 +273,7 @@ pnpm test:watch
|
|
|
273
273
|
# Run typecheck
|
|
274
274
|
pnpm test:types
|
|
275
275
|
|
|
276
|
-
# Refresh API parity fixtures
|
|
276
|
+
# Refresh API parity fixtures and README version note
|
|
277
277
|
pnpm parity:fixtures
|
|
278
278
|
|
|
279
279
|
# Run the local simulator
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
2
3
|
import { createServer } from "node:http";
|
|
3
4
|
const SIMULATOR_SIGNING_KEY_ID = "simulator-default";
|
|
4
5
|
const JSON_HEADERS = { "content-type": "application/json" };
|
|
@@ -55,6 +56,7 @@ const createMetricsBuckets = (count) => [{
|
|
|
55
56
|
const createAccountState = (apiKey) => ({
|
|
56
57
|
apiKey,
|
|
57
58
|
customerHandle: createId("customer"),
|
|
59
|
+
limit: { sends: 1e5 },
|
|
58
60
|
customTrackingDomains: [],
|
|
59
61
|
dkimKeysByDomain: /* @__PURE__ */ new Map(),
|
|
60
62
|
messages: [],
|
|
@@ -312,8 +314,8 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
312
314
|
}
|
|
313
315
|
targetKey.status = "rotated";
|
|
314
316
|
targetKey.status_modified_at = currentTimestamp();
|
|
315
|
-
targetKey.gracePeriodExpiresAt = new Date(Date.now() +
|
|
316
|
-
targetKey.retiresAt = new Date(Date.now() +
|
|
317
|
+
targetKey.gracePeriodExpiresAt = new Date(Date.now() + 6048e5).toISOString();
|
|
318
|
+
targetKey.retiresAt = new Date(Date.now() + 2592e6).toISOString();
|
|
317
319
|
const newKey = createDkimKey(domain, body?.new_key?.selector || createId("selector"));
|
|
318
320
|
account.dkimKeysByDomain.set(domain, [...keys, newKey]);
|
|
319
321
|
sendJson(response, 201, {
|
|
@@ -600,10 +602,13 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
600
602
|
return;
|
|
601
603
|
}
|
|
602
604
|
if (suffix === "usage" && method === "GET") {
|
|
605
|
+
const subLimitSends = subAccount.limit?.sends ?? -1;
|
|
606
|
+
const monthlyLimit = subLimitSends === -1 ? account.limit.sends : subLimitSends;
|
|
603
607
|
sendJson(response, 200, {
|
|
604
608
|
period_end_date: currentTimestamp(),
|
|
605
609
|
period_start_date: new Date((/* @__PURE__ */ new Date()).setDate(1)).toISOString(),
|
|
606
|
-
total_usage: subAccount.usage
|
|
610
|
+
total_usage: subAccount.usage,
|
|
611
|
+
monthly_limit: monthlyLimit
|
|
607
612
|
});
|
|
608
613
|
return;
|
|
609
614
|
}
|
|
@@ -623,7 +628,7 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
623
628
|
end_time: url.searchParams.get("end_time") || currentTimestamp(),
|
|
624
629
|
open: summary.open,
|
|
625
630
|
open_tracking_delivered: summary.openTrackingDelivered,
|
|
626
|
-
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() -
|
|
631
|
+
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() - 2592e6)).toISOString()
|
|
627
632
|
});
|
|
628
633
|
return;
|
|
629
634
|
}
|
|
@@ -642,7 +647,7 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
642
647
|
delivered: summary.delivered,
|
|
643
648
|
end_time: url.searchParams.get("end_time") || currentTimestamp(),
|
|
644
649
|
processed: summary.processed,
|
|
645
|
-
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() -
|
|
650
|
+
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() - 2592e6)).toISOString()
|
|
646
651
|
});
|
|
647
652
|
return;
|
|
648
653
|
}
|
|
@@ -655,7 +660,7 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
655
660
|
unsubscribed: createMetricsBuckets(summary.unsubscribed)
|
|
656
661
|
},
|
|
657
662
|
end_time: url.searchParams.get("end_time") || currentTimestamp(),
|
|
658
|
-
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() -
|
|
663
|
+
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() - 2592e6)).toISOString(),
|
|
659
664
|
unsubscribe_delivered: summary.unsubscribeDelivered,
|
|
660
665
|
unsubscribed: summary.unsubscribed
|
|
661
666
|
});
|
|
@@ -674,7 +679,7 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
674
679
|
dropped: summary.dropped,
|
|
675
680
|
end_time: url.searchParams.get("end_time") || currentTimestamp(),
|
|
676
681
|
processed: summary.processed,
|
|
677
|
-
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() -
|
|
682
|
+
start_time: url.searchParams.get("start_time") || (/* @__PURE__ */ new Date(Date.now() - 2592e6)).toISOString()
|
|
678
683
|
});
|
|
679
684
|
return;
|
|
680
685
|
}
|
|
@@ -714,16 +719,27 @@ const createEmailApiHandler = ({ logRequests = true } = {}) => {
|
|
|
714
719
|
limit,
|
|
715
720
|
offset,
|
|
716
721
|
senders: senders.slice(offset, offset + limit),
|
|
717
|
-
start_time: (/* @__PURE__ */ new Date(Date.now() -
|
|
722
|
+
start_time: (/* @__PURE__ */ new Date(Date.now() - 2592e6)).toISOString(),
|
|
718
723
|
total: senders.length
|
|
719
724
|
});
|
|
720
725
|
return;
|
|
721
726
|
}
|
|
722
727
|
if (url.pathname === "/tx/v1/usage" && method === "GET") {
|
|
728
|
+
let totalUsage = account.messages.length;
|
|
729
|
+
let monthlyLimit = account.limit.sends;
|
|
730
|
+
if (scopeHandle) {
|
|
731
|
+
const subAccount = account.subAccounts.get(scopeHandle);
|
|
732
|
+
if (subAccount) {
|
|
733
|
+
totalUsage = subAccount.usage;
|
|
734
|
+
const subLimitSends = subAccount.limit?.sends ?? -1;
|
|
735
|
+
monthlyLimit = subLimitSends === -1 ? account.limit.sends : subLimitSends;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
723
738
|
sendJson(response, 200, {
|
|
724
739
|
period_end_date: currentTimestamp(),
|
|
725
740
|
period_start_date: new Date((/* @__PURE__ */ new Date()).setDate(1)).toISOString(),
|
|
726
|
-
total_usage:
|
|
741
|
+
total_usage: totalUsage,
|
|
742
|
+
monthly_limit: monthlyLimit
|
|
727
743
|
});
|
|
728
744
|
return;
|
|
729
745
|
}
|
|
@@ -781,6 +797,10 @@ const DEFAULT_HOST = "127.0.0.1";
|
|
|
781
797
|
const DEFAULT_PORT = 8787;
|
|
782
798
|
const createSimulator = (options = {}) => {
|
|
783
799
|
const { host = DEFAULT_HOST, port = DEFAULT_PORT } = options;
|
|
800
|
+
if (port !== void 0 && (isNaN(port) || port < 0 || port > 65535)) {
|
|
801
|
+
console.error("[Simulator]", `Invalid port '${port}': must be an integer between 0 and 65535.`);
|
|
802
|
+
process.exit(1);
|
|
803
|
+
}
|
|
784
804
|
const logRequests = !options.silent;
|
|
785
805
|
const emailApi = createEmailApiHandler({ logRequests });
|
|
786
806
|
const server = createServer(async (request, response) => {
|
|
@@ -828,4 +848,39 @@ const createSimulator = (options = {}) => {
|
|
|
828
848
|
}
|
|
829
849
|
};
|
|
830
850
|
};
|
|
831
|
-
|
|
851
|
+
var simulate_default = async (args) => {
|
|
852
|
+
const { MAILCHANNELS_SIMULATOR_PORT, MAILCHANNELS_SIMULATOR_HOST } = process.env;
|
|
853
|
+
const { values } = parseArgs({
|
|
854
|
+
args,
|
|
855
|
+
options: {
|
|
856
|
+
port: {
|
|
857
|
+
type: "string",
|
|
858
|
+
short: "p",
|
|
859
|
+
default: MAILCHANNELS_SIMULATOR_PORT
|
|
860
|
+
},
|
|
861
|
+
host: {
|
|
862
|
+
type: "string",
|
|
863
|
+
short: "h",
|
|
864
|
+
default: MAILCHANNELS_SIMULATOR_HOST
|
|
865
|
+
},
|
|
866
|
+
silent: {
|
|
867
|
+
type: "boolean",
|
|
868
|
+
short: "s",
|
|
869
|
+
default: false
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
const simulator = createSimulator({
|
|
874
|
+
host: values.host,
|
|
875
|
+
port: values.port !== void 0 ? Number.parseInt(values.port, 10) : void 0,
|
|
876
|
+
silent: values.silent
|
|
877
|
+
});
|
|
878
|
+
await simulator.listen();
|
|
879
|
+
const shutdown = async () => {
|
|
880
|
+
await simulator.close();
|
|
881
|
+
process.exit(0);
|
|
882
|
+
};
|
|
883
|
+
process.on("SIGINT", shutdown);
|
|
884
|
+
process.on("SIGTERM", shutdown);
|
|
885
|
+
};
|
|
886
|
+
export { simulate_default as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const LOGGER_NAME = "[MailChannels-CLI]";
|
|
3
|
+
console.info = console.info.bind(console.info, LOGGER_NAME);
|
|
4
|
+
console.error = console.error.bind(console.error, LOGGER_NAME);
|
|
5
|
+
const [command, ...args] = process.argv.slice(2);
|
|
6
|
+
switch (command) {
|
|
7
|
+
case "simulate":
|
|
8
|
+
const { default: simulate } = await import("../_chunks/simulate.mjs");
|
|
9
|
+
await simulate(args);
|
|
10
|
+
break;
|
|
11
|
+
default:
|
|
12
|
+
console.error(`Unknown command: ${command}`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
export {};
|
package/dist/mailchannels.d.mts
CHANGED
|
@@ -121,13 +121,11 @@ interface EmailsSendAttachment {
|
|
|
121
121
|
*/
|
|
122
122
|
type?: string;
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
124
|
+
* A unique identifier for this attachment.
|
|
125
|
+
*
|
|
126
|
+
* When set, the attachment is embedded inline in the message body (`Content-Disposition: inline`) instead of offered as a downloadable attachment, and can be referenced from HTML content via a `cid:` URI, e.g. `<img src="cid:logo123">` refers to an attachment with content_id: `logo123`. (RFC 2392). Must be unique across all attachments in the request. Max length is 255 characters.
|
|
125
127
|
*/
|
|
126
128
|
contentId?: string;
|
|
127
|
-
/**
|
|
128
|
-
* The `Content-Disposition` header value for the attachment.
|
|
129
|
-
*/
|
|
130
|
-
disposition?: "attachment" | "inline";
|
|
131
129
|
}
|
|
132
130
|
interface EmailsSendTracking {
|
|
133
131
|
/**
|
|
@@ -193,7 +191,7 @@ interface EmailsSendContent {
|
|
|
193
191
|
*/
|
|
194
192
|
value: string;
|
|
195
193
|
}
|
|
196
|
-
type EmailsSendRecipientInput = EmailsSendRecipient
|
|
194
|
+
type EmailsSendRecipientInput = EmailsSendRecipient | string | (EmailsSendRecipient | string)[];
|
|
197
195
|
interface EmailsSendDkim {
|
|
198
196
|
/**
|
|
199
197
|
* Domain used for DKIM signing.
|
|
@@ -1440,8 +1438,15 @@ interface SubAccountsUsage {
|
|
|
1440
1438
|
startDate?: string;
|
|
1441
1439
|
/**
|
|
1442
1440
|
* The total usage for the current billing period.
|
|
1441
|
+
* @example 5000
|
|
1443
1442
|
*/
|
|
1444
1443
|
total: number;
|
|
1444
|
+
/**
|
|
1445
|
+
* The effective monthly limit for the current billing period. A limit of zero means the account cannot send any messages.
|
|
1446
|
+
* For sub-accounts with no explicit limit set (i.e., -1), the monthly limit for the parent account is returned.
|
|
1447
|
+
* @example 10000
|
|
1448
|
+
*/
|
|
1449
|
+
monthlyLimit: number;
|
|
1445
1450
|
}
|
|
1446
1451
|
type SubAccountsUsageResponse = DataResponse<SubAccountsUsage>;
|
|
1447
1452
|
interface MetricsEngagement {
|
|
@@ -1612,8 +1617,15 @@ type MetricsUsageResponse = DataResponse<{
|
|
|
1612
1617
|
startDate?: string;
|
|
1613
1618
|
/**
|
|
1614
1619
|
* The total usage for the current billing period.
|
|
1620
|
+
* @example 5000
|
|
1615
1621
|
*/
|
|
1616
1622
|
total: number;
|
|
1623
|
+
/**
|
|
1624
|
+
* The effective monthly limit for the current billing period. A limit of zero means the account cannot send any messages.
|
|
1625
|
+
* For sub-accounts with no explicit limit set (i.e., -1), the monthly limit for the parent account is returned.
|
|
1626
|
+
* @example 10000
|
|
1627
|
+
*/
|
|
1628
|
+
monthlyLimit: number;
|
|
1617
1629
|
}>;
|
|
1618
1630
|
type MetricsSendersType = "sub-accounts" | "campaigns";
|
|
1619
1631
|
interface MetricsSendersOptions {
|
|
@@ -1696,6 +1708,21 @@ interface MetricsOptions {
|
|
|
1696
1708
|
interval?: "hour" | "day" | "week" | "month";
|
|
1697
1709
|
}
|
|
1698
1710
|
type SuppressionsTypes = "transactional" | "non-transactional";
|
|
1711
|
+
interface SuppressionsCreateEntry {
|
|
1712
|
+
/**
|
|
1713
|
+
* Must be less than `1024` characters.
|
|
1714
|
+
*/
|
|
1715
|
+
notes?: string;
|
|
1716
|
+
/**
|
|
1717
|
+
* The email address to suppress. Must be a valid email address format and less than `255` characters.
|
|
1718
|
+
*/
|
|
1719
|
+
recipient: string;
|
|
1720
|
+
/**
|
|
1721
|
+
* An array of types of suppression to apply to the recipient.
|
|
1722
|
+
* @default ["non-transactional"]
|
|
1723
|
+
*/
|
|
1724
|
+
types?: SuppressionsTypes[];
|
|
1725
|
+
}
|
|
1699
1726
|
interface SuppressionsCreateOptions {
|
|
1700
1727
|
/**
|
|
1701
1728
|
* If true, the parent account creates suppression entries for all associated sub-accounts. This field is only applicable to parent accounts. Sub-accounts cannot create entries for other sub-accounts.
|
|
@@ -1704,22 +1731,9 @@ interface SuppressionsCreateOptions {
|
|
|
1704
1731
|
addToSubAccounts?: boolean;
|
|
1705
1732
|
/**
|
|
1706
1733
|
* The total number of suppression entries to create, for the parent and/or its sub-accounts, must not exceed `1000`.
|
|
1734
|
+
* @deprecated Use `create(entries, options?)` instead.
|
|
1707
1735
|
*/
|
|
1708
|
-
entries:
|
|
1709
|
-
/**
|
|
1710
|
-
* Must be less than `1024` characters.
|
|
1711
|
-
*/
|
|
1712
|
-
notes?: string;
|
|
1713
|
-
/**
|
|
1714
|
-
* The email address to suppress. Must be a valid email address format and less than `255` characters.
|
|
1715
|
-
*/
|
|
1716
|
-
recipient: string;
|
|
1717
|
-
/**
|
|
1718
|
-
* An array of types of suppression to apply to the recipient.
|
|
1719
|
-
* @default ["non-transactional"]
|
|
1720
|
-
*/
|
|
1721
|
-
types?: SuppressionsTypes[];
|
|
1722
|
-
}[];
|
|
1736
|
+
entries: SuppressionsCreateEntry[];
|
|
1723
1737
|
}
|
|
1724
1738
|
type SuppressionsSource = "api" | "unsubscribe_link" | "list_unsubscribe" | "hard_bounce" | "spam_complaint" | "all";
|
|
1725
1739
|
interface SuppressionsListOptions {
|
|
@@ -1877,7 +1891,7 @@ declare class SubAccounts {
|
|
|
1877
1891
|
readonly limits: SubAccountsLimits;
|
|
1878
1892
|
constructor(mailchannels: MailChannelsClient);
|
|
1879
1893
|
/**
|
|
1880
|
-
* Creates a new sub-account under the parent account. Each sub-account must have a unique handle composed solely of lowercase alphanumeric characters. If no handle is provided, a random handle will be generated.
|
|
1894
|
+
* Creates a new sub-account under the parent account. Each sub-account must have a unique handle composed solely of lowercase alphanumeric characters. If no handle is provided, a random handle will be generated.
|
|
1881
1895
|
* @param companyName - The name of the company associated with the sub-account. This name is used for display purposes only and does not affect the functionality of the sub-account. The length must be between 3 and 128 characters.
|
|
1882
1896
|
* @param handle - A unique name for the sub-account to be created. The length must be between 3 and 128 characters, and it may contain only lowercase letters and numbers. If not provided, a random handle will be generated.
|
|
1883
1897
|
* @example
|
|
@@ -2025,14 +2039,21 @@ declare class Suppressions {
|
|
|
2025
2039
|
constructor(mailchannels: MailChannelsClient);
|
|
2026
2040
|
/**
|
|
2027
2041
|
* Creates suppression entries for the specified account. Parent accounts can create suppression entries for all associated sub-accounts. If `types` is not provided, it defaults to `non-transactional`. The operation is atomic, meaning all entries are successfully added or none are added if an error occurs.
|
|
2028
|
-
* @param
|
|
2042
|
+
* @param entries - The total number of suppression entries to create, for the parent and/or its sub-accounts, must not exceed `1000`.
|
|
2043
|
+
* @param options - The options of the suppression entries to create.
|
|
2029
2044
|
* @example
|
|
2030
2045
|
* ```ts
|
|
2031
2046
|
* const mailchannels = new MailChannels('your-api-key')
|
|
2032
|
-
* const { success, error } = await mailchannels.suppressions.create(
|
|
2033
|
-
*
|
|
2034
|
-
*
|
|
2047
|
+
* const { success, error } = await mailchannels.suppressions.create([
|
|
2048
|
+
* {
|
|
2049
|
+
* notes: "test",
|
|
2050
|
+
* recipient: "name@example.com",
|
|
2051
|
+
* types: ["transactional"]
|
|
2052
|
+
* }
|
|
2053
|
+
* ], { addToSubAccounts: false });
|
|
2035
2054
|
*/
|
|
2055
|
+
create(entries: SuppressionsCreateEntry[], options?: Omit<SuppressionsCreateOptions, "entries">): Promise<SuccessResponse>;
|
|
2056
|
+
/** @deprecated Use positional params `create(entries, options?)` instead. */
|
|
2036
2057
|
create(options: SuppressionsCreateOptions): Promise<SuccessResponse>;
|
|
2037
2058
|
/**
|
|
2038
2059
|
* Deletes suppression entry associated with the account based on the specified recipient and source.
|
|
@@ -2070,4 +2091,4 @@ declare class MailChannels extends MailChannelsClient {
|
|
|
2070
2091
|
readonly suppressions: Suppressions;
|
|
2071
2092
|
constructor(key: string, options?: MailChannelsClientOptions);
|
|
2072
2093
|
}
|
|
2073
|
-
export { Attachment, type DataResponse, Domains, type DomainsCheckOptions, type DomainsCheckResponse, type DomainsCheckVerdict, type DomainsCustomTrackingCreateResponse, type DomainsCustomTrackingDnsSetupRequired, type DomainsCustomTrackingDomain, type DomainsCustomTrackingListOptions, type DomainsCustomTrackingListResponse, type DomainsCustomTrackingScope, type DomainsCustomTrackingUpdateOptions, type DomainsCustomTrackingUpdateResponse, type DomainsCustomTrackingWithDnsSetupRequired, type DomainsDkimCreateOptions, type DomainsDkimCreateResponse, type DomainsDkimKey, type DomainsDkimKeyStatus, type DomainsDkimListOptions, type DomainsDkimListResponse, type DomainsDkimRotateOptions, type DomainsDkimRotateResponse, type DomainsDkimUpdateStatusOptions, Emails, type EmailsQueueResponse, type EmailsSendAsyncResponse, type EmailsSendAttachment, type EmailsSendContent, type EmailsSendDkim, type EmailsSendOptions, type EmailsSendPersonalization, type EmailsSendRecipient, type EmailsSendRecipientInput, type EmailsSendResponse, type EmailsSendTemplate, type EmailsSendTemplateType, type EmailsSendTemplateValue, type EmailsSendTracking, type ErrorResponse, type ErrorType, MailChannels, MailChannelsClient, type MailChannelsClientOptions, Metrics, type MetricsBucket, type MetricsEngagement, type MetricsEngagementResponse, type MetricsOptions, type MetricsPerformance, type MetricsPerformanceResponse, type MetricsRecipientBehaviour, type MetricsRecipientBehaviourResponse, type MetricsSenders, type MetricsSendersOptions, type MetricsSendersResponse, type MetricsSendersType, type MetricsUsageResponse, type MetricsVolume, type MetricsVolumeResponse, type SubAccount, SubAccounts, type SubAccountsAccount, type SubAccountsApiKey, type SubAccountsApiKeysCreateResponse, type SubAccountsApiKeysListOptions, type SubAccountsApiKeysListResponse, type SubAccountsCreateApiKeyResponse, type SubAccountsCreateResponse, type SubAccountsCreateSmtpPasswordResponse, type SubAccountsLimit, type SubAccountsLimitResponse, type SubAccountsLimitsGetResponse, type SubAccountsLimitsSetOptions, type SubAccountsListApiKeyOptions, type SubAccountsListApiKeyResponse, type SubAccountsListOptions, type SubAccountsListResponse, type SubAccountsListSmtpPasswordResponse, type SubAccountsSmtpPassword, type SubAccountsSmtpPasswordsCreateResponse, type SubAccountsSmtpPasswordsListResponse, type SubAccountsUsage, type SubAccountsUsageResponse, type SuccessResponse, Suppressions, type SuppressionsCreateOptions, type SuppressionsListEntry, type SuppressionsListOptions, type SuppressionsListResponse, type SuppressionsSource, type SuppressionsTypes, type WebhookEvent, type WebhookEventClick, type WebhookEventComplained, type WebhookEventDelivered, type WebhookEventDropped, type WebhookEventHardBounced, type WebhookEventOpen, type WebhookEventProcessed, type WebhookEventSoftBounced, type WebhookEventTest, type WebhookEventType, type WebhookEventUnsubscribed, Webhooks, type WebhooksBatch, type WebhooksBatchResponseStatus, type WebhooksBatchStatus, type WebhooksBatchesOptions, type WebhooksBatchesResponse, type WebhooksListResponse, type WebhooksResendBatch, type WebhooksResendBatchResponse, type WebhooksSigningKeyResponse, type WebhooksValidateResponse, type WebhooksVerifyOptions, type WebhooksVerifyResponse };
|
|
2094
|
+
export { Attachment, type DataResponse, Domains, type DomainsCheckOptions, type DomainsCheckResponse, type DomainsCheckVerdict, type DomainsCustomTrackingCreateResponse, type DomainsCustomTrackingDnsSetupRequired, type DomainsCustomTrackingDomain, type DomainsCustomTrackingListOptions, type DomainsCustomTrackingListResponse, type DomainsCustomTrackingScope, type DomainsCustomTrackingUpdateOptions, type DomainsCustomTrackingUpdateResponse, type DomainsCustomTrackingWithDnsSetupRequired, type DomainsDkimCreateOptions, type DomainsDkimCreateResponse, type DomainsDkimKey, type DomainsDkimKeyStatus, type DomainsDkimListOptions, type DomainsDkimListResponse, type DomainsDkimRotateOptions, type DomainsDkimRotateResponse, type DomainsDkimUpdateStatusOptions, Emails, type EmailsQueueResponse, type EmailsSendAsyncResponse, type EmailsSendAttachment, type EmailsSendContent, type EmailsSendDkim, type EmailsSendOptions, type EmailsSendPersonalization, type EmailsSendRecipient, type EmailsSendRecipientInput, type EmailsSendResponse, type EmailsSendTemplate, type EmailsSendTemplateType, type EmailsSendTemplateValue, type EmailsSendTracking, type ErrorResponse, type ErrorType, MailChannels, MailChannelsClient, type MailChannelsClientOptions, Metrics, type MetricsBucket, type MetricsEngagement, type MetricsEngagementResponse, type MetricsOptions, type MetricsPerformance, type MetricsPerformanceResponse, type MetricsRecipientBehaviour, type MetricsRecipientBehaviourResponse, type MetricsSenders, type MetricsSendersOptions, type MetricsSendersResponse, type MetricsSendersType, type MetricsUsageResponse, type MetricsVolume, type MetricsVolumeResponse, type SubAccount, SubAccounts, type SubAccountsAccount, type SubAccountsApiKey, type SubAccountsApiKeysCreateResponse, type SubAccountsApiKeysListOptions, type SubAccountsApiKeysListResponse, type SubAccountsCreateApiKeyResponse, type SubAccountsCreateResponse, type SubAccountsCreateSmtpPasswordResponse, type SubAccountsLimit, type SubAccountsLimitResponse, type SubAccountsLimitsGetResponse, type SubAccountsLimitsSetOptions, type SubAccountsListApiKeyOptions, type SubAccountsListApiKeyResponse, type SubAccountsListOptions, type SubAccountsListResponse, type SubAccountsListSmtpPasswordResponse, type SubAccountsSmtpPassword, type SubAccountsSmtpPasswordsCreateResponse, type SubAccountsSmtpPasswordsListResponse, type SubAccountsUsage, type SubAccountsUsageResponse, type SuccessResponse, Suppressions, type SuppressionsCreateEntry, type SuppressionsCreateOptions, type SuppressionsListEntry, type SuppressionsListOptions, type SuppressionsListResponse, type SuppressionsSource, type SuppressionsTypes, type WebhookEvent, type WebhookEventClick, type WebhookEventComplained, type WebhookEventDelivered, type WebhookEventDropped, type WebhookEventHardBounced, type WebhookEventOpen, type WebhookEventProcessed, type WebhookEventSoftBounced, type WebhookEventTest, type WebhookEventType, type WebhookEventUnsubscribed, Webhooks, type WebhooksBatch, type WebhooksBatchResponseStatus, type WebhooksBatchStatus, type WebhooksBatchesOptions, type WebhooksBatchesResponse, type WebhooksListResponse, type WebhooksResendBatch, type WebhooksResendBatchResponse, type WebhooksSigningKeyResponse, type WebhooksValidateResponse, type WebhooksVerifyOptions, type WebhooksVerifyResponse };
|
package/dist/mailchannels.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { $fetch } from "ofetch";
|
|
|
2
2
|
import { subtle } from "node:crypto";
|
|
3
3
|
import { Buffer } from "node:buffer";
|
|
4
4
|
import mime from "mime";
|
|
5
|
-
var version = "1.
|
|
5
|
+
var version = "1.3.1";
|
|
6
6
|
var MailChannelsClient = class MailChannelsClient {
|
|
7
7
|
static DEFAULT_BASE_URL = "https://api.mailchannels.net";
|
|
8
8
|
static DEFAULT_TIMEOUT = 12e4;
|
|
@@ -225,8 +225,7 @@ const mapAttachment = (attachment) => ({
|
|
|
225
225
|
content: attachment.content,
|
|
226
226
|
filename: attachment.filename,
|
|
227
227
|
type: attachment.type,
|
|
228
|
-
content_id: attachment.contentId
|
|
229
|
-
disposition: attachment.disposition
|
|
228
|
+
content_id: attachment.contentId
|
|
230
229
|
});
|
|
231
230
|
const mapPersonalization = (personalization, index, rootTemplateData) => {
|
|
232
231
|
const to = parseArrayRecipients(personalization.to);
|
|
@@ -1239,7 +1238,7 @@ var Webhooks = class Webhooks {
|
|
|
1239
1238
|
if (dates.createdAfter && dates.createdBefore) {
|
|
1240
1239
|
const createdAfter = Date.parse(dates.createdAfter);
|
|
1241
1240
|
const createdBefore = Date.parse(dates.createdBefore);
|
|
1242
|
-
const maxRangeMs =
|
|
1241
|
+
const maxRangeMs = 26784e5;
|
|
1243
1242
|
if (createdBefore <= createdAfter) return {
|
|
1244
1243
|
data: null,
|
|
1245
1244
|
error: createValidationError("createdBefore must be later than createdAfter.")
|
|
@@ -1743,7 +1742,8 @@ var SubAccounts = class SubAccounts {
|
|
|
1743
1742
|
data: clean({
|
|
1744
1743
|
endDate: response.period_end_date,
|
|
1745
1744
|
startDate: response.period_start_date,
|
|
1746
|
-
total: response.total_usage
|
|
1745
|
+
total: response.total_usage,
|
|
1746
|
+
monthlyLimit: response.monthly_limit
|
|
1747
1747
|
}),
|
|
1748
1748
|
error: null
|
|
1749
1749
|
};
|
|
@@ -1989,7 +1989,8 @@ var Metrics = class {
|
|
|
1989
1989
|
data: clean({
|
|
1990
1990
|
endDate: response.period_end_date,
|
|
1991
1991
|
startDate: response.period_start_date,
|
|
1992
|
-
total: response.total_usage
|
|
1992
|
+
total: response.total_usage,
|
|
1993
|
+
monthlyLimit: response.monthly_limit
|
|
1993
1994
|
}),
|
|
1994
1995
|
error: null
|
|
1995
1996
|
};
|
|
@@ -2049,9 +2050,10 @@ var Suppressions = class {
|
|
|
2049
2050
|
constructor(mailchannels) {
|
|
2050
2051
|
this.mailchannels = mailchannels;
|
|
2051
2052
|
}
|
|
2052
|
-
async create(options) {
|
|
2053
|
+
async create(entriesOrOptions, options) {
|
|
2053
2054
|
let error = null;
|
|
2054
|
-
const
|
|
2055
|
+
const entries = Array.isArray(entriesOrOptions) ? entriesOrOptions : entriesOrOptions.entries;
|
|
2056
|
+
const createOptions = Array.isArray(entriesOrOptions) ? options : entriesOrOptions;
|
|
2055
2057
|
if (entries.length > 1e3) {
|
|
2056
2058
|
error = createValidationError("The number of suppression entries must not exceed 1000.");
|
|
2057
2059
|
return {
|
|
@@ -2060,7 +2062,7 @@ var Suppressions = class {
|
|
|
2060
2062
|
};
|
|
2061
2063
|
}
|
|
2062
2064
|
const payload = {
|
|
2063
|
-
add_to_sub_accounts: addToSubAccounts,
|
|
2065
|
+
add_to_sub_accounts: createOptions?.addToSubAccounts,
|
|
2064
2066
|
suppression_entries: entries.map((entry) => ({
|
|
2065
2067
|
notes: entry.notes,
|
|
2066
2068
|
recipient: entry.recipient,
|
|
@@ -2167,13 +2169,12 @@ const guessContentType = (filename) => {
|
|
|
2167
2169
|
};
|
|
2168
2170
|
var Attachment = class Attachment {
|
|
2169
2171
|
static fromBytes(data, options) {
|
|
2170
|
-
const { filename, type, contentId
|
|
2172
|
+
const { filename, type, contentId } = options;
|
|
2171
2173
|
return {
|
|
2172
2174
|
content: base64Content(data),
|
|
2173
2175
|
filename: decodeURIComponent(filename) || "attachment",
|
|
2174
2176
|
type: type || guessContentType(filename),
|
|
2175
|
-
contentId
|
|
2176
|
-
disposition
|
|
2177
|
+
contentId
|
|
2177
2178
|
};
|
|
2178
2179
|
}
|
|
2179
2180
|
static async fromBlob(blob, options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailchannels-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Node.js SDK to integrate MailChannels Email API into your JavaScript or TypeScript server-side applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"types": "./dist/mailchannels.d.mts",
|
|
31
31
|
"bin": {
|
|
32
|
-
"mailchannels-sdk": "./dist/cli.mjs",
|
|
33
|
-
"mailchannels": "./dist/cli.mjs"
|
|
32
|
+
"mailchannels-sdk": "./dist/cli/index.mjs",
|
|
33
|
+
"mailchannels": "./dist/cli/index.mjs"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"dist",
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
45
45
|
"@types/markdown-it": "^14.1.2",
|
|
46
|
-
"@types/node": "^26.1.
|
|
46
|
+
"@types/node": "^26.1.2",
|
|
47
47
|
"@vitest/coverage-v8": "^4.1.10",
|
|
48
48
|
"changelogen": "^0.6.2",
|
|
49
|
-
"obuild": "^0.4.
|
|
50
|
-
"oxlint": "^1.
|
|
49
|
+
"obuild": "^0.4.38",
|
|
50
|
+
"oxlint": "^1.76.0",
|
|
51
51
|
"scule": "^1.3.0",
|
|
52
52
|
"typescript": "^6.0.3",
|
|
53
53
|
"vitepress": "^2.0.0-alpha.18",
|
|
54
|
-
"vitepress-plugin-group-icons": "^1.7.
|
|
55
|
-
"vitepress-plugin-llms": "^1.13.
|
|
54
|
+
"vitepress-plugin-group-icons": "^1.7.6",
|
|
55
|
+
"vitepress-plugin-llms": "^1.13.4",
|
|
56
56
|
"vitest": "^4.1.10"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"build": "obuild",
|
|
63
63
|
"parity:fixtures": "node scripts/generate-parity-fixtures.ts",
|
|
64
64
|
"release": "pnpm lint && pnpm test && pnpm build && changelogen --bump",
|
|
65
|
-
"simulate": "node src/cli.ts simulate",
|
|
65
|
+
"simulate": "node src/cli/index.ts simulate",
|
|
66
66
|
"lint": "oxlint",
|
|
67
67
|
"lint:fix": "oxlint --fix",
|
|
68
68
|
"test": "vitest run --reporter=verbose --coverage",
|
package/dist/cli.d.mts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
package/dist/cli.mjs
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { parseArgs } from "node:util";
|
|
3
|
-
const LOGGER_NAME = "[MailChannels-CLI]";
|
|
4
|
-
console.info = console.info.bind(console.info, LOGGER_NAME);
|
|
5
|
-
console.error = console.error.bind(console.error, LOGGER_NAME);
|
|
6
|
-
const [command, ...args] = process.argv.slice(2);
|
|
7
|
-
switch (command) {
|
|
8
|
-
case "simulate":
|
|
9
|
-
const { createSimulator } = await import("./_chunks/simulator.mjs");
|
|
10
|
-
const { MAILCHANNELS_SIMULATOR_PORT, MAILCHANNELS_SIMULATOR_HOST } = process.env;
|
|
11
|
-
const { values } = parseArgs({
|
|
12
|
-
args,
|
|
13
|
-
options: {
|
|
14
|
-
port: {
|
|
15
|
-
type: "string",
|
|
16
|
-
short: "p",
|
|
17
|
-
default: MAILCHANNELS_SIMULATOR_PORT
|
|
18
|
-
},
|
|
19
|
-
host: {
|
|
20
|
-
type: "string",
|
|
21
|
-
short: "h",
|
|
22
|
-
default: MAILCHANNELS_SIMULATOR_HOST
|
|
23
|
-
},
|
|
24
|
-
silent: {
|
|
25
|
-
type: "boolean",
|
|
26
|
-
short: "s",
|
|
27
|
-
default: false
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
const port = values.port !== void 0 ? Number.parseInt(values.port, 10) : void 0;
|
|
32
|
-
if (port !== void 0 && (isNaN(port) || port < 0 || port > 65535)) {
|
|
33
|
-
console.error("[Simulator]", `Invalid port "${values.port}": must be an integer between 0 and 65535.`);
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
const simulator = createSimulator({
|
|
37
|
-
host: values.host,
|
|
38
|
-
port,
|
|
39
|
-
silent: values.silent
|
|
40
|
-
});
|
|
41
|
-
await simulator.listen();
|
|
42
|
-
const shutdown = async () => {
|
|
43
|
-
await simulator.close();
|
|
44
|
-
process.exit(0);
|
|
45
|
-
};
|
|
46
|
-
process.on("SIGINT", shutdown);
|
|
47
|
-
process.on("SIGTERM", shutdown);
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
export {};
|