@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.
- package/changelog.md +40 -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/functions.errors.d.ts +3 -0
- package/dist_ts/functions.errors.js +8 -0
- package/dist_ts/index.d.ts +3 -0
- package/dist_ts/index.js +4 -1
- package/dist_ts/mail/core/classes.bouncemanager.d.ts +16 -12
- package/dist_ts/mail/core/classes.bouncemanager.js +146 -129
- package/dist_ts/mail/core/classes.email.js +15 -13
- package/dist_ts/mail/core/classes.emailvalidator.d.ts +3 -3
- package/dist_ts/mail/core/classes.emailvalidator.js +7 -5
- package/dist_ts/mail/core/classes.templatemanager.d.ts +10 -6
- package/dist_ts/mail/core/classes.templatemanager.js +35 -51
- package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +92 -22
- package/dist_ts/mail/delivery/classes.delivery.queue.js +738 -151
- package/dist_ts/mail/delivery/classes.delivery.system.d.ts +13 -7
- package/dist_ts/mail/delivery/classes.delivery.system.js +458 -145
- package/dist_ts/mail/delivery/classes.unified.rate.limiter.js +9 -8
- package/dist_ts/mail/delivery/functions.safe-observers.d.ts +10 -0
- package/dist_ts/mail/delivery/functions.safe-observers.js +37 -0
- package/dist_ts/mail/delivery/interfaces.d.ts +21 -0
- package/dist_ts/mail/delivery/interfaces.js +1 -1
- package/dist_ts/mail/interfaces.storage.d.ts +37 -6
- package/dist_ts/mail/interfaces.storage.js +33 -3
- package/dist_ts/mail/routing/classes.dkim.manager.d.ts +10 -6
- package/dist_ts/mail/routing/classes.dkim.manager.js +47 -31
- package/dist_ts/mail/routing/classes.dns.manager.d.ts +7 -5
- package/dist_ts/mail/routing/classes.dns.manager.js +22 -11
- package/dist_ts/mail/routing/classes.email.action.executor.d.ts +2 -1
- package/dist_ts/mail/routing/classes.email.action.executor.js +45 -16
- package/dist_ts/mail/routing/classes.email.router.d.ts +5 -2
- package/dist_ts/mail/routing/classes.email.router.js +17 -12
- package/dist_ts/mail/routing/classes.unified.email.server.d.ts +12 -6
- package/dist_ts/mail/routing/classes.unified.email.server.js +69 -78
- package/dist_ts/mail/routing/interfaces.d.ts +0 -2
- package/dist_ts/mail/security/classes.dkimcreator.d.ts +22 -45
- package/dist_ts/mail/security/classes.dkimcreator.js +93 -296
- package/dist_ts/mail/security/classes.spfverifier.js +5 -3
- package/dist_ts/paths.d.ts +0 -12
- package/dist_ts/paths.js +3 -36
- package/dist_ts/plugins.d.ts +2 -5
- package/dist_ts/plugins.js +3 -6
- package/dist_ts/security/classes.contentscanner.js +14 -12
- package/dist_ts/security/classes.ipreputationchecker.d.ts +9 -6
- package/dist_ts/security/classes.ipreputationchecker.js +42 -93
- package/dist_ts/security/classes.rustsecuritybridge.d.ts +52 -4
- package/dist_ts/security/classes.rustsecuritybridge.js +201 -4
- package/dist_ts/security/classes.securitylogger.js +7 -5
- package/dist_ts/security/index.d.ts +1 -1
- package/dist_ts/security/index.js +2 -2
- package/package.json +8 -9
- package/readme.hints.md +4 -3
- package/readme.md +50 -18
- package/readme.plan.md +6 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/functions.errors.ts +8 -0
- package/ts/index.ts +3 -0
- package/ts/mail/core/classes.bouncemanager.ts +188 -155
- package/ts/mail/core/classes.email.ts +20 -14
- package/ts/mail/core/classes.emailvalidator.ts +9 -7
- package/ts/mail/core/classes.templatemanager.ts +42 -57
- package/ts/mail/delivery/classes.delivery.queue.ts +996 -185
- package/ts/mail/delivery/classes.delivery.system.ts +583 -170
- package/ts/mail/delivery/classes.unified.rate.limiter.ts +9 -8
- package/ts/mail/delivery/functions.safe-observers.ts +45 -0
- package/ts/mail/delivery/interfaces.ts +27 -1
- package/ts/mail/interfaces.storage.ts +64 -10
- package/ts/mail/routing/classes.dkim.manager.ts +65 -40
- package/ts/mail/routing/classes.dns.manager.ts +39 -16
- package/ts/mail/routing/classes.email.action.executor.ts +64 -17
- package/ts/mail/routing/classes.email.router.ts +20 -13
- package/ts/mail/routing/classes.unified.email.server.ts +107 -86
- package/ts/mail/routing/interfaces.ts +0 -2
- package/ts/mail/security/classes.dkimcreator.ts +150 -355
- package/ts/mail/security/classes.spfverifier.ts +4 -2
- package/ts/paths.ts +2 -41
- package/ts/plugins.ts +1 -6
- package/ts/security/classes.contentscanner.ts +14 -12
- package/ts/security/classes.ipreputationchecker.ts +46 -99
- package/ts/security/classes.rustsecuritybridge.ts +272 -6
- package/ts/security/classes.securitylogger.ts +6 -4
- package/ts/security/index.ts +5 -1
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import * as plugins from '../../plugins.js';
|
|
2
1
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { deserialize, serialize } from 'node:v8';
|
|
5
4
|
import { logger } from '../../logger.js';
|
|
6
5
|
import {} from './interfaces.js';
|
|
6
|
+
import { normalizeSmtpTranscript, SMTP_TRANSCRIPT_MAX_ENTRIES, SMTP_TRANSCRIPT_MAX_ENTRY_CODE_POINTS, SMTP_TRANSCRIPT_MAX_UTF8_BYTES, } from '../../security/classes.rustsecuritybridge.js';
|
|
7
|
+
import { Email } from '../core/classes.email.js';
|
|
8
|
+
import { emitSafely } from './functions.safe-observers.js';
|
|
9
|
+
import { getErrorMessage } from '../../functions.errors.js';
|
|
10
|
+
/**
|
|
11
|
+
* Queue statistics interface
|
|
12
|
+
*/
|
|
13
|
+
function normalizeStoragePrefix(prefixArg = '/email/queue/') {
|
|
14
|
+
if (!prefixArg.startsWith('/') ||
|
|
15
|
+
!prefixArg.endsWith('/') ||
|
|
16
|
+
prefixArg.includes('\\') ||
|
|
17
|
+
prefixArg.includes('\0')) {
|
|
18
|
+
throw new Error('Queue storagePrefix must be an absolute managed-storage prefix');
|
|
19
|
+
}
|
|
20
|
+
const segments = prefixArg.slice(1, -1).split('/');
|
|
21
|
+
if (segments.some((segment) => !segment || segment === '.' || segment === '..')) {
|
|
22
|
+
throw new Error('Queue storagePrefix contains an invalid path segment');
|
|
23
|
+
}
|
|
24
|
+
return prefixArg;
|
|
25
|
+
}
|
|
26
|
+
const managedQueueOwners = new WeakMap();
|
|
7
27
|
/**
|
|
8
28
|
* A unified queue for all email modes
|
|
9
29
|
*/
|
|
@@ -15,16 +35,24 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
15
35
|
stats;
|
|
16
36
|
processing = false;
|
|
17
37
|
totalProcessed = 0;
|
|
38
|
+
ownsManagedPrefix = false;
|
|
39
|
+
lifecycleState = 'new';
|
|
18
40
|
/**
|
|
19
41
|
* Create a new unified delivery queue
|
|
20
42
|
* @param options Queue options
|
|
21
43
|
*/
|
|
22
44
|
constructor(options) {
|
|
23
45
|
super();
|
|
24
|
-
|
|
46
|
+
if (options.storageMode === 'managed' && !options.storageManager) {
|
|
47
|
+
throw new Error('Managed queue storage requires an IBlobStorageManager');
|
|
48
|
+
}
|
|
49
|
+
if (options.storageMode === 'memory' && options.storageManager) {
|
|
50
|
+
throw new Error('Memory-only queue storage cannot receive an IBlobStorageManager');
|
|
51
|
+
}
|
|
25
52
|
this.options = {
|
|
26
|
-
|
|
27
|
-
|
|
53
|
+
storageMode: options.storageMode,
|
|
54
|
+
storageManager: options.storageManager,
|
|
55
|
+
storagePrefix: normalizeStoragePrefix(options.storagePrefix),
|
|
28
56
|
checkInterval: options.checkInterval || 30000, // 30 seconds
|
|
29
57
|
maxQueueSize: options.maxQueueSize || 10000,
|
|
30
58
|
maxPerDestination: options.maxPerDestination || 100,
|
|
@@ -52,27 +80,90 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
52
80
|
processingActive: false
|
|
53
81
|
};
|
|
54
82
|
}
|
|
83
|
+
assertMutable() {
|
|
84
|
+
if (this.lifecycleState === 'shutting-down' || this.lifecycleState === 'closed') {
|
|
85
|
+
throw new Error(`Delivery queue is ${this.lifecycleState}; mutations are no longer allowed`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
createInitialRecipientStates(email) {
|
|
89
|
+
const byRecipient = new Map();
|
|
90
|
+
const now = new Date();
|
|
91
|
+
for (const recipient of email.getAllRecipients()) {
|
|
92
|
+
const normalizedRecipient = recipient.trim().toLowerCase();
|
|
93
|
+
if (!normalizedRecipient || byRecipient.has(normalizedRecipient))
|
|
94
|
+
continue;
|
|
95
|
+
byRecipient.set(normalizedRecipient, {
|
|
96
|
+
recipient,
|
|
97
|
+
normalizedRecipient,
|
|
98
|
+
state: 'unresolved',
|
|
99
|
+
updatedAt: now,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return [...byRecipient.values()];
|
|
103
|
+
}
|
|
104
|
+
createBounceOperationId(itemId, normalizedRecipient) {
|
|
105
|
+
return createHash('sha256')
|
|
106
|
+
.update(itemId)
|
|
107
|
+
.update('\0')
|
|
108
|
+
.update(normalizedRecipient)
|
|
109
|
+
.update('\0smtpFailure')
|
|
110
|
+
.digest('hex');
|
|
111
|
+
}
|
|
55
112
|
/**
|
|
56
113
|
* Initialize the queue
|
|
57
114
|
*/
|
|
58
|
-
|
|
115
|
+
claimManagedPrefix() {
|
|
116
|
+
const storageManager = this.options.storageManager;
|
|
117
|
+
if (!storageManager || this.ownsManagedPrefix)
|
|
118
|
+
return;
|
|
119
|
+
let owners = managedQueueOwners.get(storageManager);
|
|
120
|
+
if (!owners) {
|
|
121
|
+
owners = new Map();
|
|
122
|
+
managedQueueOwners.set(storageManager, owners);
|
|
123
|
+
}
|
|
124
|
+
const existingOwner = owners.get(this.options.storagePrefix);
|
|
125
|
+
if (existingOwner && existingOwner !== this) {
|
|
126
|
+
throw new Error(`Managed queue prefix ${this.options.storagePrefix} already has an active delivery owner`);
|
|
127
|
+
}
|
|
128
|
+
owners.set(this.options.storagePrefix, this);
|
|
129
|
+
this.ownsManagedPrefix = true;
|
|
130
|
+
}
|
|
131
|
+
releaseManagedPrefix() {
|
|
132
|
+
const storageManager = this.options.storageManager;
|
|
133
|
+
if (!storageManager || !this.ownsManagedPrefix)
|
|
134
|
+
return;
|
|
135
|
+
const owners = managedQueueOwners.get(storageManager);
|
|
136
|
+
if (owners?.get(this.options.storagePrefix) === this) {
|
|
137
|
+
owners.delete(this.options.storagePrefix);
|
|
138
|
+
if (owners.size === 0)
|
|
139
|
+
managedQueueOwners.delete(storageManager);
|
|
140
|
+
}
|
|
141
|
+
this.ownsManagedPrefix = false;
|
|
142
|
+
}
|
|
143
|
+
async initialize(optionsArg = {}) {
|
|
59
144
|
logger.log('info', 'Initializing UnifiedDeliveryQueue');
|
|
145
|
+
if (this.lifecycleState !== 'new') {
|
|
146
|
+
throw new Error(`Delivery queue cannot initialize from ${this.lifecycleState} state`);
|
|
147
|
+
}
|
|
148
|
+
this.claimManagedPrefix();
|
|
60
149
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
150
|
+
if (this.options.storageManager) {
|
|
151
|
+
await this.loadFromStorage();
|
|
152
|
+
}
|
|
153
|
+
this.lifecycleState = 'initialized';
|
|
154
|
+
// Embedders may hydrate durable state before delivery dependencies are ready.
|
|
155
|
+
if (optionsArg.startProcessing !== false) {
|
|
156
|
+
this.startProcessing();
|
|
68
157
|
}
|
|
69
|
-
// Start the queue processing timer
|
|
70
|
-
this.startProcessing();
|
|
71
158
|
// Emit initialized event
|
|
72
|
-
this
|
|
159
|
+
await emitSafely(this, 'initialized');
|
|
73
160
|
logger.log('info', 'UnifiedDeliveryQueue initialized successfully');
|
|
74
161
|
}
|
|
75
162
|
catch (error) {
|
|
163
|
+
this.queue.clear();
|
|
164
|
+
this.updateStats();
|
|
165
|
+
this.lifecycleState = 'new';
|
|
166
|
+
this.releaseManagedPrefix();
|
|
76
167
|
logger.log('error', `Failed to initialize queue: ${error.message}`);
|
|
77
168
|
throw error;
|
|
78
169
|
}
|
|
@@ -96,7 +187,7 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
96
187
|
}, 30 * 60 * 1000);
|
|
97
188
|
this.processing = true;
|
|
98
189
|
this.stats.processingActive = true;
|
|
99
|
-
this
|
|
190
|
+
void emitSafely(this, 'processingStarted');
|
|
100
191
|
logger.log('info', 'Queue processing started');
|
|
101
192
|
}
|
|
102
193
|
/**
|
|
@@ -113,7 +204,7 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
113
204
|
}
|
|
114
205
|
this.processing = false;
|
|
115
206
|
this.stats.processingActive = false;
|
|
116
|
-
this
|
|
207
|
+
void emitSafely(this, 'processingStopped');
|
|
117
208
|
logger.log('info', 'Queue processing stopped');
|
|
118
209
|
}
|
|
119
210
|
/**
|
|
@@ -135,14 +226,14 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
135
226
|
// Sort by oldest first
|
|
136
227
|
readyItems.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
137
228
|
// Emit event for ready items
|
|
138
|
-
this
|
|
229
|
+
await emitSafely(this, 'itemsReady', readyItems);
|
|
139
230
|
logger.log('info', `Found ${readyItems.length} items ready for processing`);
|
|
140
231
|
// Update statistics
|
|
141
232
|
this.updateStats();
|
|
142
233
|
}
|
|
143
234
|
catch (error) {
|
|
144
|
-
logger.log('error', `Error processing queue: ${error
|
|
145
|
-
this
|
|
235
|
+
logger.log('error', `Error processing queue: ${getErrorMessage(error)}`);
|
|
236
|
+
await emitSafely(this, 'error', error);
|
|
146
237
|
}
|
|
147
238
|
}
|
|
148
239
|
/**
|
|
@@ -152,6 +243,10 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
152
243
|
* @param route Email route
|
|
153
244
|
*/
|
|
154
245
|
async enqueue(processingResult, mode, route) {
|
|
246
|
+
this.assertMutable();
|
|
247
|
+
if (!(processingResult instanceof Email)) {
|
|
248
|
+
throw new Error('Queue processingResult must be an Email instance');
|
|
249
|
+
}
|
|
155
250
|
// Check if queue is full
|
|
156
251
|
if (this.queue.size >= this.options.maxQueueSize) {
|
|
157
252
|
throw new Error('Queue is full');
|
|
@@ -168,18 +263,20 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
168
263
|
attempts: 0,
|
|
169
264
|
nextAttempt: new Date(),
|
|
170
265
|
createdAt: new Date(),
|
|
171
|
-
updatedAt: new Date()
|
|
266
|
+
updatedAt: new Date(),
|
|
267
|
+
deliveredRecipients: [],
|
|
268
|
+
terminalRecipients: [],
|
|
269
|
+
recipientStates: this.createInitialRecipientStates(processingResult),
|
|
270
|
+
bounceOperations: [],
|
|
271
|
+
smtpTransactions: [],
|
|
172
272
|
};
|
|
173
|
-
//
|
|
273
|
+
// Commit durable state before exposing the item in memory or emitting acceptance.
|
|
274
|
+
await this.persistItem(item);
|
|
174
275
|
this.queue.set(id, item);
|
|
175
|
-
// Persist to disk if using disk storage
|
|
176
|
-
if (this.options.storageType === 'disk') {
|
|
177
|
-
await this.persistItem(item);
|
|
178
|
-
}
|
|
179
276
|
// Update statistics
|
|
180
277
|
this.updateStats();
|
|
181
278
|
// Emit event
|
|
182
|
-
this
|
|
279
|
+
await emitSafely(this, 'itemEnqueued', item);
|
|
183
280
|
logger.log('info', `Item enqueued with ID ${id}, mode: ${mode}`);
|
|
184
281
|
return id;
|
|
185
282
|
}
|
|
@@ -191,29 +288,41 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
191
288
|
return this.queue.get(id);
|
|
192
289
|
}
|
|
193
290
|
listItems() {
|
|
194
|
-
return Array.from(this.queue.values()).map((item) => ({
|
|
291
|
+
return Array.from(this.queue.values()).map((item) => ({
|
|
292
|
+
...item,
|
|
293
|
+
deliveredRecipients: [...(item.deliveredRecipients || [])],
|
|
294
|
+
terminalRecipients: [...(item.terminalRecipients || [])],
|
|
295
|
+
recipientStates: (item.recipientStates || []).map((state) => ({ ...state })),
|
|
296
|
+
bounceOperations: (item.bounceOperations || []).map((operation) => ({ ...operation })),
|
|
297
|
+
smtpTransactions: (item.smtpTransactions || []).map((transaction) => ({
|
|
298
|
+
...transaction,
|
|
299
|
+
recipients: [...transaction.recipients],
|
|
300
|
+
recipientResults: transaction.recipientResults?.map((result) => ({ ...result })),
|
|
301
|
+
transcript: transaction.transcript.map((entry) => ({ ...entry })),
|
|
302
|
+
})),
|
|
303
|
+
}));
|
|
195
304
|
}
|
|
196
305
|
/**
|
|
197
306
|
* Mark an item as being processed
|
|
198
307
|
* @param id Item ID
|
|
199
308
|
*/
|
|
200
309
|
async markProcessing(id) {
|
|
310
|
+
this.assertMutable();
|
|
201
311
|
const item = this.queue.get(id);
|
|
202
|
-
if (!item
|
|
312
|
+
if (!item
|
|
313
|
+
|| !(item.status === 'pending'
|
|
314
|
+
|| (item.status === 'deferred' && item.nextAttempt <= new Date()))) {
|
|
203
315
|
return false;
|
|
204
316
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (this.options.storageType === 'disk') {
|
|
211
|
-
await this.persistItem(item);
|
|
212
|
-
}
|
|
317
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
318
|
+
updatedItem.status = 'processing';
|
|
319
|
+
updatedItem.attempts++;
|
|
320
|
+
updatedItem.updatedAt = new Date();
|
|
321
|
+
});
|
|
213
322
|
// Update statistics
|
|
214
323
|
this.updateStats();
|
|
215
324
|
// Emit event
|
|
216
|
-
this
|
|
325
|
+
await emitSafely(this, 'itemProcessing', item);
|
|
217
326
|
logger.log('info', `Item ${id} marked as processing, attempt ${item.attempts}`);
|
|
218
327
|
return true;
|
|
219
328
|
}
|
|
@@ -222,23 +331,21 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
222
331
|
* @param id Item ID
|
|
223
332
|
*/
|
|
224
333
|
async markDelivered(id) {
|
|
334
|
+
this.assertMutable();
|
|
225
335
|
const item = this.queue.get(id);
|
|
226
|
-
if (!item) {
|
|
336
|
+
if (!item || item.status === 'delivered' || item.status === 'failed') {
|
|
227
337
|
return false;
|
|
228
338
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (this.options.storageType === 'disk') {
|
|
235
|
-
await this.persistItem(item);
|
|
236
|
-
}
|
|
339
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
340
|
+
updatedItem.status = 'delivered';
|
|
341
|
+
updatedItem.updatedAt = new Date();
|
|
342
|
+
updatedItem.deliveredAt = new Date();
|
|
343
|
+
});
|
|
237
344
|
// Update statistics
|
|
238
345
|
this.totalProcessed++;
|
|
239
346
|
this.updateStats();
|
|
240
347
|
// Emit event
|
|
241
|
-
this
|
|
348
|
+
await emitSafely(this, 'itemDelivered', item);
|
|
242
349
|
logger.log('info', `Item ${id} marked as delivered after ${item.attempts} attempts`);
|
|
243
350
|
return true;
|
|
244
351
|
}
|
|
@@ -247,45 +354,227 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
247
354
|
* @param id Item ID
|
|
248
355
|
* @param error Error message
|
|
249
356
|
*/
|
|
250
|
-
async markFailed(id, error) {
|
|
357
|
+
async markFailed(id, error, optionsArg = {}) {
|
|
358
|
+
return (await this.markFailedWithTransition(id, error, optionsArg)).updated;
|
|
359
|
+
}
|
|
360
|
+
/** Rich internal disposition used by the delivery system without breaking markFailed(). */
|
|
361
|
+
async markFailedWithTransition(id, error, optionsArg = {}) {
|
|
362
|
+
this.assertMutable();
|
|
251
363
|
const item = this.queue.get(id);
|
|
252
364
|
if (!item) {
|
|
253
|
-
return false;
|
|
365
|
+
return { updated: false, terminal: false };
|
|
366
|
+
}
|
|
367
|
+
if (item.status === 'delivered' || item.status === 'failed') {
|
|
368
|
+
return {
|
|
369
|
+
updated: false,
|
|
370
|
+
status: item.status === 'failed' ? 'failed' : undefined,
|
|
371
|
+
terminal: true,
|
|
372
|
+
};
|
|
254
373
|
}
|
|
255
374
|
// Determine if we should retry
|
|
256
|
-
|
|
375
|
+
const retryable = optionsArg.retryable !== false;
|
|
376
|
+
if (retryable && item.attempts < this.options.maxRetries) {
|
|
257
377
|
// Calculate next retry time with exponential backoff
|
|
258
378
|
const delay = Math.min(this.options.baseRetryDelay * Math.pow(2, item.attempts - 1), this.options.maxRetryDelay);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (this.options.storageType === 'disk') {
|
|
266
|
-
await this.persistItem(item);
|
|
267
|
-
}
|
|
379
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
380
|
+
updatedItem.status = 'deferred';
|
|
381
|
+
updatedItem.lastError = error;
|
|
382
|
+
updatedItem.nextAttempt = new Date(Date.now() + delay);
|
|
383
|
+
updatedItem.updatedAt = new Date();
|
|
384
|
+
});
|
|
268
385
|
// Emit event
|
|
269
|
-
this
|
|
386
|
+
await emitSafely(this, 'itemDeferred', item);
|
|
270
387
|
logger.log('info', `Item ${id} deferred for ${delay}ms, attempt ${item.attempts}, error: ${error}`);
|
|
388
|
+
this.updateStats();
|
|
389
|
+
return { updated: true, status: 'deferred', terminal: false };
|
|
271
390
|
}
|
|
272
391
|
else {
|
|
273
392
|
// Mark as permanently failed
|
|
274
|
-
item
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
await this.persistItem(item);
|
|
280
|
-
}
|
|
393
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
394
|
+
updatedItem.status = 'failed';
|
|
395
|
+
updatedItem.lastError = error;
|
|
396
|
+
updatedItem.updatedAt = new Date();
|
|
397
|
+
});
|
|
281
398
|
// Update statistics
|
|
282
399
|
this.totalProcessed++;
|
|
283
400
|
// Emit event
|
|
284
|
-
this
|
|
401
|
+
await emitSafely(this, 'itemFailed', item);
|
|
285
402
|
logger.log('warn', `Item ${id} permanently failed after ${item.attempts} attempts, error: ${error}`);
|
|
286
403
|
}
|
|
287
|
-
// Update statistics
|
|
288
404
|
this.updateStats();
|
|
405
|
+
return {
|
|
406
|
+
updated: true,
|
|
407
|
+
status: 'failed',
|
|
408
|
+
terminal: true,
|
|
409
|
+
terminalReason: retryable ? 'retry_exhausted' : 'permanent',
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/** Persist a completed SMTP attempt before any queue status event is emitted. */
|
|
413
|
+
async appendSmtpTransaction(id, transaction) {
|
|
414
|
+
this.assertMutable();
|
|
415
|
+
const item = this.queue.get(id);
|
|
416
|
+
if (!item)
|
|
417
|
+
return false;
|
|
418
|
+
const normalizedTransaction = {
|
|
419
|
+
...transaction,
|
|
420
|
+
queueItemId: id,
|
|
421
|
+
recipients: [...transaction.recipients],
|
|
422
|
+
recipientResults: transaction.recipientResults?.map((result) => ({ ...result })),
|
|
423
|
+
transcript: normalizeSmtpTranscript(transaction.transcript),
|
|
424
|
+
};
|
|
425
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
426
|
+
updatedItem.smtpTransactions = [
|
|
427
|
+
...(updatedItem.smtpTransactions || []),
|
|
428
|
+
normalizedTransaction,
|
|
429
|
+
].slice(-20);
|
|
430
|
+
updatedItem.updatedAt = new Date();
|
|
431
|
+
});
|
|
432
|
+
await emitSafely(this, 'smtpTransaction', item, normalizedTransaction);
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
/** Record recipients accepted after the SMTP final-response 250 checkpoint. */
|
|
436
|
+
async markRecipientsDelivered(id, recipients) {
|
|
437
|
+
this.assertMutable();
|
|
438
|
+
const item = this.queue.get(id);
|
|
439
|
+
if (!item)
|
|
440
|
+
return false;
|
|
441
|
+
const normalizedRecipients = new Set(recipients.map((recipient) => recipient.trim().toLowerCase()).filter(Boolean));
|
|
442
|
+
if (normalizedRecipients.size === 0)
|
|
443
|
+
return false;
|
|
444
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
445
|
+
const states = updatedItem.recipientStates || this.createInitialRecipientStates(updatedItem.processingResult);
|
|
446
|
+
const delivered = new Set(updatedItem.deliveredRecipients || []);
|
|
447
|
+
const now = new Date();
|
|
448
|
+
for (const state of states) {
|
|
449
|
+
if (normalizedRecipients.has(state.normalizedRecipient)
|
|
450
|
+
&& state.state === 'unresolved') {
|
|
451
|
+
state.state = 'delivered';
|
|
452
|
+
state.updatedAt = now;
|
|
453
|
+
delete state.smtpCode;
|
|
454
|
+
delete state.smtpResponse;
|
|
455
|
+
delivered.add(state.normalizedRecipient);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
updatedItem.recipientStates = states;
|
|
459
|
+
updatedItem.deliveredRecipients = [...delivered];
|
|
460
|
+
updatedItem.updatedAt = now;
|
|
461
|
+
});
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Atomically checkpoint permanent recipient failures together with their
|
|
466
|
+
* durable bounce work. This is the sole 5xx recipient transition.
|
|
467
|
+
*/
|
|
468
|
+
async markRecipientsTerminal(id, failures) {
|
|
469
|
+
this.assertMutable();
|
|
470
|
+
const item = this.queue.get(id);
|
|
471
|
+
if (!item || failures.length === 0)
|
|
472
|
+
return [];
|
|
473
|
+
const normalizedFailures = failures.map((failure) => (typeof failure === 'string'
|
|
474
|
+
? {
|
|
475
|
+
recipient: failure,
|
|
476
|
+
smtpCode: 550,
|
|
477
|
+
smtpResponse: 'SMTP recipient permanently rejected',
|
|
478
|
+
}
|
|
479
|
+
: failure));
|
|
480
|
+
const newlyTerminal = [];
|
|
481
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
482
|
+
const states = updatedItem.recipientStates || this.createInitialRecipientStates(updatedItem.processingResult);
|
|
483
|
+
const terminal = new Set(updatedItem.terminalRecipients || []);
|
|
484
|
+
const operations = updatedItem.bounceOperations || [];
|
|
485
|
+
const operationIds = new Set(operations.map((operation) => operation.operationId));
|
|
486
|
+
const now = new Date();
|
|
487
|
+
for (const failure of normalizedFailures) {
|
|
488
|
+
const normalizedRecipient = failure.recipient.trim().toLowerCase();
|
|
489
|
+
const state = states.find((candidate) => candidate.normalizedRecipient === normalizedRecipient);
|
|
490
|
+
if (!state || state.state !== 'unresolved')
|
|
491
|
+
continue;
|
|
492
|
+
state.state = 'permanentFailure';
|
|
493
|
+
state.smtpCode = failure.smtpCode;
|
|
494
|
+
state.smtpResponse = failure.smtpResponse;
|
|
495
|
+
state.updatedAt = now;
|
|
496
|
+
terminal.add(normalizedRecipient);
|
|
497
|
+
newlyTerminal.push(state.recipient);
|
|
498
|
+
const operationId = this.createBounceOperationId(updatedItem.id, normalizedRecipient);
|
|
499
|
+
if (!operationIds.has(operationId)) {
|
|
500
|
+
operations.push({
|
|
501
|
+
operationId,
|
|
502
|
+
kind: 'smtpFailure',
|
|
503
|
+
recipient: state.recipient,
|
|
504
|
+
normalizedRecipient,
|
|
505
|
+
smtpCode: failure.smtpCode,
|
|
506
|
+
smtpResponse: failure.smtpResponse,
|
|
507
|
+
state: 'pending',
|
|
508
|
+
attempts: 0,
|
|
509
|
+
nextAttempt: now,
|
|
510
|
+
});
|
|
511
|
+
operationIds.add(operationId);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
updatedItem.recipientStates = states;
|
|
515
|
+
updatedItem.terminalRecipients = [...terminal];
|
|
516
|
+
updatedItem.bounceOperations = operations;
|
|
517
|
+
updatedItem.updatedAt = now;
|
|
518
|
+
});
|
|
519
|
+
return newlyTerminal;
|
|
520
|
+
}
|
|
521
|
+
getRecipientDisposition(id) {
|
|
522
|
+
const item = this.queue.get(id);
|
|
523
|
+
if (!item)
|
|
524
|
+
return { unresolved: [], delivered: [], permanentFailures: [] };
|
|
525
|
+
const states = item.recipientStates || this.createInitialRecipientStates(item.processingResult);
|
|
526
|
+
return {
|
|
527
|
+
unresolved: states.filter((state) => state.state === 'unresolved').map((state) => state.recipient),
|
|
528
|
+
delivered: states.filter((state) => state.state === 'delivered').map((state) => state.recipient),
|
|
529
|
+
permanentFailures: states
|
|
530
|
+
.filter((state) => state.state === 'permanentFailure')
|
|
531
|
+
.map((state) => state.recipient),
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/** Includes terminal queue items because bounce work outlives delivery status. */
|
|
535
|
+
listPendingBounceOperations(now = new Date()) {
|
|
536
|
+
const result = [];
|
|
537
|
+
for (const item of this.queue.values()) {
|
|
538
|
+
for (const operation of item.bounceOperations || []) {
|
|
539
|
+
if (operation.state === 'pending' && operation.nextAttempt <= now) {
|
|
540
|
+
result.push({ itemId: item.id, operation: { ...operation } });
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return result;
|
|
545
|
+
}
|
|
546
|
+
async markBounceOperationCompleted(itemId, operationId) {
|
|
547
|
+
this.assertMutable();
|
|
548
|
+
const item = this.queue.get(itemId);
|
|
549
|
+
const operation = item?.bounceOperations?.find((candidate) => candidate.operationId === operationId);
|
|
550
|
+
if (!item || !operation || operation.state === 'completed')
|
|
551
|
+
return false;
|
|
552
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
553
|
+
const updatedOperation = updatedItem.bounceOperations?.find((candidate) => candidate.operationId === operationId);
|
|
554
|
+
if (!updatedOperation)
|
|
555
|
+
return;
|
|
556
|
+
updatedOperation.state = 'completed';
|
|
557
|
+
updatedOperation.completedAt = new Date();
|
|
558
|
+
delete updatedOperation.lastError;
|
|
559
|
+
updatedItem.updatedAt = new Date();
|
|
560
|
+
});
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
async markBounceOperationFailed(itemId, operationId, error) {
|
|
564
|
+
this.assertMutable();
|
|
565
|
+
const item = this.queue.get(itemId);
|
|
566
|
+
const operation = item?.bounceOperations?.find((candidate) => candidate.operationId === operationId);
|
|
567
|
+
if (!item || !operation || operation.state === 'completed')
|
|
568
|
+
return false;
|
|
569
|
+
await this.applyPersistedMutation(item, (updatedItem) => {
|
|
570
|
+
const updatedOperation = updatedItem.bounceOperations?.find((candidate) => candidate.operationId === operationId);
|
|
571
|
+
if (!updatedOperation)
|
|
572
|
+
return;
|
|
573
|
+
updatedOperation.attempts++;
|
|
574
|
+
updatedOperation.lastError = error;
|
|
575
|
+
updatedOperation.nextAttempt = new Date(Date.now() + Math.min(60_000 * (2 ** Math.max(0, updatedOperation.attempts - 1)), 3_600_000));
|
|
576
|
+
updatedItem.updatedAt = new Date();
|
|
577
|
+
});
|
|
289
578
|
return true;
|
|
290
579
|
}
|
|
291
580
|
/**
|
|
@@ -293,92 +582,375 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
293
582
|
* @param id Item ID
|
|
294
583
|
*/
|
|
295
584
|
async removeItem(id) {
|
|
585
|
+
this.assertMutable();
|
|
296
586
|
const item = this.queue.get(id);
|
|
297
587
|
if (!item) {
|
|
298
588
|
return false;
|
|
299
589
|
}
|
|
300
|
-
//
|
|
590
|
+
// Delete durable state before making the removal visible in memory.
|
|
591
|
+
await this.removeItemFromStorage(id);
|
|
301
592
|
this.queue.delete(id);
|
|
302
|
-
// Remove from disk if using disk storage
|
|
303
|
-
if (this.options.storageType === 'disk') {
|
|
304
|
-
await this.removeItemFromDisk(id);
|
|
305
|
-
}
|
|
306
593
|
// Update statistics
|
|
307
594
|
this.updateStats();
|
|
308
595
|
// Emit event
|
|
309
|
-
this
|
|
596
|
+
await emitSafely(this, 'itemRemoved', item);
|
|
310
597
|
logger.log('info', `Item ${id} removed from queue`);
|
|
311
598
|
return true;
|
|
312
599
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
*/
|
|
600
|
+
storageKey(id) {
|
|
601
|
+
return `${this.options.storagePrefix}${id}.json`;
|
|
602
|
+
}
|
|
317
603
|
async persistItem(item) {
|
|
604
|
+
if (!this.options.storageManager)
|
|
605
|
+
return;
|
|
606
|
+
await this.options.storageManager.set(this.storageKey(item.id), serialize(this.serializeItem(item)));
|
|
607
|
+
}
|
|
608
|
+
serializeItem(item) {
|
|
609
|
+
return {
|
|
610
|
+
schemaVersion: 2,
|
|
611
|
+
id: item.id,
|
|
612
|
+
processingMode: item.processingMode,
|
|
613
|
+
processingResult: {
|
|
614
|
+
options: item.processingResult.toEmailOptions(),
|
|
615
|
+
messageId: item.processingResult.getMessageId(),
|
|
616
|
+
envelopeFrom: item.processingResult.getEnvelopeFrom(),
|
|
617
|
+
},
|
|
618
|
+
...(item.route ? { route: item.route } : {}),
|
|
619
|
+
status: item.status,
|
|
620
|
+
attempts: item.attempts,
|
|
621
|
+
nextAttempt: item.nextAttempt.getTime(),
|
|
622
|
+
...(item.lastError !== undefined ? { lastError: item.lastError } : {}),
|
|
623
|
+
createdAt: item.createdAt.getTime(),
|
|
624
|
+
updatedAt: item.updatedAt.getTime(),
|
|
625
|
+
...(item.deliveredAt ? { deliveredAt: item.deliveredAt.getTime() } : {}),
|
|
626
|
+
deliveredRecipients: item.deliveredRecipients || [],
|
|
627
|
+
terminalRecipients: item.terminalRecipients || [],
|
|
628
|
+
recipientStates: (item.recipientStates || this.createInitialRecipientStates(item.processingResult)).map((state) => ({
|
|
629
|
+
...state,
|
|
630
|
+
updatedAt: state.updatedAt.getTime(),
|
|
631
|
+
})),
|
|
632
|
+
bounceOperations: (item.bounceOperations || []).map((operation) => {
|
|
633
|
+
const { nextAttempt, completedAt, ...storedOperation } = operation;
|
|
634
|
+
return {
|
|
635
|
+
...storedOperation,
|
|
636
|
+
nextAttempt: nextAttempt.getTime(),
|
|
637
|
+
...(completedAt ? { completedAt: completedAt.getTime() } : {}),
|
|
638
|
+
};
|
|
639
|
+
}),
|
|
640
|
+
smtpTransactions: (item.smtpTransactions || []).slice(-20).map((transaction) => ({
|
|
641
|
+
...transaction,
|
|
642
|
+
queueItemId: item.id,
|
|
643
|
+
recipients: [...transaction.recipients],
|
|
644
|
+
recipientResults: transaction.recipientResults?.map((result) => ({ ...result })),
|
|
645
|
+
transcript: normalizeSmtpTranscript(transaction.transcript),
|
|
646
|
+
})),
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
async applyPersistedMutation(item, mutation) {
|
|
650
|
+
this.assertMutable();
|
|
651
|
+
const updatedItem = {
|
|
652
|
+
...item,
|
|
653
|
+
deliveredRecipients: [...(item.deliveredRecipients || [])],
|
|
654
|
+
terminalRecipients: [...(item.terminalRecipients || [])],
|
|
655
|
+
recipientStates: (item.recipientStates || []).map((state) => ({ ...state })),
|
|
656
|
+
bounceOperations: (item.bounceOperations || []).map((operation) => ({ ...operation })),
|
|
657
|
+
smtpTransactions: [...(item.smtpTransactions || [])],
|
|
658
|
+
};
|
|
659
|
+
mutation(updatedItem);
|
|
660
|
+
await this.persistItem(updatedItem);
|
|
661
|
+
Object.assign(item, updatedItem);
|
|
662
|
+
}
|
|
663
|
+
async removeItemFromStorage(id) {
|
|
664
|
+
await this.options.storageManager?.delete(this.storageKey(id));
|
|
665
|
+
}
|
|
666
|
+
deserializeItem(key, data) {
|
|
667
|
+
let parsed;
|
|
318
668
|
try {
|
|
319
|
-
|
|
320
|
-
await fs.promises.writeFile(filePath, JSON.stringify(item, null, 2), 'utf8');
|
|
669
|
+
parsed = deserialize(data);
|
|
321
670
|
}
|
|
322
671
|
catch (error) {
|
|
323
|
-
|
|
324
|
-
this.emit('error', error);
|
|
672
|
+
throw new Error(`Invalid managed queue item at ${key}: ${getErrorMessage(error)}`);
|
|
325
673
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
674
|
+
if (!parsed || typeof parsed !== 'object' || typeof parsed.id !== 'string' || !parsed.id) {
|
|
675
|
+
throw new Error(`Invalid managed queue item at ${key}: missing id`);
|
|
676
|
+
}
|
|
677
|
+
if (parsed.schemaVersion !== 1 && parsed.schemaVersion !== 2) {
|
|
678
|
+
throw new Error(`Invalid managed queue item at ${key}: unsupported schema version`);
|
|
679
|
+
}
|
|
680
|
+
if (this.storageKey(parsed.id) !== key) {
|
|
681
|
+
throw new Error(`Invalid managed queue item at ${key}: id does not match object key`);
|
|
682
|
+
}
|
|
683
|
+
if (!['pending', 'processing', 'delivered', 'failed', 'deferred'].includes(parsed.status)) {
|
|
684
|
+
throw new Error(`Invalid managed queue item at ${key}: unsupported status`);
|
|
685
|
+
}
|
|
686
|
+
if (!['forward', 'mta', 'process'].includes(parsed.processingMode)) {
|
|
687
|
+
throw new Error(`Invalid managed queue item at ${key}: unsupported processing mode`);
|
|
688
|
+
}
|
|
689
|
+
if (!Number.isInteger(parsed.attempts) || parsed.attempts < 0) {
|
|
690
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid attempt count`);
|
|
691
|
+
}
|
|
692
|
+
if (parsed.deliveredRecipients !== undefined
|
|
693
|
+
&& (!Array.isArray(parsed.deliveredRecipients)
|
|
694
|
+
|| parsed.deliveredRecipients.some((value) => typeof value !== 'string'))) {
|
|
695
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid delivered recipients`);
|
|
696
|
+
}
|
|
697
|
+
if (parsed.terminalRecipients !== undefined
|
|
698
|
+
&& (!Array.isArray(parsed.terminalRecipients)
|
|
699
|
+
|| parsed.terminalRecipients.some((value) => typeof value !== 'string'))) {
|
|
700
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid terminal recipients`);
|
|
701
|
+
}
|
|
702
|
+
if (parsed.schemaVersion === 2) {
|
|
703
|
+
if (!Array.isArray(parsed.recipientStates)
|
|
704
|
+
|| parsed.recipientStates.some((value) => {
|
|
705
|
+
if (!value || typeof value !== 'object')
|
|
706
|
+
return true;
|
|
707
|
+
const state = value;
|
|
708
|
+
return !(typeof state.recipient === 'string'
|
|
709
|
+
&& typeof state.normalizedRecipient === 'string'
|
|
710
|
+
&& state.normalizedRecipient === state.recipient.trim().toLowerCase()
|
|
711
|
+
&& ['unresolved', 'delivered', 'permanentFailure'].includes(state.state)
|
|
712
|
+
&& Number.isFinite(state.updatedAt)
|
|
713
|
+
&& (state.smtpCode === undefined || Number.isInteger(state.smtpCode))
|
|
714
|
+
&& (state.smtpResponse === undefined || typeof state.smtpResponse === 'string'));
|
|
715
|
+
})) {
|
|
716
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid recipient states`);
|
|
717
|
+
}
|
|
718
|
+
if (!Array.isArray(parsed.bounceOperations)
|
|
719
|
+
|| parsed.bounceOperations.some((value) => {
|
|
720
|
+
if (!value || typeof value !== 'object')
|
|
721
|
+
return true;
|
|
722
|
+
const operation = value;
|
|
723
|
+
return !(typeof operation.operationId === 'string'
|
|
724
|
+
&& operation.operationId.length > 0
|
|
725
|
+
&& operation.kind === 'smtpFailure'
|
|
726
|
+
&& typeof operation.recipient === 'string'
|
|
727
|
+
&& typeof operation.normalizedRecipient === 'string'
|
|
728
|
+
&& operation.normalizedRecipient === operation.recipient.trim().toLowerCase()
|
|
729
|
+
&& Number.isInteger(operation.smtpCode)
|
|
730
|
+
&& operation.smtpCode >= 500
|
|
731
|
+
&& typeof operation.smtpResponse === 'string'
|
|
732
|
+
&& ['pending', 'completed'].includes(operation.state)
|
|
733
|
+
&& Number.isInteger(operation.attempts)
|
|
734
|
+
&& operation.attempts >= 0
|
|
735
|
+
&& Number.isFinite(operation.nextAttempt)
|
|
736
|
+
&& (operation.lastError === undefined || typeof operation.lastError === 'string')
|
|
737
|
+
&& (operation.completedAt === undefined || Number.isFinite(operation.completedAt)));
|
|
738
|
+
})) {
|
|
739
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid bounce operations`);
|
|
336
740
|
}
|
|
337
741
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
742
|
+
const deliveryPhases = new Set([
|
|
743
|
+
'connect',
|
|
744
|
+
'greeting',
|
|
745
|
+
'ehlo',
|
|
746
|
+
'starttls',
|
|
747
|
+
'tls_handshake',
|
|
748
|
+
'post_tls_ehlo',
|
|
749
|
+
'auth',
|
|
750
|
+
'mail_from',
|
|
751
|
+
'rcpt_to',
|
|
752
|
+
'data_command',
|
|
753
|
+
'message_body',
|
|
754
|
+
'final_response',
|
|
755
|
+
'rset',
|
|
756
|
+
'quit',
|
|
757
|
+
'unknown',
|
|
758
|
+
]);
|
|
759
|
+
const isValidTimestamp = (value) => (typeof value === 'string' && Number.isFinite(Date.parse(value)));
|
|
760
|
+
const isValidTranscriptEntry = (value) => {
|
|
761
|
+
if (!value || typeof value !== 'object')
|
|
762
|
+
return false;
|
|
763
|
+
const entry = value;
|
|
764
|
+
return (typeof entry.timestampMs === 'number'
|
|
765
|
+
&& Number.isFinite(entry.timestampMs)
|
|
766
|
+
&& deliveryPhases.has(entry.phase)
|
|
767
|
+
&& ['client', 'server', 'system'].includes(entry.direction)
|
|
768
|
+
&& typeof entry.text === 'string'
|
|
769
|
+
&& [...entry.text].length <= SMTP_TRANSCRIPT_MAX_ENTRY_CODE_POINTS
|
|
770
|
+
&& (entry.responseCode === undefined
|
|
771
|
+
|| (Number.isInteger(entry.responseCode) && entry.responseCode >= 100)));
|
|
772
|
+
};
|
|
773
|
+
const isValidTransaction = (value) => {
|
|
774
|
+
if (!value || typeof value !== 'object')
|
|
775
|
+
return false;
|
|
776
|
+
const transaction = value;
|
|
777
|
+
return (typeof transaction.id === 'string'
|
|
778
|
+
&& transaction.id.length > 0
|
|
779
|
+
&& transaction.queueItemId === parsed.id
|
|
780
|
+
&& Number.isInteger(transaction.queueAttempt)
|
|
781
|
+
&& transaction.queueAttempt >= 0
|
|
782
|
+
&& typeof transaction.targetHost === 'string'
|
|
783
|
+
&& transaction.targetHost.length > 0
|
|
784
|
+
&& Number.isInteger(transaction.targetPort)
|
|
785
|
+
&& transaction.targetPort >= 1
|
|
786
|
+
&& transaction.targetPort <= 65_535
|
|
787
|
+
&& (transaction.recipientDomain === undefined
|
|
788
|
+
|| typeof transaction.recipientDomain === 'string')
|
|
789
|
+
&& Array.isArray(transaction.recipients)
|
|
790
|
+
&& transaction.recipients.every((recipient) => typeof recipient === 'string')
|
|
791
|
+
&& isValidTimestamp(transaction.startedAt)
|
|
792
|
+
&& isValidTimestamp(transaction.completedAt)
|
|
793
|
+
&& typeof transaction.durationMs === 'number'
|
|
794
|
+
&& Number.isFinite(transaction.durationMs)
|
|
795
|
+
&& transaction.durationMs >= 0
|
|
796
|
+
&& ['succeeded', 'failed'].includes(transaction.outcome)
|
|
797
|
+
&& typeof transaction.retryable === 'boolean'
|
|
798
|
+
&& (transaction.errorType === undefined || typeof transaction.errorType === 'string')
|
|
799
|
+
&& (transaction.smtpCode === undefined || Number.isInteger(transaction.smtpCode))
|
|
800
|
+
&& (transaction.recipientResults === undefined
|
|
801
|
+
|| (Array.isArray(transaction.recipientResults)
|
|
802
|
+
&& transaction.recipientResults.every((value) => {
|
|
803
|
+
if (!value || typeof value !== 'object')
|
|
804
|
+
return false;
|
|
805
|
+
const result = value;
|
|
806
|
+
return (typeof result.recipient === 'string'
|
|
807
|
+
&& typeof result.accepted === 'boolean'
|
|
808
|
+
&& Number.isInteger(result.responseCode));
|
|
809
|
+
})))
|
|
810
|
+
&& (transaction.failurePhase === undefined || deliveryPhases.has(transaction.failurePhase))
|
|
811
|
+
&& (transaction.error === undefined || typeof transaction.error === 'string')
|
|
812
|
+
&& Array.isArray(transaction.transcript)
|
|
813
|
+
&& transaction.transcript.length <= SMTP_TRANSCRIPT_MAX_ENTRIES
|
|
814
|
+
&& transaction.transcript.every(isValidTranscriptEntry)
|
|
815
|
+
&& transaction.transcript.reduce((sum, entry) => sum + Buffer.byteLength(entry.text, 'utf8'), 0) <= SMTP_TRANSCRIPT_MAX_UTF8_BYTES);
|
|
816
|
+
};
|
|
817
|
+
if (parsed.smtpTransactions !== undefined
|
|
818
|
+
&& (!Array.isArray(parsed.smtpTransactions)
|
|
819
|
+
|| parsed.smtpTransactions.length > 20
|
|
820
|
+
|| parsed.smtpTransactions.some((value) => !isValidTransaction(value)))) {
|
|
821
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid SMTP transactions`);
|
|
341
822
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
*/
|
|
346
|
-
async loadFromDisk() {
|
|
347
|
-
try {
|
|
348
|
-
// Check if directory exists
|
|
349
|
-
if (!fs.existsSync(this.options.persistentPath)) {
|
|
350
|
-
return;
|
|
823
|
+
const parseDate = (value, field) => {
|
|
824
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
825
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid ${field}`);
|
|
351
826
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
logger.log('error', `Failed to load item from ${file}: ${error.message}`);
|
|
827
|
+
return new Date(value);
|
|
828
|
+
};
|
|
829
|
+
if (!parsed.processingResult ||
|
|
830
|
+
typeof parsed.processingResult !== 'object' ||
|
|
831
|
+
!parsed.processingResult.options ||
|
|
832
|
+
typeof parsed.processingResult.options !== 'object' ||
|
|
833
|
+
typeof parsed.processingResult.messageId !== 'string' ||
|
|
834
|
+
!parsed.processingResult.messageId ||
|
|
835
|
+
typeof parsed.processingResult.envelopeFrom !== 'string') {
|
|
836
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid email payload`);
|
|
837
|
+
}
|
|
838
|
+
const storedOptions = parsed.processingResult.options;
|
|
839
|
+
if (storedOptions.attachments !== undefined) {
|
|
840
|
+
if (!Array.isArray(storedOptions.attachments)) {
|
|
841
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid attachments`);
|
|
842
|
+
}
|
|
843
|
+
for (const attachment of storedOptions.attachments) {
|
|
844
|
+
if (!attachment || typeof attachment !== 'object' || !Buffer.isBuffer(attachment.content)) {
|
|
845
|
+
throw new Error(`Invalid managed queue item at ${key}: invalid attachment content`);
|
|
372
846
|
}
|
|
373
847
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
848
|
+
}
|
|
849
|
+
let processingResult;
|
|
850
|
+
try {
|
|
851
|
+
processingResult = new Email(storedOptions)
|
|
852
|
+
.setMessageId(parsed.processingResult.messageId)
|
|
853
|
+
.setEnvelopeFrom(parsed.processingResult.envelopeFrom);
|
|
377
854
|
}
|
|
378
855
|
catch (error) {
|
|
379
|
-
|
|
380
|
-
throw error;
|
|
856
|
+
throw new Error(`Invalid managed queue item at ${key}: ${getErrorMessage(error)}`);
|
|
381
857
|
}
|
|
858
|
+
let recipientStates;
|
|
859
|
+
let bounceOperations;
|
|
860
|
+
if (parsed.schemaVersion === 2) {
|
|
861
|
+
recipientStates = parsed.recipientStates.map((state) => ({
|
|
862
|
+
...state,
|
|
863
|
+
updatedAt: parseDate(state.updatedAt, 'recipient state updatedAt'),
|
|
864
|
+
}));
|
|
865
|
+
bounceOperations = parsed.bounceOperations.map((operation) => ({
|
|
866
|
+
...operation,
|
|
867
|
+
nextAttempt: parseDate(operation.nextAttempt, 'bounce operation nextAttempt'),
|
|
868
|
+
...(operation.completedAt !== undefined
|
|
869
|
+
? { completedAt: parseDate(operation.completedAt, 'bounce operation completedAt') }
|
|
870
|
+
: {}),
|
|
871
|
+
}));
|
|
872
|
+
}
|
|
873
|
+
else {
|
|
874
|
+
// V1 hydration deliberately starts with an empty outbox. Bounce work is
|
|
875
|
+
// never synthesized retroactively without a durable recipient transition.
|
|
876
|
+
recipientStates = this.createInitialRecipientStates(processingResult);
|
|
877
|
+
const delivered = new Set((parsed.deliveredRecipients || []).map((recipient) => recipient.toLowerCase()));
|
|
878
|
+
const terminal = new Set((parsed.terminalRecipients || []).map((recipient) => recipient.toLowerCase()));
|
|
879
|
+
for (const state of recipientStates) {
|
|
880
|
+
if (delivered.has(state.normalizedRecipient))
|
|
881
|
+
state.state = 'delivered';
|
|
882
|
+
else if (terminal.has(state.normalizedRecipient))
|
|
883
|
+
state.state = 'permanentFailure';
|
|
884
|
+
}
|
|
885
|
+
bounceOperations = [];
|
|
886
|
+
}
|
|
887
|
+
return {
|
|
888
|
+
id: parsed.id,
|
|
889
|
+
processingMode: parsed.processingMode,
|
|
890
|
+
processingResult,
|
|
891
|
+
...(parsed.route ? { route: parsed.route } : {}),
|
|
892
|
+
status: parsed.status,
|
|
893
|
+
attempts: parsed.attempts,
|
|
894
|
+
...(typeof parsed.lastError === 'string' ? { lastError: parsed.lastError } : {}),
|
|
895
|
+
createdAt: parseDate(parsed.createdAt, 'createdAt'),
|
|
896
|
+
updatedAt: parseDate(parsed.updatedAt, 'updatedAt'),
|
|
897
|
+
nextAttempt: parseDate(parsed.nextAttempt, 'nextAttempt'),
|
|
898
|
+
...(parsed.deliveredAt
|
|
899
|
+
? { deliveredAt: parseDate(parsed.deliveredAt, 'deliveredAt') }
|
|
900
|
+
: {}),
|
|
901
|
+
deliveredRecipients: Array.isArray(parsed.deliveredRecipients)
|
|
902
|
+
? [...parsed.deliveredRecipients]
|
|
903
|
+
: [],
|
|
904
|
+
terminalRecipients: Array.isArray(parsed.terminalRecipients)
|
|
905
|
+
? [...parsed.terminalRecipients]
|
|
906
|
+
: [],
|
|
907
|
+
recipientStates,
|
|
908
|
+
bounceOperations,
|
|
909
|
+
smtpTransactions: Array.isArray(parsed.smtpTransactions)
|
|
910
|
+
? parsed.smtpTransactions.slice(-20).map((transaction) => ({
|
|
911
|
+
...transaction,
|
|
912
|
+
recipients: [...transaction.recipients],
|
|
913
|
+
recipientResults: transaction.recipientResults?.map((result) => ({ ...result })),
|
|
914
|
+
transcript: normalizeSmtpTranscript(transaction.transcript),
|
|
915
|
+
}))
|
|
916
|
+
: [],
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
async loadFromStorage() {
|
|
920
|
+
const storageManager = this.options.storageManager;
|
|
921
|
+
if (!storageManager)
|
|
922
|
+
return;
|
|
923
|
+
const keys = (await storageManager.list(this.options.storagePrefix)).sort();
|
|
924
|
+
const recoveredItems = [];
|
|
925
|
+
for (const key of keys) {
|
|
926
|
+
if (!key.startsWith(this.options.storagePrefix)) {
|
|
927
|
+
throw new Error(`Blob storage returned a queue key outside ${this.options.storagePrefix}: ${key}`);
|
|
928
|
+
}
|
|
929
|
+
if (!key.endsWith('.json'))
|
|
930
|
+
continue;
|
|
931
|
+
const data = await storageManager.get(key);
|
|
932
|
+
if (!data) {
|
|
933
|
+
throw new Error(`Managed queue item disappeared while loading: ${key}`);
|
|
934
|
+
}
|
|
935
|
+
const item = this.deserializeItem(key, data);
|
|
936
|
+
if (this.queue.has(item.id)) {
|
|
937
|
+
throw new Error(`Duplicate managed queue item id: ${item.id}`);
|
|
938
|
+
}
|
|
939
|
+
if (this.queue.size >= this.options.maxQueueSize) {
|
|
940
|
+
throw new Error(`Managed queue contains more than ${this.options.maxQueueSize} items`);
|
|
941
|
+
}
|
|
942
|
+
if (item.status === 'processing') {
|
|
943
|
+
item.status = 'deferred';
|
|
944
|
+
item.nextAttempt = new Date();
|
|
945
|
+
item.updatedAt = new Date();
|
|
946
|
+
item.lastError = 'Recovered after process restart during delivery';
|
|
947
|
+
recoveredItems.push(item);
|
|
948
|
+
}
|
|
949
|
+
this.queue.set(item.id, item);
|
|
950
|
+
}
|
|
951
|
+
await Promise.all(recoveredItems.map((item) => this.persistItem(item)));
|
|
952
|
+
this.updateStats();
|
|
953
|
+
logger.log('info', `Loaded ${this.queue.size} items from managed blob storage; recovered ${recoveredItems.length} interrupted item(s)`);
|
|
382
954
|
}
|
|
383
955
|
/**
|
|
384
956
|
* Update queue statistics
|
|
@@ -428,7 +1000,7 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
428
1000
|
// Set processing active
|
|
429
1001
|
this.stats.processingActive = this.processing;
|
|
430
1002
|
// Emit statistics event
|
|
431
|
-
this
|
|
1003
|
+
void emitSafely(this, 'statsUpdated', this.stats);
|
|
432
1004
|
}
|
|
433
1005
|
/**
|
|
434
1006
|
* Get queue statistics
|
|
@@ -440,6 +1012,7 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
440
1012
|
* Pause queue processing
|
|
441
1013
|
*/
|
|
442
1014
|
pause() {
|
|
1015
|
+
this.assertMutable();
|
|
443
1016
|
if (this.processing) {
|
|
444
1017
|
this.stopProcessing();
|
|
445
1018
|
logger.log('info', 'Queue processing paused');
|
|
@@ -449,6 +1022,7 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
449
1022
|
* Resume queue processing
|
|
450
1023
|
*/
|
|
451
1024
|
resume() {
|
|
1025
|
+
this.assertMutable();
|
|
452
1026
|
if (!this.processing) {
|
|
453
1027
|
this.startProcessing();
|
|
454
1028
|
logger.log('info', 'Queue processing resumed');
|
|
@@ -459,11 +1033,15 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
459
1033
|
* @param maxAge Maximum age in milliseconds (default: 7 days)
|
|
460
1034
|
*/
|
|
461
1035
|
async cleanupOldItems(maxAge = 7 * 24 * 60 * 60 * 1000) {
|
|
1036
|
+
this.assertMutable();
|
|
462
1037
|
const cutoff = new Date(Date.now() - maxAge);
|
|
463
1038
|
// Collect IDs first to avoid modifying the Map during iteration
|
|
464
1039
|
const idsToRemove = [];
|
|
465
1040
|
for (const item of this.queue.values()) {
|
|
466
|
-
|
|
1041
|
+
const hasPendingBounceWork = (item.bounceOperations || []).some((operation) => operation.state !== 'completed');
|
|
1042
|
+
if (['delivered', 'failed'].includes(item.status)
|
|
1043
|
+
&& item.updatedAt < cutoff
|
|
1044
|
+
&& !hasPendingBounceWork) {
|
|
467
1045
|
idsToRemove.push(item.id);
|
|
468
1046
|
}
|
|
469
1047
|
}
|
|
@@ -480,25 +1058,34 @@ export class UnifiedDeliveryQueue extends EventEmitter {
|
|
|
480
1058
|
* Shutdown the queue
|
|
481
1059
|
*/
|
|
482
1060
|
async shutdown() {
|
|
1061
|
+
if (this.lifecycleState === 'closed')
|
|
1062
|
+
return;
|
|
483
1063
|
logger.log('info', 'Shutting down UnifiedDeliveryQueue');
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
1064
|
+
this.lifecycleState = 'shutting-down';
|
|
1065
|
+
let persistenceError;
|
|
1066
|
+
try {
|
|
1067
|
+
// Stop processing (clears both check and cleanup timers).
|
|
1068
|
+
this.stopProcessing();
|
|
1069
|
+
if (this.options.storageManager) {
|
|
1070
|
+
await Promise.all([...this.queue.values()].map((item) => this.persistItem(item)));
|
|
491
1071
|
}
|
|
492
|
-
// Wait for all writes to complete
|
|
493
|
-
await Promise.all(pendingWrites);
|
|
494
1072
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
1073
|
+
catch (error) {
|
|
1074
|
+
// Preserve the original persistence failure; observer diagnostics are
|
|
1075
|
+
// isolated and can never replace it.
|
|
1076
|
+
persistenceError = error;
|
|
1077
|
+
logger.log('error', `Failed to persist delivery queue during shutdown: ${error.message}`);
|
|
1078
|
+
}
|
|
1079
|
+
finally {
|
|
1080
|
+
this.queue.clear();
|
|
1081
|
+
this.updateStats();
|
|
1082
|
+
await emitSafely(this, 'shutdown');
|
|
1083
|
+
this.lifecycleState = 'closed';
|
|
1084
|
+
this.releaseManagedPrefix();
|
|
1085
|
+
}
|
|
1086
|
+
if (persistenceError)
|
|
1087
|
+
throw persistenceError;
|
|
501
1088
|
logger.log('info', 'UnifiedDeliveryQueue shut down successfully');
|
|
502
1089
|
}
|
|
503
1090
|
}
|
|
504
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kZWxpdmVyeS5xdWV1ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvY2xhc3Nlcy5kZWxpdmVyeS5xdWV1ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDM0MsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBNEIsTUFBTSxpQkFBaUIsQ0FBQztBQW9FM0Q7O0dBRUc7QUFDSCxNQUFNLE9BQU8sb0JBQXFCLFNBQVEsWUFBWTtJQUM1QyxPQUFPLENBQTBCO0lBQ2pDLEtBQUssR0FBNEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMzQyxVQUFVLENBQWtCO0lBQzVCLFlBQVksQ0FBa0I7SUFDOUIsS0FBSyxDQUFjO0lBQ25CLFVBQVUsR0FBWSxLQUFLLENBQUM7SUFDNUIsY0FBYyxHQUFXLENBQUMsQ0FBQztJQUVuQzs7O09BR0c7SUFDSCxZQUFZLE9BQXNCO1FBQ2hDLEtBQUssRUFBRSxDQUFDO1FBRVIsc0JBQXNCO1FBQ3RCLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxRQUFRO1lBQzVDLGNBQWMsRUFBRSxPQUFPLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLGFBQWEsQ0FBQztZQUNqRixhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxLQUFLLEVBQUUsYUFBYTtZQUM1RCxZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVksSUFBSSxLQUFLO1lBQzNDLGlC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
|
|
1091
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kZWxpdmVyeS5xdWV1ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21haWwvZGVsaXZlcnkvY2xhc3Nlcy5kZWxpdmVyeS5xdWV1ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFFakQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBNEIsTUFBTSxpQkFBaUIsQ0FBQztBQUUzRCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLDJCQUEyQixFQUMzQixxQ0FBcUMsRUFDckMsOEJBQThCLEdBQy9CLE1BQU0sOENBQThDLENBQUM7QUFFdEQsT0FBTyxFQUFFLEtBQUssRUFBc0IsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBd0k1RDs7R0FFRztBQUNILFNBQVMsc0JBQXNCLENBQUMsU0FBUyxHQUFHLGVBQWU7SUFDekQsSUFDRSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDO1FBQzFCLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUM7UUFDeEIsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFDeEIsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFDeEIsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsZ0VBQWdFLENBQUMsQ0FBQztJQUNwRixDQUFDO0lBQ0QsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUs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
|