@softure-ai/mailing 0.1.7 → 0.1.9

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.
Files changed (77) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +131 -23
  3. package/dist/cli/run.d.ts +6 -2
  4. package/dist/cli/run.d.ts.map +1 -1
  5. package/dist/cli/run.js +297 -40
  6. package/dist/cli/run.js.map +1 -1
  7. package/dist/contract.d.ts +35 -5
  8. package/dist/contract.d.ts.map +1 -1
  9. package/dist/index.d.ts +14 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/next/import-deliveries.d.ts +4 -0
  14. package/dist/next/import-deliveries.d.ts.map +1 -0
  15. package/dist/next/import-deliveries.js +9 -0
  16. package/dist/next/import-deliveries.js.map +1 -0
  17. package/dist/next/index.d.ts +1 -0
  18. package/dist/next/index.d.ts.map +1 -1
  19. package/dist/next/index.js +1 -0
  20. package/dist/next/index.js.map +1 -1
  21. package/dist/next/route.d.ts +3 -2
  22. package/dist/next/route.d.ts.map +1 -1
  23. package/dist/next/route.js +5 -4
  24. package/dist/next/route.js.map +1 -1
  25. package/dist/options.d.ts +19 -2
  26. package/dist/options.d.ts.map +1 -1
  27. package/dist/options.js +30 -6
  28. package/dist/options.js.map +1 -1
  29. package/dist/schema.d.ts +17 -0
  30. package/dist/schema.d.ts.map +1 -1
  31. package/dist/schema.js +2 -0
  32. package/dist/schema.js.map +1 -1
  33. package/dist/server/campaigns.d.ts +5 -0
  34. package/dist/server/campaigns.d.ts.map +1 -1
  35. package/dist/server/campaigns.js +10 -0
  36. package/dist/server/campaigns.js.map +1 -1
  37. package/dist/server/deliveries.d.ts +9 -5
  38. package/dist/server/deliveries.d.ts.map +1 -1
  39. package/dist/server/deliveries.js +9 -7
  40. package/dist/server/deliveries.js.map +1 -1
  41. package/dist/server/dns.d.ts +48 -1
  42. package/dist/server/dns.d.ts.map +1 -1
  43. package/dist/server/dns.js +124 -15
  44. package/dist/server/dns.js.map +1 -1
  45. package/dist/server/import-deliveries.d.ts +68 -0
  46. package/dist/server/import-deliveries.d.ts.map +1 -0
  47. package/dist/server/import-deliveries.js +105 -0
  48. package/dist/server/import-deliveries.js.map +1 -0
  49. package/dist/server/index.d.ts +4 -3
  50. package/dist/server/index.d.ts.map +1 -1
  51. package/dist/server/index.js +4 -3
  52. package/dist/server/index.js.map +1 -1
  53. package/dist/server/suppressions.d.ts.map +1 -1
  54. package/dist/server/suppressions.js +9 -6
  55. package/dist/server/suppressions.js.map +1 -1
  56. package/dist/server/unsubscribe-link.d.ts +3 -2
  57. package/dist/server/unsubscribe-link.d.ts.map +1 -1
  58. package/dist/server/unsubscribe-link.js +12 -3
  59. package/dist/server/unsubscribe-link.js.map +1 -1
  60. package/migrations/0004_allow_imported_deliveries.sql +20 -0
  61. package/module.json +1 -1
  62. package/package.json +1 -1
  63. package/src/cli/run.ts +311 -39
  64. package/src/contract.ts +30 -5
  65. package/src/index.ts +4 -1
  66. package/src/next/import-deliveries.ts +9 -0
  67. package/src/next/index.ts +1 -0
  68. package/src/next/route.ts +5 -4
  69. package/src/options.ts +36 -7
  70. package/src/schema.ts +2 -0
  71. package/src/server/campaigns.ts +13 -0
  72. package/src/server/deliveries.ts +15 -8
  73. package/src/server/dns.ts +174 -16
  74. package/src/server/import-deliveries.ts +149 -0
  75. package/src/server/index.ts +21 -0
  76. package/src/server/suppressions.ts +15 -8
  77. package/src/server/unsubscribe-link.ts +10 -3
