@push.rocks/smartmta 6.5.2 → 8.0.0

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 (84) hide show
  1. package/changelog.md +40 -0
  2. package/dist_rust/mailer-bin_linux_amd64 +0 -0
  3. package/dist_rust/mailer-bin_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/functions.errors.d.ts +3 -0
  6. package/dist_ts/functions.errors.js +8 -0
  7. package/dist_ts/index.d.ts +3 -0
  8. package/dist_ts/index.js +4 -1
  9. package/dist_ts/mail/core/classes.bouncemanager.d.ts +16 -12
  10. package/dist_ts/mail/core/classes.bouncemanager.js +146 -129
  11. package/dist_ts/mail/core/classes.email.js +15 -13
  12. package/dist_ts/mail/core/classes.emailvalidator.d.ts +3 -3
  13. package/dist_ts/mail/core/classes.emailvalidator.js +7 -5
  14. package/dist_ts/mail/core/classes.templatemanager.d.ts +10 -6
  15. package/dist_ts/mail/core/classes.templatemanager.js +35 -51
  16. package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +92 -22
  17. package/dist_ts/mail/delivery/classes.delivery.queue.js +738 -151
  18. package/dist_ts/mail/delivery/classes.delivery.system.d.ts +13 -7
  19. package/dist_ts/mail/delivery/classes.delivery.system.js +458 -145
  20. package/dist_ts/mail/delivery/classes.unified.rate.limiter.js +9 -8
  21. package/dist_ts/mail/delivery/functions.safe-observers.d.ts +10 -0
  22. package/dist_ts/mail/delivery/functions.safe-observers.js +37 -0
  23. package/dist_ts/mail/delivery/interfaces.d.ts +21 -0
  24. package/dist_ts/mail/delivery/interfaces.js +1 -1
  25. package/dist_ts/mail/interfaces.storage.d.ts +37 -6
  26. package/dist_ts/mail/interfaces.storage.js +33 -3
  27. package/dist_ts/mail/routing/classes.dkim.manager.d.ts +10 -6
  28. package/dist_ts/mail/routing/classes.dkim.manager.js +47 -31
  29. package/dist_ts/mail/routing/classes.dns.manager.d.ts +7 -5
  30. package/dist_ts/mail/routing/classes.dns.manager.js +22 -11
  31. package/dist_ts/mail/routing/classes.email.action.executor.d.ts +2 -1
  32. package/dist_ts/mail/routing/classes.email.action.executor.js +45 -16
  33. package/dist_ts/mail/routing/classes.email.router.d.ts +5 -2
  34. package/dist_ts/mail/routing/classes.email.router.js +17 -12
  35. package/dist_ts/mail/routing/classes.unified.email.server.d.ts +12 -6
  36. package/dist_ts/mail/routing/classes.unified.email.server.js +69 -78
  37. package/dist_ts/mail/routing/interfaces.d.ts +0 -2
  38. package/dist_ts/mail/security/classes.dkimcreator.d.ts +22 -45
  39. package/dist_ts/mail/security/classes.dkimcreator.js +93 -296
  40. package/dist_ts/mail/security/classes.spfverifier.js +5 -3
  41. package/dist_ts/paths.d.ts +0 -12
  42. package/dist_ts/paths.js +3 -36
  43. package/dist_ts/plugins.d.ts +2 -5
  44. package/dist_ts/plugins.js +3 -6
  45. package/dist_ts/security/classes.contentscanner.js +14 -12
  46. package/dist_ts/security/classes.ipreputationchecker.d.ts +9 -6
  47. package/dist_ts/security/classes.ipreputationchecker.js +42 -93
  48. package/dist_ts/security/classes.rustsecuritybridge.d.ts +52 -4
  49. package/dist_ts/security/classes.rustsecuritybridge.js +201 -4
  50. package/dist_ts/security/classes.securitylogger.js +7 -5
  51. package/dist_ts/security/index.d.ts +1 -1
  52. package/dist_ts/security/index.js +2 -2
  53. package/package.json +8 -9
  54. package/readme.hints.md +4 -3
  55. package/readme.md +50 -18
  56. package/readme.plan.md +6 -0
  57. package/ts/00_commitinfo_data.ts +1 -1
  58. package/ts/functions.errors.ts +8 -0
  59. package/ts/index.ts +3 -0
  60. package/ts/mail/core/classes.bouncemanager.ts +188 -155
  61. package/ts/mail/core/classes.email.ts +20 -14
  62. package/ts/mail/core/classes.emailvalidator.ts +9 -7
  63. package/ts/mail/core/classes.templatemanager.ts +42 -57
  64. package/ts/mail/delivery/classes.delivery.queue.ts +996 -185
  65. package/ts/mail/delivery/classes.delivery.system.ts +583 -170
  66. package/ts/mail/delivery/classes.unified.rate.limiter.ts +9 -8
  67. package/ts/mail/delivery/functions.safe-observers.ts +45 -0
  68. package/ts/mail/delivery/interfaces.ts +27 -1
  69. package/ts/mail/interfaces.storage.ts +64 -10
  70. package/ts/mail/routing/classes.dkim.manager.ts +65 -40
  71. package/ts/mail/routing/classes.dns.manager.ts +39 -16
  72. package/ts/mail/routing/classes.email.action.executor.ts +64 -17
  73. package/ts/mail/routing/classes.email.router.ts +20 -13
  74. package/ts/mail/routing/classes.unified.email.server.ts +107 -86
  75. package/ts/mail/routing/interfaces.ts +0 -2
  76. package/ts/mail/security/classes.dkimcreator.ts +150 -355
  77. package/ts/mail/security/classes.spfverifier.ts +4 -2
  78. package/ts/paths.ts +2 -41
  79. package/ts/plugins.ts +1 -6
  80. package/ts/security/classes.contentscanner.ts +14 -12
  81. package/ts/security/classes.ipreputationchecker.ts +46 -99
  82. package/ts/security/classes.rustsecuritybridge.ts +272 -6
  83. package/ts/security/classes.securitylogger.ts +6 -4
  84. package/ts/security/index.ts +5 -1
