@push.rocks/smartmta 9.4.1 → 9.5.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.
- package/changelog.md +14 -0
- package/dist_rust/mailer-bin_linux_amd64 +0 -0
- package/dist_rust/mailer-bin_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +63 -2
- package/dist_ts/mail/delivery/classes.delivery.queue.js +749 -193
- package/dist_ts/mail/delivery/classes.delivery.system.d.ts +6 -0
- package/dist_ts/mail/delivery/classes.delivery.system.js +146 -62
- package/dist_ts/mail/delivery/functions.raw-email.d.ts +9 -0
- package/dist_ts/mail/delivery/functions.raw-email.js +85 -0
- package/dist_ts/mail/delivery/symbols.delivery.queue.d.ts +6 -0
- package/dist_ts/mail/delivery/symbols.delivery.queue.js +7 -0
- package/dist_ts/mail/index.d.ts +1 -0
- package/dist_ts/mail/index.js +1 -1
- package/dist_ts/mail/routing/classes.unified.email.server.d.ts +40 -0
- package/dist_ts/mail/routing/classes.unified.email.server.js +222 -76
- package/dist_ts/mail/routing/symbols.unified.email.server.d.ts +2 -0
- package/dist_ts/mail/routing/symbols.unified.email.server.js +3 -0
- package/dist_ts/security/classes.rustsecuritybridge.d.ts +11 -0
- package/dist_ts/security/classes.rustsecuritybridge.js +1 -1
- package/package.json +2 -2
- package/readme.hints.md +8 -0
- package/readme.md +34 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +1 -0
- package/ts/mail/delivery/classes.delivery.queue.ts +923 -226
- package/ts/mail/delivery/classes.delivery.system.ts +192 -80
- package/ts/mail/delivery/functions.raw-email.ts +111 -0
- package/ts/mail/delivery/symbols.delivery.queue.ts +6 -0
- package/ts/mail/index.ts +1 -0
- package/ts/mail/routing/classes.unified.email.server.ts +329 -85
- package/ts/mail/routing/symbols.unified.email.server.ts +6 -0
- package/ts/security/classes.rustsecuritybridge.ts +6 -0
package/changelog.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-07-31 - 9.5.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- add a durable raw outbound MTA queue (raw-outbound)
|
|
8
|
+
- Add managed-only `UnifiedEmailServer.enqueueRawEmail()` with canonical CRLF-terminated exact RFC822 bytes, a separate canonical ordered SMTP envelope, stable idempotency, a 32 MiB default message limit, and a weighted global raw-operation memory budget.
|
|
9
|
+
- Store raw items as atomic schema V3 queue blobs while retaining only sanitized metadata in memory; preserve structured schema V2 writes and V1/V2 hydration unchanged.
|
|
10
|
+
- Serialize raw status mutations and removal per item, verify payload length/digest/envelope on every lazy reread, refuse processing-item removal, and fail closed on missing or corrupt payloads.
|
|
11
|
+
- Isolate all public queue/status snapshots, keep queue-only operations behind internal symbols, and route internal readiness by item ID so observers cannot mutate delivery inputs.
|
|
12
|
+
- Reuse MX, self-MX, recipient checkpoint, retry, bounce, RemoteIngress proxy/source-evidence, timeout, TLS, pooling, capture, and cleanup behavior for raw delivery.
|
|
13
|
+
- Extend Rust raw SMTP delivery with mandatory caller-supplied DKIM material, canonical-byte enforcement, and actual-sent-byte capture without UTF-8 conversion; keep unsigned queue bytes immutable across attempts and capture memory reserved through verification.
|
|
14
|
+
- Snapshot raw caller buffers synchronously, reserve queue capacity before persistence, share the weighted memory budget with direct raw sends, cap fixed raw-operation overhead, use bounded startup hydration, close outbound admission before shutdown, drain admitted enqueue/queue-scan/delivery/authentication work before storage and Rust teardown, and recover interrupted V3 records without dropping their payload.
|
|
15
|
+
- Add `smartMtaCapabilities.durableRawOutboundQueue` and document the schema V3 downgrade gate and deployment-wide single-writer prerequisite.
|
|
16
|
+
|
|
3
17
|
## 2026-07-27 - 9.4.1
|
|
4
18
|
|
|
5
19
|
### Fixes
|
|
Binary file
|
|
Binary file
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartmta',
|
|
6
|
-
version: '9.
|
|
6
|
+
version: '9.5.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=
|
package/dist_ts/index.d.ts
CHANGED
package/dist_ts/index.js
CHANGED
|
@@ -15,5 +15,6 @@ export const smartMtaCapabilities = Object.freeze({
|
|
|
15
15
|
exactAcceptedEnvelopeDispatch: true,
|
|
16
16
|
terminalLocalDeliverActions: true,
|
|
17
17
|
smtpAuthAccountsAndScopes: true,
|
|
18
|
+
durableRawOutboundQueue: true,
|
|
18
19
|
});
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2hELDBCQUEwQixFQUFFLElBQUk7SUFDaEMscUJBQXFCLEVBQUUsSUFBSTtJQUMzQiwwQkFBMEIsRUFBRSxJQUFJO0lBQ2hDLHFCQUFxQixFQUFFLElBQUk7SUFDM0Isb0JBQW9CLEVBQUUsSUFBSTtJQUMxQixpQkFBaUIsRUFBRSxJQUFJO0lBQ3ZCLG1CQUFtQixFQUFFLElBQUk7SUFDekIsbUJBQW1CLEVBQUUsSUFBSTtJQUN6Qiw0QkFBNEIsRUFBRSxJQUFJO0lBQ2xDLDZCQUE2QixFQUFFLElBQUk7SUFDbkMsMkJBQTJCLEVBQUUsSUFBSTtJQUNqQyx5QkFBeUIsRUFBRSxJQUFJO0lBQy9CLHVCQUF1QixFQUFFLElBQUk7Q0FDckIsQ0FBQyxDQUFDIn0=
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import type
|
|
2
|
+
import { type IBlobStorageManager } from '../interfaces.storage.js';
|
|
3
3
|
import { type EmailProcessingMode } from './interfaces.js';
|
|
4
4
|
import type { ISmtpTransactionAttempt } from './interfaces.js';
|
|
5
5
|
import type { IEmailRoute } from '../routing/interfaces.js';
|
|
6
6
|
import { Email } from '../core/classes.email.js';
|
|
7
|
+
import { type IRawSmtpEnvelope } from './functions.raw-email.js';
|
|
8
|
+
import { kQueueCloseAdmission, kQueueCreateItemSnapshot, kQueueEnqueueRaw, kQueueReserveRawAccess, kQueueSetReadyItemsHandler, kQueueWithRawMessage } from './symbols.delivery.queue.js';
|
|
7
9
|
/**
|
|
8
10
|
* Queue item status
|
|
9
11
|
*/
|
|
@@ -47,6 +49,14 @@ export interface IQueueItem {
|
|
|
47
49
|
idempotencyFingerprint?: string;
|
|
48
50
|
processingMode: EmailProcessingMode;
|
|
49
51
|
processingResult: Email;
|
|
52
|
+
/** Present only for durable exact-byte outbound queue items. */
|
|
53
|
+
messageFormat?: 'raw-rfc822';
|
|
54
|
+
/** SHA-256 of the immutable unsigned RFC822 bytes. */
|
|
55
|
+
rawMessageSha256?: string;
|
|
56
|
+
/** Exact immutable unsigned RFC822 byte length. */
|
|
57
|
+
rawMessageLength?: number;
|
|
58
|
+
/** Canonical SMTP envelope, independent from message headers. */
|
|
59
|
+
smtpEnvelope?: IRawSmtpEnvelope;
|
|
50
60
|
/** Materialized attachment count for queue/detail consumers. */
|
|
51
61
|
attachmentCount?: number;
|
|
52
62
|
route?: IEmailRoute;
|
|
@@ -64,6 +74,8 @@ export interface IQueueItem {
|
|
|
64
74
|
smtpTransactions?: ISmtpTransactionAttempt[];
|
|
65
75
|
}
|
|
66
76
|
export declare const ACCEPTED_ENVELOPE_IDEMPOTENCY_RETENTION_MS: number;
|
|
77
|
+
export declare const DEFAULT_MAX_RAW_MESSAGE_BYTES: number;
|
|
78
|
+
export declare const DEFAULT_RAW_IN_FLIGHT_BYTE_BUDGET: number;
|
|
67
79
|
export interface IQueueFailureOptions {
|
|
68
80
|
/** Unknown failures default to retryable so temporary internal faults do not lose mail. */
|
|
69
81
|
retryable?: boolean;
|
|
@@ -91,6 +103,10 @@ export interface IQueueOptions {
|
|
|
91
103
|
checkInterval?: number;
|
|
92
104
|
maxQueueSize?: number;
|
|
93
105
|
maxPerDestination?: number;
|
|
106
|
+
/** Maximum exact RFC822 bytes accepted by enqueueRawEmail. Defaults to 32 MiB. */
|
|
107
|
+
maxRawMessageBytes?: number;
|
|
108
|
+
/** Conservative memory budget for active raw operations. Defaults to 192 MiB. */
|
|
109
|
+
rawInFlightByteBudget?: number;
|
|
94
110
|
maxRetries?: number;
|
|
95
111
|
baseRetryDelay?: number;
|
|
96
112
|
maxRetryDelay?: number;
|
|
@@ -103,6 +119,11 @@ export interface IQueueEnqueueOptions {
|
|
|
103
119
|
/** Fail closed unless the queue is backed by managed blob storage. */
|
|
104
120
|
requireDurable?: boolean;
|
|
105
121
|
}
|
|
122
|
+
interface IRawQueueEnqueueOptions {
|
|
123
|
+
rawMessage: Buffer;
|
|
124
|
+
envelope: IRawSmtpEnvelope;
|
|
125
|
+
idempotencyKey: string;
|
|
126
|
+
}
|
|
106
127
|
export interface IQueueStats {
|
|
107
128
|
queueSize: number;
|
|
108
129
|
status: {
|
|
@@ -131,26 +152,46 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
131
152
|
private queue;
|
|
132
153
|
private checkTimer?;
|
|
133
154
|
private cleanupTimer?;
|
|
155
|
+
private cleanupFlight?;
|
|
134
156
|
private stats;
|
|
135
157
|
private processing;
|
|
136
158
|
private processingScanPromise?;
|
|
137
159
|
private processingRescanRequested;
|
|
138
|
-
private processingScanShutdownTimeoutMs;
|
|
139
160
|
private totalProcessed;
|
|
140
161
|
private ownsManagedPrefix;
|
|
141
162
|
private lifecycleState;
|
|
142
163
|
private readonly idempotentEnqueueFlights;
|
|
143
164
|
private idempotencyTombstoneCleanupCursor?;
|
|
165
|
+
private readonly itemMutationFlights;
|
|
166
|
+
private rawBytesInFlight;
|
|
167
|
+
private rawByteWaiters;
|
|
168
|
+
private rawReservationCount;
|
|
169
|
+
private rawReservationDrainWaiters;
|
|
170
|
+
private readyItemsHandler?;
|
|
171
|
+
private acceptingNewItems;
|
|
172
|
+
private acceptingMutations;
|
|
173
|
+
private acceptingRawReservations;
|
|
174
|
+
private readonly enqueueFlights;
|
|
175
|
+
private pendingNewItemCount;
|
|
176
|
+
private shutdownFlight?;
|
|
144
177
|
/**
|
|
145
178
|
* Create a new unified delivery queue
|
|
146
179
|
* @param options Queue options
|
|
147
180
|
*/
|
|
148
181
|
constructor(options: IQueueOptions);
|
|
149
182
|
private assertMutable;
|
|
183
|
+
private assertAcceptingNewItems;
|
|
184
|
+
private trackEnqueueFlight;
|
|
150
185
|
/** Whether queue entries are committed through caller-managed blob storage. */
|
|
151
186
|
hasManagedStorage(): boolean;
|
|
152
187
|
/** Whether managed storage can list a backend-bounded page of keys. */
|
|
153
188
|
hasPaginatedManagedStorage(): boolean;
|
|
189
|
+
[kQueueCloseAdmission](): void;
|
|
190
|
+
[kQueueSetReadyItemsHandler](handlerArg?: (itemIds: string[]) => Promise<void>): void;
|
|
191
|
+
private cloneEmail;
|
|
192
|
+
[kQueueCreateItemSnapshot](itemArg: IQueueItem): IQueueItem;
|
|
193
|
+
private emitItemEventSafely;
|
|
194
|
+
private emitReadyItemsSafely;
|
|
154
195
|
private idempotentQueueId;
|
|
155
196
|
private idempotencyTombstonePrefix;
|
|
156
197
|
private idempotencyTombstoneKey;
|
|
@@ -172,6 +213,7 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
172
213
|
* Start queue processing
|
|
173
214
|
*/
|
|
174
215
|
private startProcessing;
|
|
216
|
+
private runPeriodicCleanup;
|
|
175
217
|
/**
|
|
176
218
|
* Stop queue processing
|
|
177
219
|
*/
|
|
@@ -193,6 +235,10 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
193
235
|
* @param route Email route
|
|
194
236
|
*/
|
|
195
237
|
enqueue(processingResult: Email, mode: EmailProcessingMode, route?: IEmailRoute, enqueueOptions?: IQueueEnqueueOptions): Promise<string>;
|
|
238
|
+
private enqueueAccepted;
|
|
239
|
+
[kQueueEnqueueRaw](optionsArg: IRawQueueEnqueueOptions): Promise<string>;
|
|
240
|
+
private enqueueRawAccepted;
|
|
241
|
+
private enqueueIdempotent;
|
|
196
242
|
private enqueueNew;
|
|
197
243
|
/**
|
|
198
244
|
* Get an item from the queue
|
|
@@ -253,8 +299,21 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
253
299
|
removeItem(id: string): Promise<boolean>;
|
|
254
300
|
private storageKey;
|
|
255
301
|
private persistItem;
|
|
302
|
+
private persistCurrentItem;
|
|
256
303
|
private serializeItem;
|
|
304
|
+
private withItemMutex;
|
|
257
305
|
private applyPersistedMutation;
|
|
306
|
+
private createRawIntegrityError;
|
|
307
|
+
private readVerifiedRawMessage;
|
|
308
|
+
private claimRawReservation;
|
|
309
|
+
private createRawByteRelease;
|
|
310
|
+
private reserveRawBytes;
|
|
311
|
+
private reserveRawBytesImmediately;
|
|
312
|
+
[kQueueReserveRawAccess](rawMessageLengthArg: number): () => void;
|
|
313
|
+
private releaseRawBytes;
|
|
314
|
+
private withRawByteReservation;
|
|
315
|
+
private waitForRawReservationsToDrain;
|
|
316
|
+
[kQueueWithRawMessage]<T>(itemIdArg: string, callbackArg: (rawMessage: Buffer) => Promise<T>): Promise<T>;
|
|
258
317
|
private removeItemFromStorage;
|
|
259
318
|
private deserializeItem;
|
|
260
319
|
private loadFromStorage;
|
|
@@ -283,4 +342,6 @@ export declare class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
283
342
|
* Shutdown the queue
|
|
284
343
|
*/
|
|
285
344
|
shutdown(): Promise<void>;
|
|
345
|
+
private shutdownOnce;
|
|
286
346
|
}
|
|
347
|
+
export {};
|