@serve.zone/coremail 1.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 +50 -0
- package/changelog.md +10 -0
- package/cli.js +4 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.auth.d.ts +45 -0
- package/dist_ts/classes.auth.js +204 -0
- package/dist_ts/classes.config.d.ts +2 -0
- package/dist_ts/classes.config.js +72 -0
- package/dist_ts/classes.coremail.d.ts +41 -0
- package/dist_ts/classes.coremail.js +155 -0
- package/dist_ts/classes.desiredstate.d.ts +40 -0
- package/dist_ts/classes.desiredstate.js +382 -0
- package/dist_ts/classes.gateway.d.ts +62 -0
- package/dist_ts/classes.gateway.js +669 -0
- package/dist_ts/classes.inbound.d.ts +49 -0
- package/dist_ts/classes.inbound.js +702 -0
- package/dist_ts/classes.maintenance.d.ts +16 -0
- package/dist_ts/classes.maintenance.js +339 -0
- package/dist_ts/classes.models.d.ts +161 -0
- package/dist_ts/classes.models.js +595 -0
- package/dist_ts/classes.server.d.ts +40 -0
- package/dist_ts/classes.server.js +309 -0
- package/dist_ts/classes.storage.d.ts +32 -0
- package/dist_ts/classes.storage.js +317 -0
- package/dist_ts/classes.submissions.d.ts +33 -0
- package/dist_ts/classes.submissions.js +385 -0
- package/dist_ts/classes.transfer.d.ts +41 -0
- package/dist_ts/classes.transfer.js +289 -0
- package/dist_ts/coremail.cursor.d.ts +20 -0
- package/dist_ts/coremail.cursor.js +191 -0
- package/dist_ts/coremail.log.d.ts +3 -0
- package/dist_ts/coremail.log.js +11 -0
- package/dist_ts/coremail.mime.d.ts +8 -0
- package/dist_ts/coremail.mime.js +63 -0
- package/dist_ts/coremail.persistence.d.ts +148 -0
- package/dist_ts/coremail.persistence.js +695 -0
- package/dist_ts/coremail.quota.d.ts +29 -0
- package/dist_ts/coremail.quota.js +149 -0
- package/dist_ts/coremail.selectors.d.ts +3 -0
- package/dist_ts/coremail.selectors.js +21 -0
- package/dist_ts/coremail.validation.d.ts +9 -0
- package/dist_ts/coremail.validation.js +325 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +39 -0
- package/dist_ts/interfaces.d.ts +92 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +11 -0
- package/dist_ts/plugins.js +12 -0
- package/license.md +19 -0
- package/package.json +48 -0
- package/readme.md +199 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.auth.ts +321 -0
- package/ts/classes.config.ts +104 -0
- package/ts/classes.coremail.ts +249 -0
- package/ts/classes.desiredstate.ts +508 -0
- package/ts/classes.gateway.ts +811 -0
- package/ts/classes.inbound.ts +898 -0
- package/ts/classes.maintenance.ts +335 -0
- package/ts/classes.models.ts +530 -0
- package/ts/classes.server.ts +444 -0
- package/ts/classes.storage.ts +448 -0
- package/ts/classes.submissions.ts +554 -0
- package/ts/classes.transfer.ts +379 -0
- package/ts/coremail.cursor.ts +328 -0
- package/ts/coremail.log.ts +21 -0
- package/ts/coremail.mime.ts +94 -0
- package/ts/coremail.persistence.ts +1156 -0
- package/ts/coremail.quota.ts +214 -0
- package/ts/coremail.selectors.ts +35 -0
- package/ts/coremail.validation.ts +446 -0
- package/ts/index.ts +38 -0
- package/ts/interfaces.ts +109 -0
- package/ts/plugins.ts +11 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import {
|
|
3
|
+
CoreMailAuthenticationError,
|
|
4
|
+
CoreMailAuthorizationError,
|
|
5
|
+
CoreMailCapabilityDeniedError,
|
|
6
|
+
CoreMailAuth,
|
|
7
|
+
coreMailPreAuthDeadlineKey,
|
|
8
|
+
coreMailSessionKey,
|
|
9
|
+
} from './classes.auth.js';
|
|
10
|
+
import type { CoreMailDesiredStateService } from './classes.desiredstate.js';
|
|
11
|
+
import type { CoreMailGateway } from './classes.gateway.js';
|
|
12
|
+
import type { CoreMailInboundService } from './classes.inbound.js';
|
|
13
|
+
import type { CoreMailStorage } from './classes.storage.js';
|
|
14
|
+
import type { CoreMailSubmissionService } from './classes.submissions.js';
|
|
15
|
+
import type { CoreMailTransferService } from './classes.transfer.js';
|
|
16
|
+
import type {
|
|
17
|
+
ICoreMailConfig,
|
|
18
|
+
ICoreMailPeer,
|
|
19
|
+
ICoreMailReadiness,
|
|
20
|
+
ICoreMailWorkloadSession,
|
|
21
|
+
} from './interfaces.js';
|
|
22
|
+
import { CoreMailQuotaExceededError } from './coremail.quota.js';
|
|
23
|
+
|
|
24
|
+
type TErrorCode = plugins.serveZoneInterfaces.data.TCoreMailErrorCode;
|
|
25
|
+
|
|
26
|
+
interface ICoreMailTypedTools {
|
|
27
|
+
localData: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const privacySafeError = (
|
|
31
|
+
errorArg: unknown,
|
|
32
|
+
): plugins.typedrequest.TypedResponseError => {
|
|
33
|
+
let code: TErrorCode = 'INVALID_REQUEST';
|
|
34
|
+
let retryable = false;
|
|
35
|
+
if (errorArg instanceof CoreMailAuthenticationError) {
|
|
36
|
+
code = 'AUTHENTICATION_FAILED';
|
|
37
|
+
} else if (errorArg instanceof CoreMailCapabilityDeniedError) {
|
|
38
|
+
code = 'CAPABILITY_DENIED';
|
|
39
|
+
} else if (errorArg instanceof CoreMailAuthorizationError) {
|
|
40
|
+
code = 'AUTHORITY_REVOKED';
|
|
41
|
+
} else if (errorArg instanceof CoreMailQuotaExceededError) {
|
|
42
|
+
return new plugins.typedrequest.TypedResponseError('CoreMail request rejected.', {
|
|
43
|
+
code: 'QUOTA_EXCEEDED',
|
|
44
|
+
retryable: true,
|
|
45
|
+
...(errorArg.retryAfterMs === undefined
|
|
46
|
+
? {}
|
|
47
|
+
: { retryAfterMs: errorArg.retryAfterMs }),
|
|
48
|
+
} satisfies plugins.serveZoneInterfaces.data.ICoreMailErrorData);
|
|
49
|
+
} else if (
|
|
50
|
+
errorArg instanceof Error
|
|
51
|
+
&& errorArg.message.includes('gateway')
|
|
52
|
+
&& errorArg.message.includes('unavailable')
|
|
53
|
+
) {
|
|
54
|
+
code = 'GATEWAY_UNAVAILABLE';
|
|
55
|
+
retryable = true;
|
|
56
|
+
} else if (
|
|
57
|
+
errorArg instanceof Error
|
|
58
|
+
&& errorArg.message.includes('idempotency')
|
|
59
|
+
) {
|
|
60
|
+
code = 'IDEMPOTENCY_CONFLICT';
|
|
61
|
+
} else if (
|
|
62
|
+
errorArg instanceof Error
|
|
63
|
+
&& errorArg.message.includes('fence')
|
|
64
|
+
) {
|
|
65
|
+
code = 'STATE_CONFLICT';
|
|
66
|
+
retryable = true;
|
|
67
|
+
} else if (
|
|
68
|
+
errorArg instanceof Error
|
|
69
|
+
&& (
|
|
70
|
+
errorArg.message.includes('byte budget')
|
|
71
|
+
|| errorArg.message.includes('content budget')
|
|
72
|
+
|| errorArg.message.includes('exceeds')
|
|
73
|
+
)
|
|
74
|
+
) {
|
|
75
|
+
code = 'PAYLOAD_LIMIT_EXCEEDED';
|
|
76
|
+
}
|
|
77
|
+
return new plugins.typedrequest.TypedResponseError('CoreMail request rejected.', {
|
|
78
|
+
code,
|
|
79
|
+
retryable,
|
|
80
|
+
} satisfies plugins.serveZoneInterfaces.data.ICoreMailErrorData);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const asPeer = (
|
|
84
|
+
toolsArg: ICoreMailTypedTools | undefined,
|
|
85
|
+
): ICoreMailPeer => {
|
|
86
|
+
const peer = toolsArg?.localData?.peer as ICoreMailPeer | undefined;
|
|
87
|
+
if (
|
|
88
|
+
!peer
|
|
89
|
+
|| typeof peer.id !== 'string'
|
|
90
|
+
|| !(peer.data instanceof Map)
|
|
91
|
+
|| typeof peer.close !== 'function'
|
|
92
|
+
|| typeof peer.terminate !== 'function'
|
|
93
|
+
) {
|
|
94
|
+
throw new CoreMailAuthenticationError();
|
|
95
|
+
}
|
|
96
|
+
return peer;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const countCoreMailActiveSessions = (
|
|
100
|
+
sessionsArg: Iterable<ICoreMailWorkloadSession | undefined>,
|
|
101
|
+
bindingArg: plugins.serveZoneInterfaces.data.ICoreMailBindingDesiredState,
|
|
102
|
+
configEpochArg: number,
|
|
103
|
+
): Array<{ credentialId: string; version: number; count: number }> => {
|
|
104
|
+
const counts = new Map<
|
|
105
|
+
string,
|
|
106
|
+
{ credentialId: string; version: number; count: number }
|
|
107
|
+
>();
|
|
108
|
+
for (const session of sessionsArg) {
|
|
109
|
+
if (
|
|
110
|
+
session?.kind === 'workload'
|
|
111
|
+
&& session.tenantId === bindingArg.tenantId
|
|
112
|
+
&& session.serviceId === bindingArg.serviceId
|
|
113
|
+
&& session.bindingId === bindingArg.bindingId
|
|
114
|
+
&& session.bindingRevision === bindingArg.revision
|
|
115
|
+
&& session.configEpoch === configEpochArg
|
|
116
|
+
) {
|
|
117
|
+
const key = `${session.credentialId}\u0000${session.credentialVersion}`;
|
|
118
|
+
const count = counts.get(key);
|
|
119
|
+
counts.set(key, count
|
|
120
|
+
? { ...count, count: count.count + 1 }
|
|
121
|
+
: {
|
|
122
|
+
credentialId: session.credentialId,
|
|
123
|
+
version: session.credentialVersion,
|
|
124
|
+
count: 1,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return [...counts.values()].sort((leftArg, rightArg) =>
|
|
129
|
+
leftArg.version - rightArg.version
|
|
130
|
+
|| leftArg.credentialId.localeCompare(rightArg.credentialId)
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export class CoreMailServer {
|
|
135
|
+
public readonly router:
|
|
136
|
+
plugins.typedrequest.TypedRouter<plugins.typedrequestInterfaces.ITypedRequest> =
|
|
137
|
+
new plugins.typedrequest.TypedRouter();
|
|
138
|
+
public readonly typedServer: plugins.typedserver.TypedServer;
|
|
139
|
+
private preAuthSweepTimer: ReturnType<typeof setInterval> | null = null;
|
|
140
|
+
|
|
141
|
+
public constructor(
|
|
142
|
+
private readonly config: ICoreMailConfig,
|
|
143
|
+
private readonly database: plugins.smartdata.SmartdataDb,
|
|
144
|
+
private readonly storage: CoreMailStorage,
|
|
145
|
+
private readonly transfers: CoreMailTransferService,
|
|
146
|
+
private readonly desiredState: CoreMailDesiredStateService,
|
|
147
|
+
private readonly auth: CoreMailAuth,
|
|
148
|
+
private readonly submissions: CoreMailSubmissionService,
|
|
149
|
+
private readonly inbound: CoreMailInboundService,
|
|
150
|
+
private readonly gateway: CoreMailGateway,
|
|
151
|
+
private readonly now: () => number = Date.now,
|
|
152
|
+
) {
|
|
153
|
+
this.registerHandlers();
|
|
154
|
+
this.typedServer = new plugins.typedserver.TypedServer({
|
|
155
|
+
port: config.port,
|
|
156
|
+
cors: false,
|
|
157
|
+
authorityValidation: 'strict',
|
|
158
|
+
connectionTimeout: 15_000,
|
|
159
|
+
headersTimeout: 10_000,
|
|
160
|
+
requestTimeout: 2 * 60_000,
|
|
161
|
+
websocketMaxPayloadBytes:
|
|
162
|
+
plugins.serveZoneInterfaces.data.coreMailLimits.controlMessageBytes,
|
|
163
|
+
healthzEndpoint: false,
|
|
164
|
+
noCache: true,
|
|
165
|
+
compression: false,
|
|
166
|
+
surfaces: [{
|
|
167
|
+
name: 'coremail',
|
|
168
|
+
match: {
|
|
169
|
+
hostnames: config.hostnames,
|
|
170
|
+
pathPrefixes: ['/'],
|
|
171
|
+
websocketPathPrefixes: ['/socket'],
|
|
172
|
+
},
|
|
173
|
+
typedRequestPath: false,
|
|
174
|
+
websocketTypedRouter: this.router,
|
|
175
|
+
cors: false,
|
|
176
|
+
noCache: true,
|
|
177
|
+
includeBuiltinTypedHandlers: false,
|
|
178
|
+
websocketAdmission: (contextArg) => {
|
|
179
|
+
if (contextArg.path !== '/socket') {
|
|
180
|
+
return new Response('Not Found', { status: 404 });
|
|
181
|
+
}
|
|
182
|
+
contextArg.state[coreMailPreAuthDeadlineKey] = this.now() + 5_000;
|
|
183
|
+
return true;
|
|
184
|
+
},
|
|
185
|
+
httpHandler: async (contextArg) => {
|
|
186
|
+
const transferResponse = await this.transfers.handleHttp(contextArg);
|
|
187
|
+
if (transferResponse) {
|
|
188
|
+
return transferResponse;
|
|
189
|
+
}
|
|
190
|
+
if (
|
|
191
|
+
(contextArg.method === 'GET' || contextArg.method === 'HEAD')
|
|
192
|
+
&& contextArg.path === '/live'
|
|
193
|
+
) {
|
|
194
|
+
return new Response(
|
|
195
|
+
contextArg.method === 'HEAD' ? null : JSON.stringify({ live: true }),
|
|
196
|
+
{
|
|
197
|
+
status: 200,
|
|
198
|
+
headers: {
|
|
199
|
+
'Content-Type': 'application/json',
|
|
200
|
+
'Cache-Control': 'no-store',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
if (
|
|
206
|
+
(contextArg.method === 'GET' || contextArg.method === 'HEAD')
|
|
207
|
+
&& contextArg.path === '/ready'
|
|
208
|
+
) {
|
|
209
|
+
const readiness = await this.getReadiness();
|
|
210
|
+
const ready = Object.values(readiness).every(Boolean);
|
|
211
|
+
return new Response(
|
|
212
|
+
contextArg.method === 'HEAD' ? null : JSON.stringify(readiness),
|
|
213
|
+
{
|
|
214
|
+
status: ready ? 200 : 503,
|
|
215
|
+
headers: {
|
|
216
|
+
'Content-Type': 'application/json',
|
|
217
|
+
'Cache-Control': 'no-store',
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
},
|
|
224
|
+
securityHeaders: {
|
|
225
|
+
xFrameOptions: 'DENY',
|
|
226
|
+
xContentTypeOptions: true,
|
|
227
|
+
referrerPolicy: 'no-referrer',
|
|
228
|
+
permissionsPolicy: {},
|
|
229
|
+
crossOriginOpenerPolicy: 'same-origin',
|
|
230
|
+
crossOriginResourcePolicy: 'same-origin',
|
|
231
|
+
},
|
|
232
|
+
}],
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public async start(): Promise<void> {
|
|
237
|
+
await this.typedServer.start();
|
|
238
|
+
this.preAuthSweepTimer = setInterval(() => {
|
|
239
|
+
const now = this.now();
|
|
240
|
+
for (const peer of this.typedServer.smartServe.getWebSocketConnections()) {
|
|
241
|
+
const deadline = Number(peer.context.state[coreMailPreAuthDeadlineKey]);
|
|
242
|
+
if (
|
|
243
|
+
!peer.data.has(coreMailSessionKey)
|
|
244
|
+
&& (!Number.isSafeInteger(deadline) || deadline < now)
|
|
245
|
+
) {
|
|
246
|
+
peer.terminate();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}, 250);
|
|
250
|
+
this.preAuthSweepTimer.unref?.();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public async stop(): Promise<void> {
|
|
254
|
+
if (this.preAuthSweepTimer) {
|
|
255
|
+
clearInterval(this.preAuthSweepTimer);
|
|
256
|
+
this.preAuthSweepTimer = null;
|
|
257
|
+
}
|
|
258
|
+
await this.typedServer.stop();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
public activeSessionCounts(
|
|
262
|
+
bindingArg: plugins.serveZoneInterfaces.data.ICoreMailBindingDesiredState,
|
|
263
|
+
configEpochArg: number,
|
|
264
|
+
): Array<{ credentialId: string; version: number; count: number }> {
|
|
265
|
+
if (!this.typedServer.smartServe) {
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
return countCoreMailActiveSessions(
|
|
269
|
+
this.typedServer.smartServe.getWebSocketConnections().map((peerArg) =>
|
|
270
|
+
peerArg.data.get(coreMailSessionKey) as ICoreMailWorkloadSession | undefined
|
|
271
|
+
),
|
|
272
|
+
bindingArg,
|
|
273
|
+
configEpochArg,
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public async getReadiness(): Promise<ICoreMailReadiness> {
|
|
278
|
+
const [database, objectStorage, desiredState] = await Promise.all([
|
|
279
|
+
this.database.checkReadiness({ timeoutMs: 1_500 })
|
|
280
|
+
.then((resultArg) => resultArg.ready)
|
|
281
|
+
.catch(() => false),
|
|
282
|
+
this.storage.checkReadiness().catch(() => false),
|
|
283
|
+
this.desiredState.getActiveDesiredState().catch(() => null),
|
|
284
|
+
]);
|
|
285
|
+
return {
|
|
286
|
+
live: true,
|
|
287
|
+
database,
|
|
288
|
+
objectStorage,
|
|
289
|
+
exactUpload: objectStorage,
|
|
290
|
+
exactPurge: objectStorage,
|
|
291
|
+
controlBootstrap: true,
|
|
292
|
+
gateway: Boolean(desiredState) && this.gateway.isReady(),
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private registerHandlers(): void {
|
|
297
|
+
this.addHandler<
|
|
298
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailAuthenticateControl
|
|
299
|
+
>('coreMailAuthenticateControl', async (requestArg, toolsArg) => {
|
|
300
|
+
const peer = asPeer(toolsArg);
|
|
301
|
+
const session = await this.auth.authenticateControl(peer, requestArg);
|
|
302
|
+
return {
|
|
303
|
+
authenticated: true,
|
|
304
|
+
credentialId: session.credentialId,
|
|
305
|
+
replica: { ...this.config.replica },
|
|
306
|
+
credentialVersion: session.credentialVersion,
|
|
307
|
+
};
|
|
308
|
+
});
|
|
309
|
+
this.addHandler<
|
|
310
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailAuthenticateWorkload
|
|
311
|
+
>('coreMailAuthenticateWorkload', async (requestArg, toolsArg) => {
|
|
312
|
+
const session = await this.auth.authenticateWorkload(asPeer(toolsArg), requestArg);
|
|
313
|
+
return {
|
|
314
|
+
authenticated: true,
|
|
315
|
+
credentialId: session.credentialId,
|
|
316
|
+
credentialVersion: session.credentialVersion,
|
|
317
|
+
bindingState: session.bindingState,
|
|
318
|
+
capabilities: [...session.capabilities],
|
|
319
|
+
allowedOperations: [...session.allowedOperations],
|
|
320
|
+
coreMailTransferOrigin: session.coreMailTransferOrigin,
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
this.addHandler<
|
|
324
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailPrepareDesiredStateUpload
|
|
325
|
+
>('coreMailPrepareDesiredStateUpload', async (requestArg, toolsArg) => {
|
|
326
|
+
this.auth.requireControlSession(asPeer(toolsArg));
|
|
327
|
+
return await this.desiredState.prepare(requestArg);
|
|
328
|
+
});
|
|
329
|
+
this.addHandler<
|
|
330
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailApplyDesiredState
|
|
331
|
+
>('coreMailApplyDesiredState', async (requestArg, toolsArg) => {
|
|
332
|
+
this.auth.requireControlSession(asPeer(toolsArg));
|
|
333
|
+
return { status: await this.desiredState.apply(requestArg) };
|
|
334
|
+
});
|
|
335
|
+
this.addHandler<
|
|
336
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailGetReconciliationStatus
|
|
337
|
+
>('coreMailGetReconciliationStatus', async (requestArg, toolsArg) => {
|
|
338
|
+
this.auth.requireControlSession(asPeer(toolsArg));
|
|
339
|
+
return { status: await this.desiredState.getStatus(requestArg) };
|
|
340
|
+
});
|
|
341
|
+
this.addHandler<
|
|
342
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailPrepareOutboundSubmission
|
|
343
|
+
>('coreMailPrepareOutboundSubmission', async (requestArg, toolsArg) => {
|
|
344
|
+
const { session, binding } = await this.auth.requireWorkloadSession(
|
|
345
|
+
asPeer(toolsArg),
|
|
346
|
+
'coreMailPrepareOutboundSubmission',
|
|
347
|
+
);
|
|
348
|
+
return await this.submissions.prepare(session, binding, requestArg);
|
|
349
|
+
});
|
|
350
|
+
this.addHandler<
|
|
351
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailPrepareOutboundPartUpload
|
|
352
|
+
>('coreMailPrepareOutboundPartUpload', async (requestArg, toolsArg) => {
|
|
353
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
354
|
+
asPeer(toolsArg),
|
|
355
|
+
'coreMailPrepareOutboundPartUpload',
|
|
356
|
+
);
|
|
357
|
+
return await this.submissions.preparePartUpload(session, requestArg);
|
|
358
|
+
});
|
|
359
|
+
this.addHandler<
|
|
360
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailCompleteOutboundPartUpload
|
|
361
|
+
>('coreMailCompleteOutboundPartUpload', async (requestArg, toolsArg) => {
|
|
362
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
363
|
+
asPeer(toolsArg),
|
|
364
|
+
'coreMailCompleteOutboundPartUpload',
|
|
365
|
+
);
|
|
366
|
+
return await this.submissions.completePartUpload(session, requestArg);
|
|
367
|
+
});
|
|
368
|
+
this.addHandler<
|
|
369
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailFinalizeOutboundSubmission
|
|
370
|
+
>('coreMailFinalizeOutboundSubmission', async (requestArg, toolsArg) => {
|
|
371
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
372
|
+
asPeer(toolsArg),
|
|
373
|
+
'coreMailFinalizeOutboundSubmission',
|
|
374
|
+
);
|
|
375
|
+
return await this.submissions.finalize(session, requestArg);
|
|
376
|
+
});
|
|
377
|
+
this.addHandler<
|
|
378
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailGetOutboundSubmission
|
|
379
|
+
>('coreMailGetOutboundSubmission', async (requestArg, toolsArg) => {
|
|
380
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
381
|
+
asPeer(toolsArg),
|
|
382
|
+
'coreMailGetOutboundSubmission',
|
|
383
|
+
);
|
|
384
|
+
return await this.submissions.get(session, requestArg);
|
|
385
|
+
});
|
|
386
|
+
this.addHandler<
|
|
387
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailListInboundDeliveries
|
|
388
|
+
>('coreMailListInboundDeliveries', async (requestArg, toolsArg) => {
|
|
389
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
390
|
+
asPeer(toolsArg),
|
|
391
|
+
'coreMailListInboundDeliveries',
|
|
392
|
+
);
|
|
393
|
+
return await this.inbound.listDeliveries(session, requestArg);
|
|
394
|
+
});
|
|
395
|
+
this.addHandler<
|
|
396
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailPrepareInboundFetch
|
|
397
|
+
>('coreMailPrepareInboundFetch', async (requestArg, toolsArg) => {
|
|
398
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
399
|
+
asPeer(toolsArg),
|
|
400
|
+
'coreMailPrepareInboundFetch',
|
|
401
|
+
);
|
|
402
|
+
return await this.inbound.prepareFetch(session, requestArg);
|
|
403
|
+
});
|
|
404
|
+
this.addHandler<
|
|
405
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailCompleteInboundFetch
|
|
406
|
+
>('coreMailCompleteInboundFetch', async (requestArg, toolsArg) => {
|
|
407
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
408
|
+
asPeer(toolsArg),
|
|
409
|
+
'coreMailCompleteInboundFetch',
|
|
410
|
+
);
|
|
411
|
+
return await this.inbound.completeFetch(session, requestArg);
|
|
412
|
+
});
|
|
413
|
+
this.addHandler<
|
|
414
|
+
plugins.serveZoneInterfaces.requests.coremail.IReq_CoreMailAcknowledgeInboundDelivery
|
|
415
|
+
>('coreMailAcknowledgeInboundDelivery', async (requestArg, toolsArg) => {
|
|
416
|
+
const { session } = await this.auth.requireWorkloadSession(
|
|
417
|
+
asPeer(toolsArg),
|
|
418
|
+
'coreMailAcknowledgeInboundDelivery',
|
|
419
|
+
);
|
|
420
|
+
return await this.inbound.acknowledge(session, requestArg);
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private addHandler<
|
|
425
|
+
TRequest extends plugins.typedrequestInterfaces.ITypedRequest,
|
|
426
|
+
>(
|
|
427
|
+
methodArg: TRequest['method'],
|
|
428
|
+
handlerArg: (
|
|
429
|
+
requestArg: TRequest['request'],
|
|
430
|
+
toolsArg: ICoreMailTypedTools | undefined,
|
|
431
|
+
) => Promise<TRequest['response']>,
|
|
432
|
+
): void {
|
|
433
|
+
this.router.addTypedHandler(new plugins.typedrequest.TypedHandler<TRequest>(
|
|
434
|
+
methodArg,
|
|
435
|
+
async (requestArg, toolsArg) => {
|
|
436
|
+
try {
|
|
437
|
+
return await handlerArg(requestArg, toolsArg);
|
|
438
|
+
} catch (error) {
|
|
439
|
+
throw privacySafeError(error);
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
));
|
|
443
|
+
}
|
|
444
|
+
}
|