package/changelog.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-07-20 - 8.0.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - make recipient delivery and bounce processing durable per recipient (delivery)
8
+ - Queue schema V2 stores explicit unresolved, delivered, and permanent-failure recipient states plus a durable bounce outbox.
9
+ - V1 queue blobs remain readable and upgrade on their next mutation without synthesizing bounce work; V7 cannot read V2 blobs, so rollback after a V2 write is unsupported.
10
+ - Require Node.js 22 or newer.
11
+ - introduce durable per-recipient delivery checkpoints and bounce outbox (delivery)
12
+ - Add queue schema V2 with explicit recipient dispositions, structured SMTP transaction history, and deterministic bounce operations.
13
+ - Record final SMTP outcomes per recipient so accepted recipients are not resent and permanent RCPT failures are checkpointed with bounce work.
14
+ - Make built-in bounce processing idempotent by durable operation ID and add readiness barriers for managed routing, suppression, and reputation state.
15
+ - Add typed SMTP delivery failures with bounded, redacted transcripts and exact recipient results across Rust and TypeScript.
16
+ - Support caller-managed DKIM keys with validation-only startup, fail-closed signing, and no automatic key or DNS provisioning.
17
+ - Require Node.js 22 and upgrade TypeScript/Rust dependencies and tooling.
18
+
19
+ ### Fixes
20
+
21
+ - checkpoint final SMTP outcomes without duplicate delivery (smtp)
22
+ - Record acceptance only after the final 250 response, retry only unresolved 4xx recipients on later MX hosts, and never resend accepted or permanently rejected recipients.
23
+ - Atomically persist permanent 5xx recipient state with deterministic pending bounce operations.
24
+ - Drain pending bounce operations at startup and periodically across all queue statuses, isolating failures per recipient.
25
+ - make bounce processing idempotent by durable operation ID (bounce)
26
+ - Deduplicate concurrent and restarted built-in bounce processing and await suppression persistence before recording completion.
27
+ - Bound the hot completed-operation cache to 10,000 entries with a 24-hour TTL; durable processed markers remain authoritative after cache eviction or restart.
28
+ - Preserve at-least-once delivery semantics; custom handlers receive operation IDs for their own durable deduplication.
29
+ - isolate queue, delivery, security-log, and hook observers from committed state and statistics (events)
30
+ - make caller-managed DKIM initialization validation-only with zero SmartMTA DNS handlers, writes, rotation, or key generation (dkim)
31
+ - upgrade dependencies and make the stricter tsbuild 4.4.2 checks pass without skipLibCheck (tooling)
32
+
33
+ ## 2026-07-20 - 7.0.0
34
+
35
+ ### Breaking Changes
36
+
37
+ - require managed storage for SmartMTA persistence (storage)
38
+ - Removes local filesystem persistence fallbacks for DKIM keys, bounce data, templates, reputation cache, TLS material, and queue storage.
39
+ - Adds explicit IStorageManager and IBlobStorageManager contracts with in-memory implementations for tests and non-durable runtimes.
40
+ - Requires explicit queue.storageMode configuration and supports managed blob-backed queue persistence with restart recovery.
41
+ - Replaces path-based TLS configuration and file-based SMTP message handoff with in-memory PEM and inline message transport.
42
+
3
43
  ## 2026-07-19 - 6.5.2
4
44
 
5
45
  ### Fixes
Binary file
Binary file
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartmta',
6
- version: '6.5.2',
6
+ version: '8.0.0',
7
7
  description: 'A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with Rust acceleration.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlIQUF5SDtDQUN2SSxDQUFBIn0=
