@push.rocks/smartmta 7.0.0 → 8.0.1
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 +36 -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 +11 -0
- package/dist_ts/mail/core/classes.bouncemanager.js +120 -38
- package/dist_ts/mail/core/classes.email.js +14 -12
- 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/delivery/classes.delivery.queue.d.ts +77 -2
- package/dist_ts/mail/delivery/classes.delivery.queue.js +551 -46
- 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/index.d.ts +1 -0
- package/dist_ts/mail/delivery/index.js +2 -1
- package/dist_ts/mail/delivery/interfaces.d.ts +21 -0
- package/dist_ts/mail/delivery/interfaces.js +1 -1
- package/dist_ts/mail/index.d.ts +1 -0
- package/dist_ts/mail/index.js +1 -1
- package/dist_ts/mail/routing/classes.dkim.manager.d.ts +8 -4
- package/dist_ts/mail/routing/classes.dkim.manager.js +46 -29
- package/dist_ts/mail/routing/classes.dns.manager.d.ts +5 -3
- 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 +3 -0
- package/dist_ts/mail/routing/classes.email.router.js +15 -9
- package/dist_ts/mail/routing/classes.unified.email.server.d.ts +4 -0
- package/dist_ts/mail/routing/classes.unified.email.server.js +61 -40
- package/dist_ts/mail/security/classes.dkimcreator.d.ts +7 -0
- package/dist_ts/mail/security/classes.dkimcreator.js +33 -8
- package/dist_ts/mail/security/classes.spfverifier.js +5 -3
- package/dist_ts/security/classes.contentscanner.js +14 -11
- package/dist_ts/security/classes.ipreputationchecker.d.ts +3 -0
- package/dist_ts/security/classes.ipreputationchecker.js +20 -11
- package/dist_ts/security/classes.rustsecuritybridge.d.ts +49 -1
- 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 -8
- package/readme.hints.md +4 -3
- package/readme.md +41 -13
- 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 +157 -45
- package/ts/mail/core/classes.email.ts +19 -13
- package/ts/mail/core/classes.emailvalidator.ts +9 -7
- package/ts/mail/delivery/classes.delivery.queue.ts +740 -58
- 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/index.ts +1 -0
- package/ts/mail/delivery/interfaces.ts +27 -1
- package/ts/mail/index.ts +1 -0
- package/ts/mail/routing/classes.dkim.manager.ts +62 -37
- package/ts/mail/routing/classes.dns.manager.ts +36 -13
- package/ts/mail/routing/classes.email.action.executor.ts +64 -17
- package/ts/mail/routing/classes.email.router.ts +15 -8
- package/ts/mail/routing/classes.unified.email.server.ts +90 -44
- package/ts/mail/security/classes.dkimcreator.ts +50 -7
- package/ts/mail/security/classes.spfverifier.ts +4 -2
- package/ts/security/classes.contentscanner.ts +14 -11
- package/ts/security/classes.ipreputationchecker.ts +21 -10
- package/ts/security/classes.rustsecuritybridge.ts +269 -3
- package/ts/security/classes.securitylogger.ts +6 -4
- package/ts/security/index.ts +6 -1
|
@@ -69,6 +69,251 @@ interface IContentScanResult {
|
|
|
69
69
|
|
|
70
70
|
// --- SMTP Client types ---
|
|
71
71
|
|
|
72
|
+
export type TSmtpDeliveryPhase =
|
|
73
|
+
| 'connect'
|
|
74
|
+
| 'greeting'
|
|
75
|
+
| 'ehlo'
|
|
76
|
+
| 'starttls'
|
|
77
|
+
| 'tls_handshake'
|
|
78
|
+
| 'post_tls_ehlo'
|
|
79
|
+
| 'auth'
|
|
80
|
+
| 'mail_from'
|
|
81
|
+
| 'rcpt_to'
|
|
82
|
+
| 'data_command'
|
|
83
|
+
| 'message_body'
|
|
84
|
+
| 'final_response'
|
|
85
|
+
| 'rset'
|
|
86
|
+
| 'quit'
|
|
87
|
+
| 'unknown';
|
|
88
|
+
|
|
89
|
+
export interface ISmtpTranscriptEntry {
|
|
90
|
+
timestampMs: number;
|
|
91
|
+
phase: TSmtpDeliveryPhase;
|
|
92
|
+
direction: 'client' | 'server' | 'system';
|
|
93
|
+
text: string;
|
|
94
|
+
responseCode?: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Persisted SMTP traces are bounded by entries, Unicode code points, and UTF-8 bytes. */
|
|
98
|
+
export const SMTP_TRANSCRIPT_MAX_ENTRIES = 200;
|
|
99
|
+
export const SMTP_TRANSCRIPT_MAX_ENTRY_CODE_POINTS = 2_048;
|
|
100
|
+
export const SMTP_TRANSCRIPT_MAX_UTF8_BYTES = 64 * 1_024;
|
|
101
|
+
export const SMTP_TRANSCRIPT_TRUNCATION_MARKER = 'SMTP transcript truncated';
|
|
102
|
+
|
|
103
|
+
const utf8ByteLength = (valueArg: string): number => Buffer.byteLength(valueArg, 'utf8');
|
|
104
|
+
|
|
105
|
+
const truncateCodePoints = (valueArg: string): string => {
|
|
106
|
+
const codePoints = [...valueArg];
|
|
107
|
+
if (codePoints.length <= SMTP_TRANSCRIPT_MAX_ENTRY_CODE_POINTS) return valueArg;
|
|
108
|
+
return `${codePoints.slice(0, SMTP_TRANSCRIPT_MAX_ENTRY_CODE_POINTS - 1).join('')}…`;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const redactAuthTranscriptText = (
|
|
112
|
+
phaseArg: TSmtpDeliveryPhase,
|
|
113
|
+
directionArg: ISmtpTranscriptEntry['direction'],
|
|
114
|
+
textArg: string,
|
|
115
|
+
): string => {
|
|
116
|
+
if (phaseArg !== 'auth') return textArg;
|
|
117
|
+
if (directionArg === 'client') return '[AUTH command redacted]';
|
|
118
|
+
if (directionArg === 'server') return '[AUTH response redacted]';
|
|
119
|
+
return '[AUTH diagnostic redacted]';
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Normalize an untrusted SMTP trace before exposing or persisting it.
|
|
124
|
+
* Entry text is measured in Unicode code points; the aggregate is measured in UTF-8 bytes.
|
|
125
|
+
*/
|
|
126
|
+
export const normalizeSmtpTranscript = (entriesArg: unknown[]): ISmtpTranscriptEntry[] => {
|
|
127
|
+
const normalized: ISmtpTranscriptEntry[] = [];
|
|
128
|
+
let totalUtf8Bytes = 0;
|
|
129
|
+
|
|
130
|
+
const appendTruncationMarker = (referenceArg?: Partial<ISmtpTranscriptEntry>): void => {
|
|
131
|
+
const markerBytes = utf8ByteLength(SMTP_TRANSCRIPT_TRUNCATION_MARKER);
|
|
132
|
+
while (
|
|
133
|
+
normalized.length >= SMTP_TRANSCRIPT_MAX_ENTRIES
|
|
134
|
+
|| totalUtf8Bytes + markerBytes > SMTP_TRANSCRIPT_MAX_UTF8_BYTES
|
|
135
|
+
) {
|
|
136
|
+
const removed = normalized.pop();
|
|
137
|
+
if (!removed) break;
|
|
138
|
+
totalUtf8Bytes -= utf8ByteLength(removed.text);
|
|
139
|
+
}
|
|
140
|
+
if (
|
|
141
|
+
normalized.length < SMTP_TRANSCRIPT_MAX_ENTRIES
|
|
142
|
+
&& totalUtf8Bytes + markerBytes <= SMTP_TRANSCRIPT_MAX_UTF8_BYTES
|
|
143
|
+
) {
|
|
144
|
+
normalized.push({
|
|
145
|
+
timestampMs: typeof referenceArg?.timestampMs === 'number'
|
|
146
|
+
&& Number.isFinite(referenceArg.timestampMs)
|
|
147
|
+
? referenceArg.timestampMs
|
|
148
|
+
: Date.now(),
|
|
149
|
+
phase: isSmtpDeliveryPhase(referenceArg?.phase) ? referenceArg.phase : 'unknown',
|
|
150
|
+
direction: 'system',
|
|
151
|
+
text: SMTP_TRANSCRIPT_TRUNCATION_MARKER,
|
|
152
|
+
});
|
|
153
|
+
totalUtf8Bytes += markerBytes;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
for (const valueArg of entriesArg) {
|
|
158
|
+
if (!valueArg || typeof valueArg !== 'object') continue;
|
|
159
|
+
const value = valueArg as Partial<ISmtpTranscriptEntry>;
|
|
160
|
+
if (
|
|
161
|
+
typeof value.timestampMs !== 'number'
|
|
162
|
+
|| !Number.isFinite(value.timestampMs)
|
|
163
|
+
|| !isSmtpDeliveryPhase(value.phase)
|
|
164
|
+
|| !['client', 'server', 'system'].includes(value.direction as string)
|
|
165
|
+
|| typeof value.text !== 'string'
|
|
166
|
+
) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const direction = value.direction as ISmtpTranscriptEntry['direction'];
|
|
171
|
+
const text = truncateCodePoints(redactAuthTranscriptText(value.phase, direction, value.text));
|
|
172
|
+
const textBytes = utf8ByteLength(text);
|
|
173
|
+
if (
|
|
174
|
+
normalized.length >= SMTP_TRANSCRIPT_MAX_ENTRIES
|
|
175
|
+
|| totalUtf8Bytes + textBytes > SMTP_TRANSCRIPT_MAX_UTF8_BYTES
|
|
176
|
+
) {
|
|
177
|
+
appendTruncationMarker(value);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
normalized.push({
|
|
182
|
+
timestampMs: value.timestampMs,
|
|
183
|
+
phase: value.phase,
|
|
184
|
+
direction,
|
|
185
|
+
text,
|
|
186
|
+
...(typeof value.responseCode === 'number' && Number.isInteger(value.responseCode)
|
|
187
|
+
? { responseCode: value.responseCode }
|
|
188
|
+
: {}),
|
|
189
|
+
});
|
|
190
|
+
totalUtf8Bytes += textBytes;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return normalized;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export interface ISmtpDeliveryErrorDetails {
|
|
197
|
+
message: string;
|
|
198
|
+
errorType: string;
|
|
199
|
+
retryable: boolean;
|
|
200
|
+
smtpCode?: number;
|
|
201
|
+
phase: TSmtpDeliveryPhase;
|
|
202
|
+
transactionLog: ISmtpTranscriptEntry[];
|
|
203
|
+
recipients?: string[];
|
|
204
|
+
recipientDomain?: string;
|
|
205
|
+
recipientResults?: ISmtpRecipientResult[];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
interface ISmtpRecipientResult {
|
|
209
|
+
recipient: string;
|
|
210
|
+
accepted: boolean;
|
|
211
|
+
responseCode: number;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export class SmtpDeliveryError extends Error implements ISmtpDeliveryErrorDetails {
|
|
215
|
+
public readonly errorType: string;
|
|
216
|
+
public readonly retryable: boolean;
|
|
217
|
+
public readonly smtpCode?: number;
|
|
218
|
+
public readonly phase: TSmtpDeliveryPhase;
|
|
219
|
+
public readonly transactionLog: ISmtpTranscriptEntry[];
|
|
220
|
+
public readonly recipients: string[];
|
|
221
|
+
public readonly recipientDomain?: string;
|
|
222
|
+
public readonly recipientResults: ISmtpRecipientResult[];
|
|
223
|
+
|
|
224
|
+
constructor(details: ISmtpDeliveryErrorDetails, cause?: unknown) {
|
|
225
|
+
const transactionLog = normalizeSmtpTranscript(details.transactionLog);
|
|
226
|
+
const authFailure = (
|
|
227
|
+
details.phase === 'auth'
|
|
228
|
+
|| details.errorType === 'authentication'
|
|
229
|
+
|| transactionLog.some((entry) => entry.phase === 'auth')
|
|
230
|
+
);
|
|
231
|
+
super(authFailure ? 'SMTP authentication failed' : details.message);
|
|
232
|
+
this.name = 'SmtpDeliveryError';
|
|
233
|
+
this.errorType = details.errorType;
|
|
234
|
+
this.retryable = details.retryable;
|
|
235
|
+
this.smtpCode = details.smtpCode;
|
|
236
|
+
this.phase = details.phase;
|
|
237
|
+
this.transactionLog = transactionLog;
|
|
238
|
+
this.recipients = details.recipients || [];
|
|
239
|
+
this.recipientDomain = details.recipientDomain;
|
|
240
|
+
this.recipientResults = (details.recipientResults || []).map((result) => ({ ...result }));
|
|
241
|
+
if (cause !== undefined && !authFailure) {
|
|
242
|
+
(this as Error & { cause?: unknown }).cause = cause;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
public static from(errorArg: unknown): SmtpDeliveryError {
|
|
247
|
+
if (errorArg instanceof SmtpDeliveryError) {
|
|
248
|
+
return errorArg;
|
|
249
|
+
}
|
|
250
|
+
const source = errorArg instanceof Error ? errorArg : new Error(String(errorArg));
|
|
251
|
+
try {
|
|
252
|
+
const parsed = JSON.parse(source.message) as Partial<ISmtpDeliveryErrorDetails>;
|
|
253
|
+
if (typeof parsed.message !== 'string' || typeof parsed.retryable !== 'boolean') {
|
|
254
|
+
throw new Error('Incomplete SMTP error payload');
|
|
255
|
+
}
|
|
256
|
+
const phase = isSmtpDeliveryPhase(parsed.phase) ? parsed.phase : 'unknown';
|
|
257
|
+
const transactionLog = Array.isArray(parsed.transactionLog)
|
|
258
|
+
? normalizeSmtpTranscript(parsed.transactionLog)
|
|
259
|
+
: [];
|
|
260
|
+
return new SmtpDeliveryError({
|
|
261
|
+
message: parsed.message,
|
|
262
|
+
errorType: typeof parsed.errorType === 'string' ? parsed.errorType : 'unknown',
|
|
263
|
+
retryable: parsed.retryable,
|
|
264
|
+
...(typeof parsed.smtpCode === 'number' ? { smtpCode: parsed.smtpCode } : {}),
|
|
265
|
+
phase,
|
|
266
|
+
transactionLog,
|
|
267
|
+
recipients: Array.isArray(parsed.recipients)
|
|
268
|
+
? parsed.recipients.filter((value): value is string => typeof value === 'string')
|
|
269
|
+
: [],
|
|
270
|
+
recipientResults: Array.isArray(parsed.recipientResults)
|
|
271
|
+
? parsed.recipientResults.filter((value): value is ISmtpRecipientResult => (
|
|
272
|
+
Boolean(value)
|
|
273
|
+
&& typeof value === 'object'
|
|
274
|
+
&& typeof (value as ISmtpRecipientResult).recipient === 'string'
|
|
275
|
+
&& typeof (value as ISmtpRecipientResult).accepted === 'boolean'
|
|
276
|
+
&& Number.isInteger((value as ISmtpRecipientResult).responseCode)
|
|
277
|
+
)).map((value) => ({ ...value }))
|
|
278
|
+
: [],
|
|
279
|
+
...(typeof parsed.recipientDomain === 'string'
|
|
280
|
+
? { recipientDomain: parsed.recipientDomain }
|
|
281
|
+
: {}),
|
|
282
|
+
}, source);
|
|
283
|
+
} catch {
|
|
284
|
+
return new SmtpDeliveryError({
|
|
285
|
+
message: source.message,
|
|
286
|
+
errorType: 'unknown',
|
|
287
|
+
retryable: true,
|
|
288
|
+
phase: 'unknown',
|
|
289
|
+
transactionLog: [],
|
|
290
|
+
recipients: [],
|
|
291
|
+
}, source);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const smtpDeliveryPhases = new Set<TSmtpDeliveryPhase>([
|
|
297
|
+
'connect',
|
|
298
|
+
'greeting',
|
|
299
|
+
'ehlo',
|
|
300
|
+
'starttls',
|
|
301
|
+
'tls_handshake',
|
|
302
|
+
'post_tls_ehlo',
|
|
303
|
+
'auth',
|
|
304
|
+
'mail_from',
|
|
305
|
+
'rcpt_to',
|
|
306
|
+
'data_command',
|
|
307
|
+
'message_body',
|
|
308
|
+
'final_response',
|
|
309
|
+
'rset',
|
|
310
|
+
'quit',
|
|
311
|
+
'unknown',
|
|
312
|
+
]);
|
|
313
|
+
|
|
314
|
+
const isSmtpDeliveryPhase = (valueArg: unknown): valueArg is TSmtpDeliveryPhase =>
|
|
315
|
+
typeof valueArg === 'string' && smtpDeliveryPhases.has(valueArg as TSmtpDeliveryPhase);
|
|
316
|
+
|
|
72
317
|
interface IOutboundEmail {
|
|
73
318
|
from: string;
|
|
74
319
|
to: string[];
|
|
@@ -83,9 +328,11 @@ interface IOutboundEmail {
|
|
|
83
328
|
interface ISmtpSendResult {
|
|
84
329
|
accepted: string[];
|
|
85
330
|
rejected: string[];
|
|
331
|
+
recipientResults?: ISmtpRecipientResult[];
|
|
86
332
|
messageId?: string;
|
|
87
333
|
response: string;
|
|
88
334
|
envelope: { from: string; to: string[] };
|
|
335
|
+
transactionLog: ISmtpTranscriptEntry[];
|
|
89
336
|
}
|
|
90
337
|
|
|
91
338
|
interface ISmtpSendOptions {
|
|
@@ -442,7 +689,9 @@ export class RustSecurityBridge extends EventEmitter {
|
|
|
442
689
|
this.bridge = new plugins.smartrust.RustBridge<TMailerCommands>({
|
|
443
690
|
binaryName: 'mailer-bin',
|
|
444
691
|
cliArgs: ['--management'],
|
|
445
|
-
|
|
692
|
+
// A full SMTP transaction can legitimately span several socket waits.
|
|
693
|
+
// Health checks retain their own short timeout and run concurrently.
|
|
694
|
+
requestTimeoutMs: 300_000,
|
|
446
695
|
readyTimeoutMs: 10_000,
|
|
447
696
|
localPaths,
|
|
448
697
|
searchSystemPath: false,
|
|
@@ -877,13 +1126,29 @@ export class RustSecurityBridge extends EventEmitter {
|
|
|
877
1126
|
/** Send a structured email via the Rust SMTP client. */
|
|
878
1127
|
public async sendOutboundEmail(opts: ISmtpSendOptions): Promise<ISmtpSendResult> {
|
|
879
1128
|
this.ensureRunning();
|
|
880
|
-
|
|
1129
|
+
try {
|
|
1130
|
+
const result = await this.bridge.sendCommand('sendEmail', opts);
|
|
1131
|
+
return {
|
|
1132
|
+
...result,
|
|
1133
|
+
transactionLog: normalizeSmtpTranscript(result.transactionLog),
|
|
1134
|
+
};
|
|
1135
|
+
} catch (error) {
|
|
1136
|
+
throw SmtpDeliveryError.from(error);
|
|
1137
|
+
}
|
|
881
1138
|
}
|
|
882
1139
|
|
|
883
1140
|
/** Send a pre-formatted raw email via the Rust SMTP client. */
|
|
884
1141
|
public async sendRawEmail(opts: ISmtpSendRawOptions): Promise<ISmtpSendResult> {
|
|
885
1142
|
this.ensureRunning();
|
|
886
|
-
|
|
1143
|
+
try {
|
|
1144
|
+
const result = await this.bridge.sendCommand('sendRawEmail', opts);
|
|
1145
|
+
return {
|
|
1146
|
+
...result,
|
|
1147
|
+
transactionLog: normalizeSmtpTranscript(result.transactionLog),
|
|
1148
|
+
};
|
|
1149
|
+
} catch (error) {
|
|
1150
|
+
throw SmtpDeliveryError.from(error);
|
|
1151
|
+
}
|
|
887
1152
|
}
|
|
888
1153
|
|
|
889
1154
|
/** Verify connectivity to an SMTP server. */
|
|
@@ -1065,6 +1330,7 @@ export type {
|
|
|
1065
1330
|
IScramCredentialRequestEvent,
|
|
1066
1331
|
IOutboundEmail,
|
|
1067
1332
|
ISmtpSendResult,
|
|
1333
|
+
ISmtpRecipientResult,
|
|
1068
1334
|
ISmtpSendOptions,
|
|
1069
1335
|
ISmtpSendRawOptions,
|
|
1070
1336
|
ISmtpVerifyOptions,
|
|
@@ -146,12 +146,14 @@ export class SecurityLogger {
|
|
|
146
146
|
filteredEvents = filteredEvents.filter(event => event.type === filter.type);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
const fromTimestamp = filter.fromTimestamp;
|
|
150
|
+
if (fromTimestamp !== undefined) {
|
|
151
|
+
filteredEvents = filteredEvents.filter(event => event.timestamp >= fromTimestamp);
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
const toTimestamp = filter.toTimestamp;
|
|
155
|
+
if (toTimestamp !== undefined) {
|
|
156
|
+
filteredEvents = filteredEvents.filter(event => event.timestamp <= toTimestamp);
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
159
|
|
package/ts/security/index.ts
CHANGED
|
@@ -23,7 +23,11 @@ export {
|
|
|
23
23
|
export {
|
|
24
24
|
RustSecurityBridge,
|
|
25
25
|
BridgeState,
|
|
26
|
+
SmtpDeliveryError,
|
|
26
27
|
type IBridgeResilienceConfig,
|
|
28
|
+
type TSmtpDeliveryPhase,
|
|
29
|
+
type ISmtpTranscriptEntry,
|
|
30
|
+
type ISmtpDeliveryErrorDetails,
|
|
27
31
|
type IDkimVerificationResult,
|
|
28
32
|
type ISpfResult,
|
|
29
33
|
type IDmarcResult,
|
|
@@ -34,7 +38,8 @@ export {
|
|
|
34
38
|
type IVersionInfo,
|
|
35
39
|
type IOutboundEmail,
|
|
36
40
|
type ISmtpSendResult,
|
|
41
|
+
type ISmtpRecipientResult,
|
|
37
42
|
type ISmtpSendOptions,
|
|
38
43
|
type ISmtpVerifyResult,
|
|
39
44
|
type ISmtpPoolStatus,
|
|
40
|
-
} from './classes.rustsecuritybridge.js';
|
|
45
|
+
} from './classes.rustsecuritybridge.js';
|