@serve.zone/coremail 1.2.0 → 32.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/.smartconfig.json +1 -0
- package/changelog.md +50 -0
- package/dist_ts/00_commitinfo_data.js +4 -4
- package/dist_ts/classes.auth.d.ts +19 -0
- package/dist_ts/classes.auth.js +58 -1
- package/dist_ts/classes.coremail.d.ts +3 -0
- package/dist_ts/classes.coremail.js +11 -4
- package/dist_ts/classes.gateway.d.ts +21 -1
- package/dist_ts/classes.gateway.js +115 -68
- package/dist_ts/classes.inbound.d.ts +10 -1
- package/dist_ts/classes.inbound.js +45 -7
- package/dist_ts/classes.maintenance.js +16 -1
- package/dist_ts/classes.models.d.ts +24 -2
- package/dist_ts/classes.models.js +72 -2
- package/dist_ts/classes.server.d.ts +6 -12
- package/dist_ts/classes.server.js +18 -78
- package/dist_ts/classes.smtpsubmission.d.ts +85 -0
- package/dist_ts/classes.smtpsubmission.js +379 -0
- package/dist_ts/classes.storage.d.ts +9 -0
- package/dist_ts/classes.storage.js +44 -1
- package/dist_ts/classes.submissions.d.ts +27 -1
- package/dist_ts/classes.submissions.js +164 -14
- package/dist_ts/coremail.cursor.js +1 -15
- package/dist_ts/coremail.errors.d.ts +18 -0
- package/dist_ts/coremail.errors.js +84 -0
- package/dist_ts/coremail.log.d.ts +1 -1
- package/dist_ts/coremail.log.js +3 -6
- package/dist_ts/coremail.mime.d.ts +15 -0
- package/dist_ts/coremail.mime.js +76 -1
- package/dist_ts/coremail.persistence.d.ts +38 -1
- package/dist_ts/coremail.persistence.js +123 -40
- package/dist_ts/coremail.stats.d.ts +72 -0
- package/dist_ts/coremail.stats.js +242 -0
- package/dist_ts/coremail.validation.d.ts +15 -2
- package/dist_ts/coremail.validation.js +26 -79
- package/dist_ts/interfaces.d.ts +18 -0
- package/dist_ts/plugins.d.ts +1 -0
- package/dist_ts/plugins.js +2 -1
- package/package.json +6 -5
- package/readme.md +66 -8
- package/ts/00_commitinfo_data.ts +3 -3
- package/ts/classes.auth.ts +77 -0
- package/ts/classes.coremail.ts +20 -0
- package/ts/classes.gateway.ts +142 -71
- package/ts/classes.inbound.ts +71 -6
- package/ts/classes.maintenance.ts +14 -0
- package/ts/classes.models.ts +67 -1
- package/ts/classes.server.ts +22 -86
- package/ts/classes.smtpsubmission.ts +466 -0
- package/ts/classes.storage.ts +54 -0
- package/ts/classes.submissions.ts +247 -12
- package/ts/coremail.cursor.ts +2 -18
- package/ts/coremail.errors.ts +111 -0
- package/ts/coremail.log.ts +3 -6
- package/ts/coremail.mime.ts +89 -0
- package/ts/coremail.persistence.ts +195 -48
- package/ts/coremail.stats.ts +342 -0
- package/ts/coremail.validation.ts +31 -104
- package/ts/interfaces.ts +20 -0
- package/ts/plugins.ts +1 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { createSha256 } from './classes.storage.js';
|
|
3
|
+
import { coreMailStatKinds, } from './coremail.persistence.js';
|
|
4
|
+
const dayMs = 86_400_000;
|
|
5
|
+
/** How long a counted day is retained before the maintenance sweep drops it. */
|
|
6
|
+
export const coreMailStatRetentionMs = 90 * dayMs;
|
|
7
|
+
/**
|
|
8
|
+
* The counter row an event at `nowArg` belongs to.
|
|
9
|
+
*
|
|
10
|
+
* Counters are keyed by binding rather than binding revision: a revision bump
|
|
11
|
+
* is a configuration change, not a new tenant, and a day's totals must survive
|
|
12
|
+
* one.
|
|
13
|
+
*/
|
|
14
|
+
export const createCoreMailStatDescriptor = (authorityArg, nowArg) => {
|
|
15
|
+
const dayUtc = Math.floor(nowArg / dayMs) * dayMs;
|
|
16
|
+
return {
|
|
17
|
+
tenantId: authorityArg.tenantId,
|
|
18
|
+
serviceId: authorityArg.serviceId,
|
|
19
|
+
bindingId: authorityArg.bindingId,
|
|
20
|
+
dayUtc,
|
|
21
|
+
statId: createSha256(JSON.stringify({
|
|
22
|
+
tenantId: authorityArg.tenantId,
|
|
23
|
+
serviceId: authorityArg.serviceId,
|
|
24
|
+
bindingId: authorityArg.bindingId,
|
|
25
|
+
dayUtc,
|
|
26
|
+
})),
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
const matchesDescriptor = (counterArg, descriptorArg) => counterArg.tenantId === descriptorArg.tenantId
|
|
30
|
+
&& counterArg.serviceId === descriptorArg.serviceId
|
|
31
|
+
&& counterArg.bindingId === descriptorArg.bindingId
|
|
32
|
+
&& counterArg.dayUtc === descriptorArg.dayUtc;
|
|
33
|
+
/** Create the day's row if it does not exist yet. Safe to call concurrently. */
|
|
34
|
+
export const ensureCoreMailStatCounter = async (modelsArg, descriptorArg) => {
|
|
35
|
+
const existing = await modelsArg.StatCounter.exact.findStoredOne({
|
|
36
|
+
statId: descriptorArg.statId,
|
|
37
|
+
});
|
|
38
|
+
if (existing) {
|
|
39
|
+
if (!matchesDescriptor(existing, descriptorArg)) {
|
|
40
|
+
throw new Error('CoreMail stat counter identity conflicts with persisted state.');
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const result = await modelsArg.StatCounter.exact.insert({
|
|
46
|
+
...descriptorArg,
|
|
47
|
+
...Object.fromEntries(coreMailStatKinds.map((kindArg) => [kindArg, 0])),
|
|
48
|
+
createdAt: descriptorArg.dayUtc,
|
|
49
|
+
updatedAt: descriptorArg.dayUtc,
|
|
50
|
+
});
|
|
51
|
+
if (result.status !== 'conflict') {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (!(error instanceof plugins.smartdata.SmartdataExactPersistenceError)
|
|
57
|
+
|| error.code !== 'unique_conflict') {
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const concurrent = await modelsArg.StatCounter.exact.findStoredOne({
|
|
62
|
+
statId: descriptorArg.statId,
|
|
63
|
+
});
|
|
64
|
+
if (!concurrent || !matchesDescriptor(concurrent, descriptorArg)) {
|
|
65
|
+
throw new Error('CoreMail stat counter identity conflicts with persisted state.');
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Add one to a counter through the revision-fenced transition primitive, so
|
|
70
|
+
* the read and the write are one atomic compare-and-set. Call this inside the
|
|
71
|
+
* transaction that carries the counted state transition; then the event and
|
|
72
|
+
* its count commit together or not at all.
|
|
73
|
+
*/
|
|
74
|
+
export const incrementCoreMailStatCounter = async (modelsArg, descriptorArg, kindArg, updatedAtArg, sessionArg) => {
|
|
75
|
+
const counter = await modelsArg.StatCounter.exact.findStoredOne({ statId: descriptorArg.statId }, sessionArg ? { session: sessionArg } : undefined);
|
|
76
|
+
if (!counter) {
|
|
77
|
+
throw new Error('CoreMail stat counter is unavailable.');
|
|
78
|
+
}
|
|
79
|
+
if (!matchesDescriptor(counter, descriptorArg)) {
|
|
80
|
+
throw new Error('CoreMail stat counter identity conflicts with persisted state.');
|
|
81
|
+
}
|
|
82
|
+
const update = await modelsArg.StatCounter.exact.transition({
|
|
83
|
+
current: counter,
|
|
84
|
+
change: (modelArg) => {
|
|
85
|
+
modelArg[kindArg] += 1;
|
|
86
|
+
modelArg.updatedAt = updatedAtArg;
|
|
87
|
+
},
|
|
88
|
+
}, sessionArg ? { session: sessionArg } : undefined);
|
|
89
|
+
if (update.status !== 'transitioned') {
|
|
90
|
+
throw new Error('CoreMail stat counter transition was contended.');
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Ensure the day's row exists, then count one event on it.
|
|
95
|
+
*
|
|
96
|
+
* For a counted transition that runs inside a transaction, call
|
|
97
|
+
* `ensureCoreMailStatCounter` before opening it and
|
|
98
|
+
* `incrementCoreMailStatCounter` with the session inside it — the same order
|
|
99
|
+
* the quota counters use, so the row insert never contends with the
|
|
100
|
+
* transaction that increments it.
|
|
101
|
+
*/
|
|
102
|
+
export const countCoreMailStat = async (modelsArg, authorityArg, kindArg, nowArg, sessionArg) => {
|
|
103
|
+
const descriptor = createCoreMailStatDescriptor(authorityArg, nowArg);
|
|
104
|
+
await ensureCoreMailStatCounter(modelsArg, descriptor);
|
|
105
|
+
await incrementCoreMailStatCounter(modelsArg, descriptor, kindArg, nowArg, sessionArg);
|
|
106
|
+
return descriptor;
|
|
107
|
+
};
|
|
108
|
+
/** Maximum rows one statistics page may return. */
|
|
109
|
+
export const coreMailStatPageMaximum = 200;
|
|
110
|
+
const dayPattern = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
|
|
111
|
+
/** `YYYY-MM-DD` to the UTC midnight milliseconds the counter rows are keyed by. */
|
|
112
|
+
export const parseCoreMailStatDay = (valueArg, labelArg) => {
|
|
113
|
+
if (typeof valueArg !== 'string' || !dayPattern.test(valueArg)) {
|
|
114
|
+
throw new Error(`CoreMail statistics ${labelArg} must be a YYYY-MM-DD day.`);
|
|
115
|
+
}
|
|
116
|
+
const parsed = Date.parse(`${valueArg}T00:00:00.000Z`);
|
|
117
|
+
if (!Number.isSafeInteger(parsed) || parsed % dayMs !== 0) {
|
|
118
|
+
throw new Error(`CoreMail statistics ${labelArg} must be a real UTC day.`);
|
|
119
|
+
}
|
|
120
|
+
return parsed;
|
|
121
|
+
};
|
|
122
|
+
export const formatCoreMailStatDay = (dayUtcArg) => new Date(dayUtcArg).toISOString().slice(0, 10);
|
|
123
|
+
/**
|
|
124
|
+
* Opaque composite cursor over `(dayUtc, statId)`.
|
|
125
|
+
*
|
|
126
|
+
* It carries no authority: the control session is what authorizes the read,
|
|
127
|
+
* and every filter is re-applied on the next page, so a replayed cursor can
|
|
128
|
+
* only ever resume the same ordered scan.
|
|
129
|
+
*/
|
|
130
|
+
export const encodeCoreMailStatCursor = (positionArg) => Buffer.from(JSON.stringify({ v: 1, d: positionArg.dayUtc, s: positionArg.statId }), 'utf8').toString('base64url');
|
|
131
|
+
export const decodeCoreMailStatCursor = (valueArg) => {
|
|
132
|
+
if (typeof valueArg !== 'string'
|
|
133
|
+
|| valueArg.length === 0
|
|
134
|
+
|| valueArg.length
|
|
135
|
+
> plugins.serveZoneInterfaces.data.coreMailLimits.cursorBytes) {
|
|
136
|
+
throw new Error('CoreMail statistics cursor is invalid.');
|
|
137
|
+
}
|
|
138
|
+
let decoded;
|
|
139
|
+
try {
|
|
140
|
+
decoded = JSON.parse(Buffer.from(valueArg, 'base64url').toString('utf8'));
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
throw new Error('CoreMail statistics cursor is invalid.');
|
|
144
|
+
}
|
|
145
|
+
const record = decoded;
|
|
146
|
+
if (!record
|
|
147
|
+
|| typeof record !== 'object'
|
|
148
|
+
|| record.v !== 1
|
|
149
|
+
|| !Number.isSafeInteger(record.d)
|
|
150
|
+
|| Number(record.d) % dayMs !== 0
|
|
151
|
+
|| typeof record.s !== 'string') {
|
|
152
|
+
throw new Error('CoreMail statistics cursor is invalid.');
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
return {
|
|
156
|
+
dayUtc: Number(record.d),
|
|
157
|
+
statId: plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(record.s),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
throw new Error('CoreMail statistics cursor is invalid.');
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
/** Project one counter row onto the wire contract. */
|
|
165
|
+
export const toCoreMailServiceMailStatistics = (counterArg) => plugins.serveZoneInterfaces.data.normalizeCoreMailServiceMailStatistics({
|
|
166
|
+
tenantId: counterArg.tenantId,
|
|
167
|
+
serviceId: counterArg.serviceId,
|
|
168
|
+
bindingId: counterArg.bindingId,
|
|
169
|
+
dayUtc: formatCoreMailStatDay(counterArg.dayUtc),
|
|
170
|
+
outbound: {
|
|
171
|
+
submittedApi: counterArg.submittedApi,
|
|
172
|
+
submittedSmtp: counterArg.submittedSmtp,
|
|
173
|
+
delivered: counterArg.delivered,
|
|
174
|
+
deferred: counterArg.deferred,
|
|
175
|
+
failed: counterArg.failed,
|
|
176
|
+
deadLettered: counterArg.deadLettered,
|
|
177
|
+
},
|
|
178
|
+
inbound: {
|
|
179
|
+
received: counterArg.received,
|
|
180
|
+
acknowledgedProcessed: counterArg.acknowledgedProcessed,
|
|
181
|
+
acknowledgedDiscarded: counterArg.acknowledgedDiscarded,
|
|
182
|
+
},
|
|
183
|
+
updatedAt: counterArg.updatedAt,
|
|
184
|
+
});
|
|
185
|
+
/** One ordered, bounded page of per-service daily counters. */
|
|
186
|
+
export const listCoreMailServiceMailStatistics = async (modelsArg, requestArg) => {
|
|
187
|
+
const fromDayUtc = parseCoreMailStatDay(requestArg.fromDayUtc, 'fromDayUtc');
|
|
188
|
+
const toDayUtc = parseCoreMailStatDay(requestArg.toDayUtc, 'toDayUtc');
|
|
189
|
+
if (toDayUtc < fromDayUtc) {
|
|
190
|
+
throw new Error('CoreMail statistics range is inverted.');
|
|
191
|
+
}
|
|
192
|
+
if (!Number.isSafeInteger(requestArg.limit)
|
|
193
|
+
|| requestArg.limit < 1
|
|
194
|
+
|| requestArg.limit > coreMailStatPageMaximum) {
|
|
195
|
+
throw new Error(`CoreMail statistics limit must be between 1 and ${coreMailStatPageMaximum}.`);
|
|
196
|
+
}
|
|
197
|
+
let serviceIds;
|
|
198
|
+
if (requestArg.serviceIds !== undefined) {
|
|
199
|
+
if (!Array.isArray(requestArg.serviceIds)
|
|
200
|
+
|| requestArg.serviceIds.length === 0
|
|
201
|
+
|| requestArg.serviceIds.length > 1_000
|
|
202
|
+
|| requestArg.serviceIds.some((entryArg) => typeof entryArg !== 'string')) {
|
|
203
|
+
throw new Error('CoreMail statistics serviceIds filter is invalid.');
|
|
204
|
+
}
|
|
205
|
+
serviceIds = [...new Set(requestArg.serviceIds)];
|
|
206
|
+
}
|
|
207
|
+
const cursor = requestArg.cursor === undefined
|
|
208
|
+
? undefined
|
|
209
|
+
: decodeCoreMailStatCursor(requestArg.cursor);
|
|
210
|
+
const rows = await modelsArg.StatCounter.exact.findStored({
|
|
211
|
+
filter: {
|
|
212
|
+
$and: [
|
|
213
|
+
{ dayUtc: { $gte: fromDayUtc, $lte: toDayUtc } },
|
|
214
|
+
...(serviceIds ? [{ serviceId: { $in: serviceIds } }] : []),
|
|
215
|
+
...(cursor
|
|
216
|
+
? [{
|
|
217
|
+
$or: [
|
|
218
|
+
{ dayUtc: { $gt: cursor.dayUtc } },
|
|
219
|
+
{ dayUtc: cursor.dayUtc, statId: { $gt: cursor.statId } },
|
|
220
|
+
],
|
|
221
|
+
}]
|
|
222
|
+
: []),
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
sort: { dayUtc: 1, statId: 1 },
|
|
226
|
+
limit: requestArg.limit + 1,
|
|
227
|
+
});
|
|
228
|
+
const page = rows.slice(0, requestArg.limit);
|
|
229
|
+
const last = page.at(-1);
|
|
230
|
+
return {
|
|
231
|
+
statistics: page.map(toCoreMailServiceMailStatistics),
|
|
232
|
+
...(rows.length > page.length && last
|
|
233
|
+
? {
|
|
234
|
+
nextCursor: encodeCoreMailStatCursor({
|
|
235
|
+
dayUtc: last.dayUtc,
|
|
236
|
+
statId: last.statId,
|
|
237
|
+
}),
|
|
238
|
+
}
|
|
239
|
+
: {}),
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZW1haWwuc3RhdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jb3JlbWFpbC5zdGF0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDcEQsT0FBTyxFQUNMLGlCQUFpQixHQUdsQixNQUFNLDJCQUEyQixDQUFDO0FBRW5DLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQztBQUV6QixnRkFBZ0Y7QUFDaEYsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQztBQWFsRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSw0QkFBNEIsR0FBRyxDQUMxQyxZQUFvQyxFQUNwQyxNQUFjLEVBQ1csRUFBRTtJQUMzQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDbEQsT0FBTztRQUNMLFFBQVEsRUFBRSxZQUFZLENBQUMsUUFBUTtRQUMvQixTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVM7UUFDakMsU0FBUyxFQUFFLFlBQVksQ0FBQyxTQUFTO1FBQ2pDLE1BQU07UUFDTixNQUFNLEVBQUUsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDbEMsUUFBUSxFQUFFLFlBQVksQ0FBQyxRQUFRO1lBQy9CLFNBQVMsRUFBRSxZQUFZLENBQUMsU0FBUztZQUNqQyxTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVM7WUFDakMsTUFBTTtTQUNQLENBQUMsQ0FBQztLQUNKLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixNQUFNLGlCQUFpQixHQUFHLENBQ3hCLFVBQXlFLEVBQ3pFLGFBQXNDLEVBQzdCLEVBQUUsQ0FDWCxVQUFVLENBQUMsUUFBUSxLQUFLLGFBQWEsQ0FBQyxRQUFRO09BQzND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
|
|
@@ -2,8 +2,21 @@ import * as plugins from './plugins.js';
|
|
|
2
2
|
type TMessage = plugins.serveZoneInterfaces.data.ICoreMailOutboundMessageDescriptor;
|
|
3
3
|
export declare const normalizeCoreMailMailboxAddress: (valueArg: unknown) => string;
|
|
4
4
|
export declare const normalizeCoreMailEnvelope: (valueArg: unknown) => plugins.serveZoneInterfaces.data.ICoreMailEnvelope;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The single sender-authorization rule every outbound path applies: the
|
|
7
|
+
* envelope sender must be an exact member of the binding's allowed senders.
|
|
8
|
+
*/
|
|
9
|
+
export declare const assertCoreMailSenderAllowed: (senderAddressArg: string, bindingArg: plugins.serveZoneInterfaces.data.ICoreMailBindingDesiredState) => void;
|
|
7
10
|
export declare const normalizeCoreMailOutboundMessage: (valueArg: unknown, bindingArg: plugins.serveZoneInterfaces.data.ICoreMailBindingDesiredState) => TMessage;
|
|
11
|
+
/**
|
|
12
|
+
* Build the outbound message descriptor of an exact-byte SMTP submission.
|
|
13
|
+
*
|
|
14
|
+
* An SMTP submission has no CoreMail-composed body: the bytes are opaque and
|
|
15
|
+
* are owned by the immutable MIME tuple, so the descriptor carries only the
|
|
16
|
+
* SMTP envelope. `parts` is therefore empty, which is why such a descriptor is
|
|
17
|
+
* deliberately not routed through
|
|
18
|
+
* `normalizeCoreMailOutboundMessageDescriptor` (it requires at least one part).
|
|
19
|
+
*/
|
|
20
|
+
export declare const createCoreMailRawOutboundMessage: (envelopeArg: plugins.serveZoneInterfaces.data.ICoreMailEnvelope) => TMessage;
|
|
8
21
|
export declare const createCoreMailSubmissionDigest: (idempotencyKeyArg: string, messageArg: TMessage) => plugins.serveZoneInterfaces.data.TCoreMailSha256;
|
|
9
22
|
export {};
|
|
@@ -63,98 +63,45 @@ export const normalizeCoreMailEnvelope = (valueArg) => {
|
|
|
63
63
|
}
|
|
64
64
|
return { mailFrom, rcptTo };
|
|
65
65
|
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'
|
|
73
|
-
'authUsername',
|
|
74
|
-
'authenticatedCredentialId',
|
|
75
|
-
], 'connectionInfo');
|
|
76
|
-
if (value.protocol !== 'smtp'
|
|
77
|
-
&& value.protocol !== 'submission'
|
|
78
|
-
&& value.protocol !== 'api') {
|
|
79
|
-
throw new Error('CoreMail gateway connection protocol is invalid.');
|
|
80
|
-
}
|
|
81
|
-
for (const key of [
|
|
82
|
-
'remoteAddress',
|
|
83
|
-
'proxyAddress',
|
|
84
|
-
'heloName',
|
|
85
|
-
'authUsername',
|
|
86
|
-
'authenticatedCredentialId',
|
|
87
|
-
]) {
|
|
88
|
-
if (value[key] !== undefined
|
|
89
|
-
&& (typeof value[key] !== 'string'
|
|
90
|
-
|| value[key].length === 0
|
|
91
|
-
|| Buffer.byteLength(value[key], 'utf8') > 512
|
|
92
|
-
|| value[key].trim() !== value[key])) {
|
|
93
|
-
throw new Error(`CoreMail gateway connection ${key} is invalid.`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (value.tls !== undefined && typeof value.tls !== 'boolean') {
|
|
97
|
-
throw new Error('CoreMail gateway connection TLS state is invalid.');
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
protocol: value.protocol,
|
|
101
|
-
...(value.remoteAddress === undefined
|
|
102
|
-
? {}
|
|
103
|
-
: { remoteAddress: value.remoteAddress }),
|
|
104
|
-
...(value.proxyAddress === undefined
|
|
105
|
-
? {}
|
|
106
|
-
: { proxyAddress: value.proxyAddress }),
|
|
107
|
-
...(value.heloName === undefined
|
|
108
|
-
? {}
|
|
109
|
-
: { heloName: value.heloName }),
|
|
110
|
-
...(value.tls === undefined ? {} : { tls: value.tls }),
|
|
111
|
-
...(value.authUsername === undefined
|
|
112
|
-
? {}
|
|
113
|
-
: { authUsername: value.authUsername }),
|
|
114
|
-
...(value.authenticatedCredentialId === undefined
|
|
115
|
-
? {}
|
|
116
|
-
: {
|
|
117
|
-
authenticatedCredentialId: value.authenticatedCredentialId,
|
|
118
|
-
}),
|
|
119
|
-
};
|
|
120
|
-
};
|
|
121
|
-
export const normalizeCoreMailGatewayMessage = (valueArg) => {
|
|
122
|
-
const value = requirePlainRecord(valueArg, 'gatewayMessage');
|
|
123
|
-
requireExactKeys(value, ['envelope', 'rawMime'], [], 'gatewayMessage');
|
|
124
|
-
const rawMime = requirePlainRecord(value.rawMime, 'gatewayMessage.rawMime');
|
|
125
|
-
requireExactKeys(rawMime, ['sha256', 'lengthBytes', 'contentType'], [], 'gatewayMessage.rawMime');
|
|
126
|
-
if (rawMime.contentType !== 'message/rfc822'
|
|
127
|
-
|| !Number.isSafeInteger(rawMime.lengthBytes)
|
|
128
|
-
|| Number(rawMime.lengthBytes) < 1
|
|
129
|
-
|| Number(rawMime.lengthBytes)
|
|
130
|
-
> plugins.serveZoneInterfaces.data.coreMailLimits.serializedMimeBytes) {
|
|
131
|
-
throw new Error('CoreMail gateway MIME descriptor is invalid.');
|
|
66
|
+
/**
|
|
67
|
+
* The single sender-authorization rule every outbound path applies: the
|
|
68
|
+
* envelope sender must be an exact member of the binding's allowed senders.
|
|
69
|
+
*/
|
|
70
|
+
export const assertCoreMailSenderAllowed = (senderAddressArg, bindingArg) => {
|
|
71
|
+
if (!bindingArg.allowedSenders.includes(senderAddressArg)) {
|
|
72
|
+
throw new Error('CoreMail sender is not authorized by the binding.');
|
|
132
73
|
}
|
|
133
|
-
return {
|
|
134
|
-
envelope: normalizeCoreMailEnvelope(value.envelope),
|
|
135
|
-
rawMime: {
|
|
136
|
-
sha256: plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(rawMime.sha256),
|
|
137
|
-
lengthBytes: Number(rawMime.lengthBytes),
|
|
138
|
-
contentType: 'message/rfc822',
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
74
|
};
|
|
142
75
|
export const normalizeCoreMailOutboundMessage = (valueArg, bindingArg) => {
|
|
143
76
|
const message = plugins.serveZoneInterfaces.data
|
|
144
77
|
.normalizeCoreMailOutboundMessageDescriptor(valueArg);
|
|
145
|
-
|
|
146
|
-
throw new Error('CoreMail sender is not authorized by the binding.');
|
|
147
|
-
}
|
|
78
|
+
assertCoreMailSenderAllowed(message.sender.address, bindingArg);
|
|
148
79
|
return message;
|
|
149
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Build the outbound message descriptor of an exact-byte SMTP submission.
|
|
83
|
+
*
|
|
84
|
+
* An SMTP submission has no CoreMail-composed body: the bytes are opaque and
|
|
85
|
+
* are owned by the immutable MIME tuple, so the descriptor carries only the
|
|
86
|
+
* SMTP envelope. `parts` is therefore empty, which is why such a descriptor is
|
|
87
|
+
* deliberately not routed through
|
|
88
|
+
* `normalizeCoreMailOutboundMessageDescriptor` (it requires at least one part).
|
|
89
|
+
*/
|
|
90
|
+
export const createCoreMailRawOutboundMessage = (envelopeArg) => ({
|
|
91
|
+
sender: { address: envelopeArg.mailFrom },
|
|
92
|
+
recipients: {
|
|
93
|
+
to: envelopeArg.rcptTo.map((recipientArg) => ({ address: recipientArg })),
|
|
94
|
+
},
|
|
95
|
+
subject: '',
|
|
96
|
+
parts: [],
|
|
97
|
+
});
|
|
150
98
|
export const createCoreMailSubmissionDigest = (idempotencyKeyArg, messageArg) => {
|
|
151
99
|
if (!idRegex.test(idempotencyKeyArg)) {
|
|
152
100
|
throw new Error('CoreMail idempotency key is invalid.');
|
|
153
101
|
}
|
|
154
102
|
return createSha256(JSON.stringify({
|
|
155
|
-
schemaVersion: 1,
|
|
156
103
|
idempotencyKey: idempotencyKeyArg,
|
|
157
104
|
message: messageArg,
|
|
158
105
|
}));
|
|
159
106
|
};
|
|
160
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZW1haWwudmFsaWRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NvcmVtYWlsLnZhbGlkYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBSXBELE1BQU0scUJBQXFCLEdBQUcsaUNBQWlDLENBQUM7QUFDaEUsTUFBTSx1QkFBdUIsR0FBRyx3Q0FBd0MsQ0FBQztBQUN6RSxNQUFNLE9BQU8sR0FBRyxxQ0FBcUMsQ0FBQztBQUV0RCxNQUFNLGtCQUFrQixHQUFHLENBQ3pCLFFBQWlCLEVBQ2pCLFFBQWdCLEVBQ1MsRUFBRTtJQUMzQixJQUNFLENBQUMsUUFBUTtXQUNOLE9BQU8sUUFBUSxLQUFLLFFBQVE7V0FDNUIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7V0FDdkIsQ0FDRCxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxTQUFTO2VBQ2pELE1BQU0sQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxDQUM1QyxFQUNELENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSwwQkFBMEIsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFDRCxPQUFPLFFBQW1DLENBQUM7QUFDN0MsQ0FBQyxDQUFDO0FBRUYsTUFBTSxnQkFBZ0IsR0FBRyxDQUN2QixTQUFrQyxFQUNsQyxXQUFxQixFQUNyQixXQUFxQixFQUNyQixRQUFnQixFQUNWLEVBQUU7SUFDUixNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsV0FBVyxFQUFFLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUMxRCxJQUNFLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7V0FDNUQsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUNoRSxDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsc0NBQXNDLENBQUMsQ0FBQztJQUNyRSxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sK0JBQStCLEdBQUcsQ0FBQyxRQUFpQixFQUFVLEVBQUU7SUFDM0UsSUFDRSxPQUFPLFFBQVEsS0FBSyxRQUFRO1dBQ3pCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQztXQUNuQixNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsR0FBRyxHQUFHO1dBQ3pDLFFBQVEsS0FBSyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQ3RDLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHFEQUFxRCxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNoRSxNQUFNLE1BQU0sR0FBRyxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzlELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsSUFDRSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUM7V0FDbkIsU0FBUyxDQUFDLE1BQU0sR0FBRyxFQUFFO1dBQ3JCLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztXQUN0QyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztXQUN6QixTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQztXQUN2QixTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztXQUN4QixNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7V0FDbkIsTUFBTSxDQUFDLE1BQU0sR0FBRyxHQUFHO1dBQ25CLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztXQUNqQixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUNyRSxDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxRQUFpQixFQUNtQyxFQUFFO0lBQ3RELE1BQU0sS0FBSyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN2RCxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2hFLElBQ0UsT0FBTyxLQUFLLENBQUMsUUFBUSxLQUFLLFFBQVE7V0FDL0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7V0FDNUIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztXQUN6QixLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQzVCLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUNELE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLEtBQUssRUFBRTtRQUNwQyxDQUFDLENBQUMsRUFBRTtRQUNKLENBQUMsQ0FBQywrQkFBK0IsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEQsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUNqRSxJQUFJLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0MsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFDRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQzlCLENBQUMsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUFHLENBQ3pDLGdCQUF3QixFQUN4QixVQUF5RSxFQUNuRSxFQUFFO0lBQ1IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztRQUMxRCxNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7SUFDdkUsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLENBQzlDLFFBQWlCLEVBQ2pCLFVBQXlFLEVBQy9ELEVBQUU7SUFDWixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsSUFBSTtTQUM3QywwQ0FBMEMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN4RCwyQkFBMkIsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUNoRSxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLENBQzlDLFdBQStELEVBQ3JELEVBQUUsQ0FBQyxDQUFDO0lBQ2QsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUU7SUFDekMsVUFBVSxFQUFFO1FBQ1YsRUFBRSxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7S0FDMUU7SUFDRCxPQUFPLEVBQUUsRUFBRTtJQUNYLEtBQUssRUFBRSxFQUFFO0NBQ1YsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsQ0FDNUMsaUJBQXlCLEVBQ3pCLFVBQW9CLEVBQzhCLEVBQUU7SUFDcEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQ0QsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNqQyxjQUFjLEVBQUUsaUJBQWlCO1FBQ2pDLE9BQU8sRUFBRSxVQUFVO0tBQ3BCLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQyxDQUFDIn0=
|
package/dist_ts/interfaces.d.ts
CHANGED
|
@@ -56,6 +56,22 @@ export interface ITransferAuthority {
|
|
|
56
56
|
serviceId: string;
|
|
57
57
|
bindingId: string;
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* How an outbound submission entered CoreMail. Records persisted before this
|
|
61
|
+
* discriminator existed carry no value and are read as 'api'.
|
|
62
|
+
*/
|
|
63
|
+
export type TCoreMailSubmissionSource = 'api' | 'smtp';
|
|
64
|
+
/**
|
|
65
|
+
* Exact-byte SMTP submission handed to CoreMail by an authenticated MSA
|
|
66
|
+
* session. CoreMail never parses or rewrites `rawMime`.
|
|
67
|
+
*/
|
|
68
|
+
export interface ICoreMailRawSubmissionInput {
|
|
69
|
+
envelope: {
|
|
70
|
+
from: string;
|
|
71
|
+
to: string[];
|
|
72
|
+
};
|
|
73
|
+
rawMime: Uint8Array;
|
|
74
|
+
}
|
|
59
75
|
export interface ISubmissionPartRecord {
|
|
60
76
|
partId: string;
|
|
61
77
|
kind: plugins.serveZoneInterfaces.data.TCoreMailPartKind;
|
|
@@ -76,6 +92,8 @@ export interface ICoreMailReadiness {
|
|
|
76
92
|
exactPurge: boolean;
|
|
77
93
|
controlBootstrap: boolean;
|
|
78
94
|
gateway: boolean;
|
|
95
|
+
/** False whenever the desired state asks for an SMTP listener that is not accepting submissions. */
|
|
96
|
+
smtpSubmission: boolean;
|
|
79
97
|
}
|
|
80
98
|
export interface ICoreMailAuthLimiterSnapshot {
|
|
81
99
|
inFlight: number;
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * as projectinfo from '@push.rocks/projectinfo';
|
|
|
6
6
|
export * as smartbucket from '@push.rocks/smartbucket';
|
|
7
7
|
export * as smartdata from '@push.rocks/smartdata';
|
|
8
8
|
export * as smartlog from '@push.rocks/smartlog';
|
|
9
|
+
export * as smartmta from '@push.rocks/smartmta';
|
|
9
10
|
export * as serveZoneInterfaces from '@serve.zone/interfaces';
|
|
10
11
|
export * as argon2 from 'argon2';
|
|
11
12
|
export * as nodeCrypto from 'node:crypto';
|
package/dist_ts/plugins.js
CHANGED
|
@@ -6,7 +6,8 @@ export * as projectinfo from '@push.rocks/projectinfo';
|
|
|
6
6
|
export * as smartbucket from '@push.rocks/smartbucket';
|
|
7
7
|
export * as smartdata from '@push.rocks/smartdata';
|
|
8
8
|
export * as smartlog from '@push.rocks/smartlog';
|
|
9
|
+
export * as smartmta from '@push.rocks/smartmta';
|
|
9
10
|
export * as serveZoneInterfaces from '@serve.zone/interfaces';
|
|
10
11
|
export * as argon2 from 'argon2';
|
|
11
12
|
export * as nodeCrypto from 'node:crypto';
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssc0JBQXNCLE1BQU0scUNBQXFDLENBQUM7QUFDOUUsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBQ25ELE9BQU8sS0FBSyxRQUFRLE1BQU0sc0JBQXNCLENBQUM7QUFDakQsT0FBTyxLQUFLLFFBQVEsTUFBTSxzQkFBc0IsQ0FBQztBQUNqRCxPQUFPLEtBQUssbUJBQW1CLE1BQU0sd0JBQXdCLENBQUM7QUFDOUQsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDakMsT0FBTyxLQUFLLFVBQVUsTUFBTSxhQUFhLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/coremail",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "32.0.0",
|
|
4
4
|
"description": "Authenticated mail persistence and delivery orchestration for serve.zone workloads.",
|
|
5
5
|
"main": "dist_ts/index.js",
|
|
6
6
|
"typings": "dist_ts/index.d.ts",
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"author": "Task Venture Capital GmbH",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@git.zone/tsbuild": "^4.
|
|
11
|
+
"@git.zone/tsbuild": "^4.5.0",
|
|
12
12
|
"@git.zone/tsdocker": "^3.5.8",
|
|
13
13
|
"@git.zone/tsrun": "^2.0.6",
|
|
14
|
-
"@git.zone/tstest": "6.
|
|
14
|
+
"@git.zone/tstest": "6.1.1",
|
|
15
15
|
"@git.zone/tswatch": "^3.3.5",
|
|
16
16
|
"@push.rocks/smartmongo": "9.0.0",
|
|
17
|
-
"@types/node": "26.5.
|
|
17
|
+
"@types/node": "26.5.1"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@api.global/typedrequest": "^8.0.4",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"@push.rocks/smartbucket": "^4.11.0",
|
|
26
26
|
"@push.rocks/smartdata": "^10.4.0",
|
|
27
27
|
"@push.rocks/smartlog": "^3.2.2",
|
|
28
|
-
"@
|
|
28
|
+
"@push.rocks/smartmta": "^9.6.1",
|
|
29
|
+
"@serve.zone/interfaces": "^32.0.0",
|
|
29
30
|
"argon2": "^0.45.1"
|
|
30
31
|
},
|
|
31
32
|
"files": [
|