@@ -0,0 +1,3 @@
1
+ /** Normalize values caught from promise and callback boundaries. */
2
+ export declare function getErrorMessage(error: unknown): string;
3
+ export declare function getErrorStack(error: unknown): string | undefined;
@@ -0,0 +1,8 @@
1
+ /** Normalize values caught from promise and callback boundaries. */
2
+ export function getErrorMessage(error) {
3
+ return error instanceof Error ? error.message : String(error);
4
+ }
5
+ export function getErrorStack(error) {
6
+ return error instanceof Error ? error.stack : undefined;
7
+ }
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb25zLmVycm9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2Z1bmN0aW9ucy5lcnJvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0VBQW9FO0FBQ3BFLE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBYztJQUM1QyxPQUFPLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRSxDQUFDO0FBRUQsTUFBTSxVQUFVLGFBQWEsQ0FBQyxLQUFjO0lBQzFDLE9BQU8sS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzFELENBQUMifQ==
@@ -4,4 +4,7 @@ export * from './security/index.js';
4
4
  export { baseLogger, logger } from './logger.js';
5
5
  export declare const smartMtaCapabilities: Readonly<{
6
6
  readonly selectorCorrectDkimSigning: true;
7
+ readonly callerManagedDkimKeys: true;
8
+ readonly structuredSmtpTransactions: true;
9
+ readonly typedDeliveryFailures: true;
7
10
  }>;
package/dist_ts/index.js CHANGED
@@ -4,5 +4,8 @@ export * from './security/index.js';
4
4
  export { baseLogger, logger } from './logger.js';
5
5
  export const smartMtaCapabilities = Object.freeze({
6
6
  selectorCorrectDkimSigning: true,
7
+ callerManagedDkimKeys: true,
8
+ structuredSmtpTransactions: true,
9
+ typedDeliveryFailures: true,
7
10
  });
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2hELDBCQUEwQixFQUFFLElBQUk7Q0FDeEIsQ0FBQyxDQUFDIn0=
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2hELDBCQUEwQixFQUFFLElBQUk7SUFDaEMscUJBQXFCLEVBQUUsSUFBSTtJQUMzQiwwQkFBMEIsRUFBRSxJQUFJO0lBQ2hDLHFCQUFxQixFQUFFLElBQUk7Q0FDbkIsQ0FBQyxDQUFDIn0=
@@ -1,4 +1,4 @@
1
- import { type IStorageManagerLike } from '../interfaces.storage.js';
1
+ import type { IStorageManager } from '../interfaces.storage.js';
2
2
  import type { Email } from './classes.email.js';
3
3
  /**
4
4
  * Bounce types for categorizing the reasons for bounces
@@ -34,6 +34,7 @@ export declare enum BounceCategory {
34
34
  */
35
35
  export interface BounceRecord {
36
36
  id: string;
37
+ operationId?: string;
37
38
  originalEmailId?: string;
38
39
  recipient: string;
39
40
  sender: string;
@@ -69,12 +70,17 @@ export declare class BounceManager {
69
70
  private bounceCache;
70
71
  private suppressionList;
71
72
  private storageManager?;
73
+ private initializationPromise;
74
+ private operationPromises;
75
+ private completedOperations;
72
76
  constructor(options?: {
73
77
  retryStrategy?: Partial<RetryStrategy>;
74
78
  maxCacheSize?: number;
75
79
  cacheTTL?: number;
76
- storageManager?: IStorageManagerLike;
80
+ storageManager?: IStorageManager;
77
81
  });
82
+ /** Wait until the managed suppression state has been hydrated. */
83
+ initialize(): Promise<void>;
78
84
  /**
79
85
  * Process a bounce notification
80
86
  * @param bounceData Bounce data to process
@@ -89,11 +95,14 @@ export declare class BounceManager {
89
95
  * @returns Processed bounce record
90
96
  */
91
97
  processSmtpFailure(recipient: string, smtpResponse: string, options?: {
98
+ operationId?: string;
92
99
  sender?: string;
93
100
  originalEmailId?: string;
94
101
  statusCode?: string;
95
102
  headers?: Record<string, string>;
96
103
  }): Promise<BounceRecord>;
104
+ private processSmtpFailureOperation;
105
+ private readProcessedBounce;
97
106
  /**
98
107
  * Process a bounce notification email
99
108
  * @param bounceEmail The email containing bounce information
@@ -116,6 +125,8 @@ export declare class BounceManager {
116
125
  * @param reason Reason for suppression
117
126
  * @param expiresAt Expiration timestamp (undefined for permanent)
118
127
  */
128
+ private setSuppressionListEntry;
129
+ private addToSuppressionListAndPersist;
119
130
  addToSuppressionList(email: string, reason: string, expiresAt?: number): void;
120
131
  /**
121
132
  * Remove an email address from the suppression list
@@ -138,18 +149,11 @@ export declare class BounceManager {
138
149
  timestamp: number;
139
150
  expiresAt?: number;
140
151
  } | null;
141
- /**
142
- * Save suppression list to disk
143
- */
152
+ /** Save the suppression list through managed storage when durability is configured. */
144
153
  private saveSuppressionList;
145
- /**
146
- * Load suppression list from disk
147
- */
154
+ /** Load the suppression list from managed storage. */
148
155
  private loadSuppressionList;
149
- /**
150
- * Save bounce record to disk
151
- * @param bounce Bounce record to save
152
- */
156
+ /** Save one bounce record through managed storage when configured. */
153
157
  private saveBounceRecord;
154
158
  /**
155
159
  * Update bounce cache with new bounce information