@@ -52,29 +52,32 @@ export async function liftSuppression(ctx, address) {
52
52
  * throws (nothing is stored).
53
53
  */
54
54
  export async function unsubscribe(ctx, link, source, env = process.env) {
55
- const recipientKey = await verifyLink(ctx, link, env);
56
- if (recipientKey === null)
55
+ const verified = await verifyLink(ctx, link, env);
56
+ if (verified === null)
57
57
  return err("mailing.invalid_link");
58
+ const { recipientKey } = verified;
58
59
  const { onUnsubscribed } = getMailingOptions(ctx.config);
59
60
  await ctx.db.transaction(async (tx) => {
60
61
  const txCtx = { ...ctx, db: tx };
61
62
  await recordSuppression(txCtx, recipientKey, source);
62
- await onUnsubscribed?.({ recipientKey, source }, txCtx);
63
+ await onUnsubscribed?.({ recipientKey, source, link: verified.link }, txCtx);
63
64
  });
64
65
  return ok();
65
66
  }
66
- /** The recipient key a link proves, or `null` when it proves none. */
67
+ /** The recipient key a link proves and the link it came through, or `null` when it proves none. */
67
68
  async function verifyLink(ctx, link, env) {
68
69
  if (link === null)
69
70
  return null;
70
71
  if (!("scheme" in link) || link.scheme === "signed") {
71
72
  const token = "scheme" in link ? link.token : link;
72
- return verifyUnsubscribeToken(token, readUnsubscribeSecrets(env)) ? token.recipientKey : null;
73
+ return verifyUnsubscribeToken(token, readUnsubscribeSecrets(env)) ? { recipientKey: token.recipientKey, link: { scheme: "signed" } } : null;
73
74
  }
74
75
  const legacy = getMailingOptions(ctx.config).legacyUnsubscribe;
75
76
  if (legacy === undefined)
76
77
  return null;
77
78
  const address = await legacy.verify(link.values, ctx);
78
- return typeof address === "string" && address.trim() !== "" ? getRecipientKey(address) : null;
79
+ if (typeof address !== "string" || address.trim() === "")
80
+ return null;
81
+ return { recipientKey: getRecipientKey(address), link: { scheme: "legacy", values: link.values } };
79
82
  }
80
83
  //# sourceMappingURL=suppressions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"suppressions.js","sourceRoot":"","sources":["../../src/server/suppressions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"suppressions.js","sourceRoot":"","sources":["../../src/server/suppressions.ts"],"names":[],"mappings":"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"}
@@ -61,8 +61,9 @@ export interface LinkParams {
61
61
  /**
62
62
  * The link in a query or a form. A link with the recipient parameter (`r`) is a signed link, whatever else it
63
63
  * carries, so a crafted URL cannot route a signed link to the app's legacy check. Without it, and with
64
- * `mailing({ legacyUnsubscribe })`, a link that has every legacy parameter (non-empty, at most 512 characters) is
65
- * a legacy link. Anything else is `null`. Checks no signature: `unsubscribe` does.
64
+ * `mailing({ legacyUnsubscribe })`, a link that has every required legacy parameter (non-empty, at most 512
65
+ * characters) is a legacy link; its values also hold the optional parameters it has (an empty one is absent, one
66
+ * over 512 characters makes the link invalid). Anything else is `null`. Checks no signature: `unsubscribe` does.
66
67
  */
67
68
  export declare function readUnsubscribeLink(params: LinkParams, config: SoftureConfig): UnsubscribeLink | null;
68
69
  /** The query (or form) parameters that carry `link`, to send it back to the page. */
@@ -1 +1 @@
1
- {"version":3,"file":"unsubscribe-link.d.ts","sourceRoot":"","sources":["../../src/server/unsubscribe-link.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,yCAAyC;AACzC,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AACnE,sEAAsE;AACtE,eAAO,MAAM,+BAA+B,wCAAwC,CAAC;AACrF,kFAAkF;AAClF,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,0CAA0C;AAC1C,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,eAAe,MAAM,CAAC;AAWnC,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAE/D,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,2DAA2D;AAC3D,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,8FAA8F;AAC9F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wCAAwC;AACxC,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,GAAiB,GAAG,kBAAkB,CAEjF;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAWpG;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAQ9G;AAED,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,6GAA6G;AAC7G,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAErF,gFAAgF;AAChF,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,GAAG,eAAe,GAAG,IAAI,CAcrG;AAED,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtF;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,gBAAgB,GAAG,IAAI,CAIpG"}
1
+ {"version":3,"file":"unsubscribe-link.d.ts","sourceRoot":"","sources":["../../src/server/unsubscribe-link.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,yCAAyC;AACzC,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AACnE,sEAAsE;AACtE,eAAO,MAAM,+BAA+B,wCAAwC,CAAC;AACrF,kFAAkF;AAClF,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,0CAA0C;AAC1C,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,eAAe,MAAM,CAAC;AAWnC,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAE/D,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,2DAA2D;AAC3D,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,8FAA8F;AAC9F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wCAAwC;AACxC,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,GAAiB,GAAG,kBAAkB,CAEjF;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAWpG;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAQ9G;AAED,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,6GAA6G;AAC7G,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAErF,gFAAgF;AAChF,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,GAAG,eAAe,GAAG,IAAI,CAoBrG;AAED,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtF;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,gBAAgB,GAAG,IAAI,CAIpG"}
@@ -74,8 +74,9 @@ export const MAX_LEGACY_VALUE_LENGTH = 512;
74
74
  /**
75
75
  * The link in a query or a form. A link with the recipient parameter (`r`) is a signed link, whatever else it
76
76
  * carries, so a crafted URL cannot route a signed link to the app's legacy check. Without it, and with
77
- * `mailing({ legacyUnsubscribe })`, a link that has every legacy parameter (non-empty, at most 512 characters) is
78
- * a legacy link. Anything else is `null`. Checks no signature: `unsubscribe` does.
77
+ * `mailing({ legacyUnsubscribe })`, a link that has every required legacy parameter (non-empty, at most 512
78
+ * characters) is a legacy link; its values also hold the optional parameters it has (an empty one is absent, one
79
+ * over 512 characters makes the link invalid). Anything else is `null`. Checks no signature: `unsubscribe` does.
79
80
  */
80
81
  export function readUnsubscribeLink(params, config) {
81
82
  if (params.get(RECIPIENT_PARAM) !== null && params.get(RECIPIENT_PARAM) !== undefined) {
@@ -86,12 +87,20 @@ export function readUnsubscribeLink(params, config) {
86
87
  if (legacy === undefined)
87
88
  return null;
88
89
  const values = {};
89
- for (const name of legacy.params) {
90
+ for (const name of legacy.params.required) {
90
91
  const value = params.get(name);
91
92
  if (typeof value !== "string" || value === "" || value.length > MAX_LEGACY_VALUE_LENGTH)
92
93
  return null;
93
94
  values[name] = value;
94
95
  }
96
+ for (const name of legacy.params.optional) {
97
+ const value = params.get(name);
98
+ if (typeof value !== "string" || value === "")
99
+ continue;
100
+ if (value.length > MAX_LEGACY_VALUE_LENGTH)
101
+ return null;
102
+ values[name] = value;
103
+ }
95
104
  return { scheme: "legacy", values };
96
105
  }
97
106
  /** The query (or form) parameters that carry `link`, to send it back to the page. */
@@ -1 +1 @@
1
- {"version":3,"file":"unsubscribe-link.js","sourceRoot":"","sources":["../../src/server/unsubscribe-link.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,kGAAkG;AAClG,kGAAkG;AAClG,kGAAkG;AAClG,mDAAmD;AACnD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEnE,yCAAyC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,sEAAsE;AACtE,MAAM,CAAC,MAAM,+BAA+B,GAAG,qCAAqC,CAAC;AACrF,kFAAkF;AAClF,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD,0CAA0C;AAC1C,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC;;;GAGG;AACH,MAAM,aAAa,GAAG,iCAAiC,CAAC;AAExD,sCAAsC;AACtC,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAwB5C;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACvF,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,gBAAgB,CAAC,YAAoB,EAAE,MAAc;IACnE,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,aAAa,GAAG,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACpG,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,sBAAsB,CAAC,MAAW,OAAO,CAAC,GAAG;IAC3D,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,EAAE,CAAC;AAC1H,CAAC;AAED,SAAS,UAAU,CAAC,KAAyB;IAC3C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,6BAA6B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAuB,EAAE,OAA2B;IACzF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAClG,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC5D,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,IAAI,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;QACxF,yDAAyD;QACzD,OAAO,GAAG,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,OAAO,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,qBAAqB,CAAC,MAAqB,EAAE,OAAe,EAAE,MAAc;IAC1F,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC,eAAe,CAAC,EAAE,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAClI,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO;QACL,IAAI,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE;QACpE,QAAQ,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE;KACtE,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAY3C;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAkB,EAAE,MAAqB;IAC3E,IAAI,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,SAAS,EAAE,CAAC;QACtF,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7D,CAAC;IACD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC;IAC3D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,uBAAuB;YAAE,OAAO,IAAI,CAAC;QACrG,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,wBAAwB,CAAC,IAAqB;IAC5D,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;AACjJ,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAC,MAAsC;IACzE,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9C,OAAO,OAAO,YAAY,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChH,CAAC"}
1
+ {"version":3,"file":"unsubscribe-link.js","sourceRoot":"","sources":["../../src/server/unsubscribe-link.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ -- Lets an app seed the ledger with the deliveries it made before it adopted the module (importDeliveries), so the
2
+ -- first deliverOnce or campaign run skips them. Its history rarely kept the provider's message id, so a `sent` row
3
+ -- needs one only when the module sent it; an imported row is marked by imported_at. A row the module did not close
4
+ -- still never has a message id.
5
+ -- Rollback: DELETE FROM mailing.deliveries WHERE imported_at IS NOT NULL AND provider_message_id IS NULL;
6
+ -- ALTER TABLE mailing.deliveries DROP CONSTRAINT deliveries_message_id_check;
7
+ -- ALTER TABLE mailing.deliveries DROP CONSTRAINT deliveries_sent_message_id_check;
8
+ -- ALTER TABLE mailing.deliveries DROP COLUMN imported_at;
9
+ -- ALTER TABLE mailing.deliveries ADD CONSTRAINT deliveries_check1 CHECK ((status = 'sent') = (provider_message_id IS NOT NULL));
10
+ -- DELETE FROM softure.migrations WHERE module = 'mailing' AND version = 4;
11
+
12
+ -- When the row was imported; null for a delivery the module made. Only a closed row can be imported.
13
+ ALTER TABLE deliveries ADD COLUMN imported_at timestamptz
14
+ CONSTRAINT deliveries_imported_at_check CHECK (imported_at IS NULL OR status IN ('sent', 'rejected'));
15
+
16
+ -- Was: CHECK ((status = 'sent') = (provider_message_id IS NOT NULL)), unnamed in 0002.
17
+ ALTER TABLE deliveries DROP CONSTRAINT deliveries_check1;
18
+ ALTER TABLE deliveries ADD CONSTRAINT deliveries_message_id_check CHECK (provider_message_id IS NULL OR status = 'sent');
19
+ ALTER TABLE deliveries ADD CONSTRAINT deliveries_sent_message_id_check
20
+ CHECK (status <> 'sent' OR provider_message_id IS NOT NULL OR imported_at IS NOT NULL);
package/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "mailing",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "dependsOn": {},
5
5
  "dbSchema": "mailing",
6
6
  "tables": ["suppressions", "campaigns", "deliveries"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softure-ai/mailing",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "SOFTURE AI mailing module: sendMail over a provider adapter (Resend first) with plain-text and HTML bodies, sender and reply-to from config, idempotency keys, a timeout and a typed result; signed one-click unsubscribe (RFC 8058) with a suppression list for list mail; an exactly-once delivery ledger, campaigns sent from a content file by the softure-mail command, and a sender DNS check; a fake provider for tests.",
5
5
  "license": "MIT",
6
6
  "type": "module",