mailchannels-sdk 1.5.1 → 1.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.
@@ -3,7 +3,7 @@ import { subtle } from "node:crypto";
3
3
  import { Buffer } from "node:buffer";
4
4
  import mime from "mime";
5
5
  var name = "mailchannels-sdk";
6
- var version = "1.5.1";
6
+ var version = "1.5.2";
7
7
  var MailChannelsClient = class MailChannelsClient {
8
8
  static DEFAULT_BASE_URL = "https://api.mailchannels.net";
9
9
  static DEFAULT_TIMEOUT = 12e4;
@@ -80,6 +80,10 @@ const STATUS_ERROR_TYPE_MAP = {
80
80
  [429]: "rate_limit_error",
81
81
  [500]: "internal_server_error"
82
82
  };
83
+ const STATUS_DEFAULT_TEXT_MAP = {
84
+ [400]: "Bad request.",
85
+ [401]: "Invalid API key."
86
+ };
83
87
  const createError = (message, statusCode = null, type, response = null) => {
84
88
  return {
85
89
  message,
@@ -89,11 +93,12 @@ const createError = (message, statusCode = null, type, response = null) => {
89
93
  };
90
94
  };
91
95
  const getStatusError = (response, errors = {}) => {
92
- const statusText = errors[response.status] || "Unknown error.";
96
+ const statusText = errors[response.status] || STATUS_DEFAULT_TEXT_MAP[response.status] || "Unknown error.";
97
+ const contentType = response.headers?.get("content-type")?.toLowerCase();
93
98
  const payload = response._data ?? response.data;
94
99
  let details;
95
100
  let errorResponse = null;
96
- if (typeof payload === "string") details = payload;
101
+ if (typeof payload === "string" && !contentType?.includes("text/html")) details = payload;
97
102
  else if (typeof payload === "object" && payload !== null) {
98
103
  if (typeof payload.message === "string") details = payload.message;
99
104
  else if (Array.isArray(payload.errors) && payload.errors.length) details = payload.errors.join(", ");
@@ -393,7 +398,6 @@ var Emails = class {
393
398
  body: payload,
394
399
  onResponseError: async ({ response }) => {
395
400
  error = getStatusError(response, {
396
- [400]: "Bad Request.",
397
401
  [403]: "User does not have access to this feature.",
398
402
  [413]: "The total message size should not exceed 30MB. This includes the message itself, headers, and the combined size of any attachments."
399
403
  });
@@ -483,10 +487,7 @@ var DomainsDkim = class {
483
487
  const response = await this.mailchannels.post(`/tx/v1/domains/${encodeURIComponent(domain)}/dkim-keys`, {
484
488
  body: payload,
485
489
  onResponseError: async ({ response }) => {
486
- error = getStatusError(response, {
487
- [400]: "Bad Request.",
488
- [409]: "Key pair already created for domain, and selector."
489
- });
490
+ error = getStatusError(response, { [409]: "Key pair already created for domain, and selector." });
490
491
  }
491
492
  }).catch((e) => {
492
493
  error ||= getResultError(e, "Failed to create DKIM key.");
@@ -535,7 +536,7 @@ var DomainsDkim = class {
535
536
  const response = await this.mailchannels.get(`/tx/v1/domains/${encodeURIComponent(domain)}/dkim-keys`, {
536
537
  query: payload,
537
538
  onResponseError: async ({ response }) => {
538
- error = getStatusError(response, { [400]: "Bad Request." });
539
+ error = getStatusError(response);
539
540
  }
540
541
  }).catch((e) => {
541
542
  error ||= getResultError(e, "Failed to fetch DKIM keys.");
@@ -570,10 +571,7 @@ var DomainsDkim = class {
570
571
  await this.mailchannels.patch(`/tx/v1/domains/${encodeURIComponent(domain)}/dkim-keys/${encodeURIComponent(options.selector)}`, {
571
572
  body: payload,
572
573
  onResponseError: async ({ response }) => {
573
- error = getStatusError(response, {
574
- [400]: "Bad Request.",
575
- [404]: "Specified key pair not found, or no active key for rotation. This may also occur if the DKIM domain or selector path parameter is missing."
576
- });
574
+ error = getStatusError(response, { [404]: "Specified key pair not found, or no active key for rotation. This may also occur if the DKIM domain or selector path parameter is missing." });
577
575
  }
578
576
  }).catch((e) => {
579
577
  error ||= getResultError(e, "Failed to update status of DKIM key.");
@@ -611,7 +609,6 @@ var DomainsDkim = class {
611
609
  body: payload,
612
610
  onResponseError: async ({ response }) => {
613
611
  error = getStatusError(response, {
614
- [400]: "Bad Request.",
615
612
  [404]: "Specified key pair not found.",
616
613
  [409]: "Key pair already created for domain, and provided new key selector."
617
614
  });
@@ -656,7 +653,7 @@ var DomainsCustomTracking = class DomainsCustomTracking {
656
653
  const response = await this.mailchannels.get("/tx/v1/custom-tracking-domains", {
657
654
  query: options,
658
655
  onResponseError: async ({ response }) => {
659
- error = getStatusError(response, { [400]: "Bad Request." });
656
+ error = getStatusError(response);
660
657
  }
661
658
  }).catch((e) => {
662
659
  error ||= getResultError(e, "Failed to fetch custom tracking domains.");
@@ -714,7 +711,6 @@ var DomainsCustomTracking = class DomainsCustomTracking {
714
711
  },
715
712
  onResponseError: async ({ response }) => {
716
713
  error = getStatusError(response, {
717
- [400]: "Invalid request body.",
718
714
  [403]: "No permission to register this domain.",
719
715
  [409]: "A domain with the same name already exists, or the hostname and scope combination is already registered.",
720
716
  [422]: "DNS verification incomplete. Either the TXT ownership record has not propagated yet or the hostname CNAME does not point to the required target."
@@ -796,7 +792,6 @@ var DomainsCustomTracking = class DomainsCustomTracking {
796
792
  },
797
793
  onResponseError: async ({ response }) => {
798
794
  error = getStatusError(response, {
799
- [400]: "Bad Request.",
800
795
  [403]: "No permission to update this domain.",
801
796
  [404]: `Custom tracking domain for hostname '${hostname}' and scope '${scope}' not found.`,
802
797
  [409]: "Name already used by another domain.",
@@ -910,10 +905,7 @@ var Domains = class {
910
905
  const response = await this.mailchannels.post("/tx/v1/check-domain", {
911
906
  body: payload,
912
907
  onResponseError: async ({ response }) => {
913
- error = getStatusError(response, {
914
- [400]: "Bad Request.",
915
- [403]: "User does not have access to this feature."
916
- });
908
+ error = getStatusError(response, { [403]: "User does not have access to this feature." });
917
909
  }
918
910
  }).catch((e) => {
919
911
  error ||= getResultError(e, "Failed to check domain.");
@@ -1110,10 +1102,7 @@ var Webhooks = class Webhooks {
1110
1102
  const response = await this.mailchannels.get("/tx/v1/webhook/public-key", {
1111
1103
  query: { id },
1112
1104
  onResponseError: async ({ response }) => {
1113
- error = getStatusError(response, {
1114
- [400]: "Bad Request.",
1115
- [404]: `The key '${id}' is not found.`
1116
- });
1105
+ error = getStatusError(response, { [404]: `The key '${id}' is not found.` });
1117
1106
  }
1118
1107
  }).catch((e) => {
1119
1108
  error ||= getResultError(e, "Failed to get signing key.");
@@ -1143,10 +1132,7 @@ var Webhooks = class Webhooks {
1143
1132
  const response = await this.mailchannels.post("/tx/v1/webhook/validate", {
1144
1133
  body: { request_id: requestId },
1145
1134
  onResponseError: async ({ response }) => {
1146
- error = getStatusError(response, {
1147
- [400]: "Bad Request.",
1148
- [404]: "No webhooks found for the account."
1149
- });
1135
+ error = getStatusError(response, { [404]: "No webhooks found for the account." });
1150
1136
  }
1151
1137
  }).catch((e) => {
1152
1138
  error ||= getResultError(e, "Failed to validate webhooks.");
@@ -1260,7 +1246,7 @@ var Webhooks = class Webhooks {
1260
1246
  offset: options?.offset
1261
1247
  },
1262
1248
  onResponseError: async ({ response }) => {
1263
- error = getStatusError(response, { [400]: "Bad Request." });
1249
+ error = getStatusError(response);
1264
1250
  }
1265
1251
  }).catch((e) => {
1266
1252
  error ||= getResultError(e, "Failed to fetch webhook batches.");
@@ -1288,7 +1274,7 @@ var Webhooks = class Webhooks {
1288
1274
  let error = null;
1289
1275
  const response = await this.mailchannels.post(`/tx/v1/webhook-batch/${encodeURIComponent(batchId)}/resend`, { onResponseError: async ({ response }) => {
1290
1276
  error = getStatusError(response, {
1291
- [400]: "Bad Request. The batch ID is invalid.",
1277
+ [400]: "The batch ID is invalid.",
1292
1278
  [404]: `The batch '${batchId}' is not found for the customer.`
1293
1279
  });
1294
1280
  } }).catch((e) => {
@@ -1537,10 +1523,7 @@ var SubAccountsLimits = class {
1537
1523
  await this.mailchannels.put(`/tx/v1/sub-account/${encodeURIComponent(handle)}/limit`, {
1538
1524
  body: options,
1539
1525
  onResponseError: async ({ response }) => {
1540
- error = getStatusError(response, {
1541
- [400]: "Bad Request.",
1542
- [404]: `Sub-account with handle '${handle}' not found.`
1543
- });
1526
+ error = getStatusError(response, { [404]: `Sub-account with handle '${handle}' not found.` });
1544
1527
  }
1545
1528
  }).catch((e) => {
1546
1529
  error ||= getResultError(e, "Failed to set sub-account limit.");
@@ -1807,7 +1790,7 @@ var Metrics = class {
1807
1790
  interval: options?.interval
1808
1791
  },
1809
1792
  onResponseError: async ({ response }) => {
1810
- error = getStatusError(response, { [400]: "Bad Request." });
1793
+ error = getStatusError(response);
1811
1794
  }
1812
1795
  }).catch((e) => {
1813
1796
  error ||= getResultError(e, "Failed to fetch engagement metrics.");
@@ -1861,7 +1844,7 @@ var Metrics = class {
1861
1844
  interval: options?.interval
1862
1845
  },
1863
1846
  onResponseError: async ({ response }) => {
1864
- error = getStatusError(response, { [400]: "Bad Request." });
1847
+ error = getStatusError(response);
1865
1848
  }
1866
1849
  }).catch((e) => {
1867
1850
  error ||= getResultError(e, "Failed to fetch performance metrics.");
@@ -1907,7 +1890,7 @@ var Metrics = class {
1907
1890
  interval: options?.interval
1908
1891
  },
1909
1892
  onResponseError: async ({ response }) => {
1910
- error = getStatusError(response, { [400]: "Bad Request." });
1893
+ error = getStatusError(response);
1911
1894
  }
1912
1895
  }).catch((e) => {
1913
1896
  error ||= getResultError(e, "Failed to fetch recipient behaviour metrics.");
@@ -1949,7 +1932,7 @@ var Metrics = class {
1949
1932
  interval: options?.interval
1950
1933
  },
1951
1934
  onResponseError: async ({ response }) => {
1952
- error = getStatusError(response, { [400]: "Bad Request." });
1935
+ error = getStatusError(response);
1953
1936
  }
1954
1937
  }).catch((e) => {
1955
1938
  error ||= getResultError(e, "Failed to fetch volume metrics.");
@@ -2024,7 +2007,7 @@ var Metrics = class {
2024
2007
  sort_order: options?.sortOrder
2025
2008
  },
2026
2009
  onResponseError: async ({ response }) => {
2027
- error = getStatusError(response, { [400]: "Bad Request." });
2010
+ error = getStatusError(response);
2028
2011
  }
2029
2012
  }).catch((e) => {
2030
2013
  error ||= getResultError(e, "Failed to fetch senders metrics.");
@@ -2075,7 +2058,6 @@ var Suppressions = class {
2075
2058
  body: payload,
2076
2059
  onResponseError: async ({ response }) => {
2077
2060
  error = getStatusError(response, {
2078
- [400]: "Bad Request.",
2079
2061
  [409]: "Conflict. One or more suppression entries in the request already exist and cannot be created again.",
2080
2062
  [413]: "Payload too large. The request exceeds the maximum allowed total of 1000 suppression entries for the parent account and/or its sub-accounts."
2081
2063
  });
@@ -2093,7 +2075,7 @@ var Suppressions = class {
2093
2075
  await this.mailchannels.delete(`/tx/v1/suppression-list/recipients/${encodeURIComponent(recipient)}`, {
2094
2076
  query: { source },
2095
2077
  onResponseError: async ({ response }) => {
2096
- error = getStatusError(response, { [400]: "Bad Request." });
2078
+ error = getStatusError(response);
2097
2079
  }
2098
2080
  }).catch((e) => {
2099
2081
  error ||= getResultError(e, "Failed to delete suppression entry.");
@@ -2139,7 +2121,7 @@ var Suppressions = class {
2139
2121
  const response = await this.mailchannels.get("/tx/v1/suppression-list", {
2140
2122
  query: payload,
2141
2123
  onResponseError: async ({ response }) => {
2142
- error = getStatusError(response, { [400]: "Bad Request." });
2124
+ error = getStatusError(response);
2143
2125
  }
2144
2126
  }).catch((e) => {
2145
2127
  error ||= getResultError(e, "Failed to fetch suppression entries.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailchannels-sdk",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
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",
@@ -52,13 +52,13 @@
52
52
  "devDependencies": {
53
53
  "@stylistic/eslint-plugin": "^5.10.0",
54
54
  "@types/markdown-it": "^14.2.0",
55
- "@types/node": "^26.2.0",
55
+ "@types/node": "^26.4.0",
56
56
  "@types/nodemailer": "^8.0.1",
57
57
  "@vitest/coverage-v8": "^4.1.11",
58
58
  "changelogen": "^0.6.2",
59
- "nodemailer": "^9.0.5",
59
+ "nodemailer": "^9.0.6",
60
60
  "obuild": "^0.4.38",
61
- "oxlint": "^1.79.0",
61
+ "oxlint": "^1.80.0",
62
62
  "scule": "^1.3.0",
63
63
  "typescript": "^6.0.3",
64
64
  "vitepress": "^2.0.0-alpha.19",