@push.rocks/smartjmap 1.0.0 → 2.1.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.
@@ -1,4 +1,94 @@
1
- import * as plugins from './smartjmap.plugins.js';
1
+ import * as plugins from "./smartjmap.plugins.js";
2
+ import { JMAP_CORE_CAPABILITY, JMAP_MAIL_CAPABILITY, JMAP_SUBMISSION_CAPABILITY, } from "./classes.jmapclient.js";
3
+ import {} from "./interfaces.backend.js";
4
+ import { MemoryMailBackend } from "./classes.memorymailbackend.js";
5
+ /**
6
+ * Semantic capability marker for the bounded streaming-upload server surface.
7
+ * Consumers must check this exact value before relying on streaming backend
8
+ * uploads, upload concurrency limits, Bearer-only challenges, or error mapping.
9
+ */
10
+ export const JMAP_SERVER_STREAMING_API_VERSION = 1;
11
+ /** The advertised — and enforced — RFC 8620 core limits. */
12
+ export const JMAP_SERVER_LIMITS = {
13
+ maxSizeUpload: 50_000_000,
14
+ maxConcurrentUpload: 4,
15
+ maxSizeRequest: 10_000_000,
16
+ maxConcurrentRequests: 4,
17
+ maxCallsInRequest: 16,
18
+ maxObjectsInGet: 500,
19
+ maxObjectsInSet: 500,
20
+ };
21
+ /** The session object never changes at runtime, so its state is constant. */
22
+ const SESSION_STATE = "0";
23
+ /** Default Email/get properties per RFC 8621 §4.2. */
24
+ const DEFAULT_EMAIL_PROPERTIES = [
25
+ "id",
26
+ "blobId",
27
+ "threadId",
28
+ "mailboxIds",
29
+ "keywords",
30
+ "size",
31
+ "receivedAt",
32
+ "messageId",
33
+ "inReplyTo",
34
+ "references",
35
+ "sender",
36
+ "from",
37
+ "to",
38
+ "cc",
39
+ "bcc",
40
+ "replyTo",
41
+ "subject",
42
+ "sentAt",
43
+ "hasAttachment",
44
+ "preview",
45
+ "bodyValues",
46
+ "textBody",
47
+ "htmlBody",
48
+ "attachments",
49
+ ];
50
+ const KNOWN_EMAIL_PROPERTIES = new Set(DEFAULT_EMAIL_PROPERTIES);
51
+ const MAILBOX_PROPERTIES = [
52
+ "id",
53
+ "name",
54
+ "parentId",
55
+ "role",
56
+ "sortOrder",
57
+ "totalEmails",
58
+ "unreadEmails",
59
+ "totalThreads",
60
+ "unreadThreads",
61
+ "myRights",
62
+ "isSubscribed",
63
+ ];
64
+ const KNOWN_MAILBOX_PROPERTIES = new Set(MAILBOX_PROPERTIES);
65
+ const SUPPORTED_EMAIL_FILTER_KEYS = new Set([
66
+ "inMailbox",
67
+ "text",
68
+ "subject",
69
+ "from",
70
+ "to",
71
+ "before",
72
+ "after",
73
+ "hasKeyword",
74
+ "notKeyword",
75
+ ]);
76
+ const DEFAULT_MAILBOX_RIGHTS = {
77
+ mayReadItems: true,
78
+ mayAddItems: true,
79
+ mayRemoveItems: true,
80
+ maySetSeen: true,
81
+ maySetKeywords: true,
82
+ mayCreateChild: true,
83
+ mayRename: true,
84
+ mayDelete: true,
85
+ maySubmit: true,
86
+ };
87
+ const textEncoder = new TextEncoder();
88
+ /** Ensures bytes are backed by a plain ArrayBuffer so they satisfy BodyInit. */
89
+ const asBodyBytes = (data) => data.buffer instanceof ArrayBuffer
90
+ ? data
91
+ : new Uint8Array(data);
2
92
  /** Error type used inside method dispatch; rendered as a JMAP `error` method response. */
3
93
  class JmapServerMethodError extends Error {
4
94
  constructor(type, description) {
@@ -6,868 +96,1906 @@ class JmapServerMethodError extends Error {
6
96
  this.type = type;
7
97
  }
8
98
  }
99
+ class JmapRequestBodyError extends Error {
100
+ constructor(reason) {
101
+ super(reason);
102
+ this.reason = reason;
103
+ }
104
+ }
105
+ /** UTF-8-safe truncation: cuts at a codepoint boundary at or below maxBytes. */
106
+ const truncateUtf8 = (value, maxBytes) => {
107
+ const bytes = textEncoder.encode(value);
108
+ if (bytes.length <= maxBytes) {
109
+ return value;
110
+ }
111
+ let end = maxBytes;
112
+ while (end > 0 && (bytes[end] & 0b1100_0000) === 0b1000_0000) {
113
+ end--;
114
+ }
115
+ return new TextDecoder().decode(bytes.subarray(0, end));
116
+ };
117
+ /**
118
+ * Evaluates an RFC 6901 JSON pointer with the RFC 8620 §3.7 extension: a `*`
119
+ * token applied to an array maps the rest of the pointer over every item,
120
+ * flattening one array level. Throws on any unresolvable path.
121
+ */
122
+ const evalJsonPointer = (root, pointer) => {
123
+ if (pointer === "") {
124
+ return root;
125
+ }
126
+ if (!pointer.startsWith("/")) {
127
+ throw new Error(`Invalid JSON pointer "${pointer}".`);
128
+ }
129
+ const tokens = pointer.slice(1).split("/");
130
+ const evaluate = (value, index) => {
131
+ if (index === tokens.length) {
132
+ return value;
133
+ }
134
+ const token = tokens[index].replaceAll("~1", "/").replaceAll("~0", "~");
135
+ if (Array.isArray(value)) {
136
+ if (token === "*") {
137
+ const results = value.map((item) => evaluate(item, index + 1));
138
+ return results.some((result) => Array.isArray(result))
139
+ ? results.flatMap((result) => (Array.isArray(result) ? result : [result]))
140
+ : results;
141
+ }
142
+ const arrayIndex = Number(token);
143
+ if (!Number.isInteger(arrayIndex) || arrayIndex < 0 ||
144
+ arrayIndex >= value.length) {
145
+ throw new Error(`JSON pointer index "${token}" is out of range.`);
146
+ }
147
+ return evaluate(value[arrayIndex], index + 1);
148
+ }
149
+ if (value !== null && typeof value === "object" && token in value) {
150
+ return evaluate(value[token], index + 1);
151
+ }
152
+ throw new Error(`JSON pointer token "${token}" does not resolve.`);
153
+ };
154
+ return evaluate(root, 0);
155
+ };
9
156
  /**
10
- * A minimal in-memory JMAP server (RFC 8620 core + RFC 8621 mail subset)
11
- * for offline testing. Serves the session resource at /.well-known/jmap and
12
- * /jmap/session, the API at /jmap/api, blob downloads at /jmap/download/...,
13
- * and StateChange pushes via SSE at /jmap/eventsource.
157
+ * A JMAP server core (RFC 8620) with the RFC 8621 mail method surface,
158
+ * dispatching all storage into a pluggable `IJmapMailBackend`.
159
+ *
160
+ * The primary API is the web-standard `fetchHandler(request)` — mount it in
161
+ * any Request/Response runtime (Deno, Bun, service workers, Node ≥18). The
162
+ * `start(port)`/`stop()` pair wraps it in a node:http server for convenience.
163
+ *
164
+ * Endpoints: session (`/.well-known/jmap`, `/jmap/session`), API
165
+ * (`/jmap/api`), upload (`/jmap/upload/{accountId}`), download
166
+ * (`/jmap/download/{accountId}/{blobId}/{name}?type=`), and event source
167
+ * (`/jmap/eventsource` — SSE StateChange pushes per RFC 8620 §7.3).
168
+ *
169
+ * With no options this behaves as the offline test helper: an in-memory
170
+ * backend plus a static credential registry (`addUser`/`addBearerToken`).
14
171
  */
15
172
  export class JmapServer {
16
- constructor() {
17
- this.users = new Map();
173
+ constructor(options = {}) {
174
+ this.registry = new Map();
175
+ this.httpServer = null;
18
176
  this.sockets = new Set();
19
- this.eventStreams = new Map();
20
- this.server = plugins.http.createServer((req, res) => {
21
- this.handleRequest(req, res);
22
- });
23
- this.server.on('connection', (socket) => {
24
- this.sockets.add(socket);
25
- socket.on('close', () => {
26
- this.sockets.delete(socket);
27
- });
28
- });
177
+ this.eventStreams = new Set();
178
+ this.changeFeedUnsubscribe = null;
179
+ this.cleanupErrors = [];
180
+ this.activeApiRequests = 0;
181
+ this.activeUploadRequests = 0;
182
+ this.activeUploadsByPrincipal = new Map();
183
+ this.activeNodeRequests = new Set();
184
+ this.nodeRequestControllers = new Set();
185
+ this.stopping = false;
186
+ this.options = options;
187
+ this.backend = options.backend ?? new MemoryMailBackend();
188
+ const authenticationChallenges = options.authenticationChallenges ?? [
189
+ 'Bearer realm="jmap"',
190
+ 'Basic realm="jmap"',
191
+ ];
192
+ if (authenticationChallenges.length === 0 ||
193
+ authenticationChallenges.some((challenge) => typeof challenge !== "string" || !challenge.trim() ||
194
+ /[\r\n]/.test(challenge))) {
195
+ throw new Error("authenticationChallenges must contain safe non-empty challenge values.");
196
+ }
197
+ this.authenticationChallenges = authenticationChallenges
198
+ .map((value) => value.trim())
199
+ .join(", ");
200
+ this.limits = { ...JMAP_SERVER_LIMITS, ...options.limits };
201
+ for (const [name, value] of Object.entries(this.limits)) {
202
+ if (!Number.isSafeInteger(value) || value <= 0) {
203
+ throw new Error(`JMAP limit ${name} must be a positive safe integer.`);
204
+ }
205
+ }
206
+ this.maxConcurrentUploadServer = options.maxConcurrentUploadServer ??
207
+ this.limits.maxConcurrentUpload;
208
+ if (!Number.isSafeInteger(this.maxConcurrentUploadServer) ||
209
+ this.maxConcurrentUploadServer < this.limits.maxConcurrentUpload) {
210
+ throw new Error("maxConcurrentUploadServer must be a safe integer at least as large as maxConcurrentUpload.");
211
+ }
29
212
  }
30
213
  // ======================
31
- // store management
214
+ // default auth registry
32
215
  // ======================
216
+ /**
217
+ * Registers Basic credentials in the default authenticator's registry.
218
+ * Only consulted when no custom `authenticate` option is set. Account data
219
+ * itself lives in the backend (the memory backend auto-creates accounts).
220
+ */
33
221
  addUser(username, password) {
34
- if (this.users.has(username)) {
222
+ if (this.registry.has(username)) {
35
223
  throw new Error(`User "${username}" already exists.`);
36
224
  }
37
- const email = username.includes('@') ? username : `${username}@example.com`;
38
- this.users.set(username, {
39
- username,
40
- password,
41
- bearerTokens: new Set(),
42
- accountId: `account_${username}`,
43
- mailboxes: new Map(),
44
- emails: new Map(),
45
- blobs: new Map(),
46
- submissions: new Map(),
47
- identities: [{ id: 'identity_1', name: username, email, mayDelete: false }],
48
- state: 0,
49
- changes: [],
50
- idCounter: 0,
51
- });
225
+ this.registry.set(username, { password, bearerTokens: new Set() });
52
226
  }
53
- /** Registers a valid Bearer token for a user. */
227
+ /** Registers a valid Bearer token for a user in the default authenticator. */
54
228
  addBearerToken(username, token) {
55
- const user = this.requireUser(username);
56
- user.bearerTokens.add(token);
57
- }
58
- createMailbox(username, name, role) {
59
- const user = this.requireUser(username);
60
- for (const mailbox of user.mailboxes.values()) {
61
- if (mailbox.name === name) {
62
- throw new Error(`Mailbox "${name}" already exists for user "${username}".`);
63
- }
64
- }
65
- const id = `mailbox_${++user.idCounter}`;
66
- user.mailboxes.set(id, {
67
- id,
68
- name,
69
- role: role ?? null,
70
- parentId: null,
71
- sortOrder: user.mailboxes.size,
72
- });
73
- return id;
74
- }
75
- /** Seeds an email into a user's mailbox; bumps state and pushes a StateChange. Returns the email id. */
76
- addEmail(username, mailboxName, input) {
77
- const user = this.requireUser(username);
78
- const mailbox = Array.from(user.mailboxes.values()).find((candidate) => candidate.name === mailboxName || candidate.role === mailboxName);
79
- if (!mailbox) {
80
- throw new Error(`Mailbox "${mailboxName}" does not exist for user "${username}".`);
81
- }
82
- const from = Array.isArray(input.from) ? input.from : [input.from];
83
- const to = Array.isArray(input.to) ? input.to : [input.to];
84
- const id = `email_${++user.idCounter}`;
85
- const receivedAt = input.receivedAt ?? new Date().toISOString();
86
- const textBody = input.textBody ?? '';
87
- // raw message blob for Email/get blobId + downloads
88
- const blobId = `blob_${id}`;
89
- const rawLines = [
90
- `From: ${from.map((address) => address.email).join(', ')}`,
91
- `To: ${to.map((address) => address.email).join(', ')}`,
92
- `Subject: ${input.subject ?? ''}`,
93
- `Date: ${receivedAt}`,
94
- '',
95
- textBody,
96
- ];
97
- user.blobs.set(blobId, {
98
- data: Buffer.from(rawLines.join('\r\n'), 'utf8'),
99
- type: 'message/rfc822',
100
- name: `${id}.eml`,
101
- });
102
- const bodyValues = {
103
- text: { value: textBody, isTruncated: false },
104
- };
105
- const textBodyParts = [{ partId: 'text', type: 'text/plain', size: textBody.length }];
106
- const htmlBodyParts = [];
107
- if (typeof input.htmlBody === 'string') {
108
- bodyValues.html = { value: input.htmlBody, isTruncated: false };
109
- htmlBodyParts.push({ partId: 'html', type: 'text/html', size: input.htmlBody.length });
110
- }
111
- const attachmentParts = [];
112
- for (const [index, attachment] of (input.attachments ?? []).entries()) {
113
- const attachmentBlobId = `blob_${id}_att${index + 1}`;
114
- const data = Buffer.from(attachment.content);
115
- user.blobs.set(attachmentBlobId, {
116
- data,
117
- type: attachment.type,
118
- name: attachment.name,
119
- });
120
- attachmentParts.push({
121
- partId: null,
122
- blobId: attachmentBlobId,
123
- name: attachment.name,
124
- type: attachment.type,
125
- size: data.length,
126
- disposition: 'attachment',
127
- });
229
+ const entry = this.registry.get(username);
230
+ if (!entry) {
231
+ throw new Error(`User "${username}" does not exist.`);
128
232
  }
129
- const email = {
130
- id,
131
- blobId,
132
- threadId: `thread_${id}`,
133
- mailboxIds: { [mailbox.id]: true },
134
- keywords: input.keywords ?? {},
135
- size: textBody.length,
136
- receivedAt,
137
- sentAt: receivedAt,
138
- subject: input.subject ?? null,
139
- from,
140
- to,
141
- cc: input.cc ?? null,
142
- bcc: input.bcc ?? null,
143
- replyTo: null,
144
- hasAttachment: attachmentParts.length > 0,
145
- preview: textBody.slice(0, 100),
146
- bodyValues,
147
- textBody: textBodyParts,
148
- htmlBody: htmlBodyParts,
149
- attachments: attachmentParts,
150
- };
151
- user.emails.set(id, email);
152
- this.bumpState(user, { created: [id] });
153
- return id;
233
+ entry.bearerTokens.add(token);
154
234
  }
155
235
  // ======================
156
- // lifecycle
236
+ // lifecycle (node wrapper)
157
237
  // ======================
158
- /** Starts the server. Resolves with the bound port (pass 0 for an ephemeral port). */
238
+ /** Starts a node:http server around fetchHandler. Resolves with the bound port (pass 0 for ephemeral). */
159
239
  start(port) {
240
+ if (this.httpServer) {
241
+ throw new Error("JmapServer is already started.");
242
+ }
243
+ this.stopping = false;
244
+ const server = plugins.http.createServer((req, res) => {
245
+ if (this.stopping) {
246
+ res.writeHead(503, {
247
+ "content-type": "application/problem+json",
248
+ "connection": "close",
249
+ });
250
+ res.end(JSON.stringify({
251
+ type: "about:blank",
252
+ status: 503,
253
+ detail: "JMAP server is shutting down.",
254
+ }));
255
+ return;
256
+ }
257
+ const requestAbortController = new AbortController();
258
+ this.nodeRequestControllers.add(requestAbortController);
259
+ let requestTask;
260
+ requestTask = this.handleNodeRequest(req, res, requestAbortController)
261
+ .finally(() => {
262
+ this.nodeRequestControllers.delete(requestAbortController);
263
+ this.activeNodeRequests.delete(requestTask);
264
+ });
265
+ this.activeNodeRequests.add(requestTask);
266
+ void requestTask;
267
+ });
268
+ const onConnection = (socket) => {
269
+ this.sockets.add(socket);
270
+ socket.on("close", () => {
271
+ this.sockets.delete(socket);
272
+ });
273
+ };
274
+ server.on("connection", onConnection);
275
+ this.httpServer = server;
160
276
  return new Promise((resolve, reject) => {
161
- this.server.once('error', reject);
162
- this.server.listen(port, () => {
163
- const address = this.server.address();
164
- const boundPort = typeof address === 'object' && address ? address.port : port;
277
+ const onStartupError = (error) => {
278
+ server.off("listening", onListening);
279
+ server.off("connection", onConnection);
280
+ if (this.httpServer === server) {
281
+ this.httpServer = null;
282
+ }
283
+ try {
284
+ server.close(() => undefined);
285
+ }
286
+ catch {
287
+ // The failed listener never reached the listening state.
288
+ }
289
+ reject(error);
290
+ };
291
+ const onListening = () => {
292
+ server.off("error", onStartupError);
293
+ server.on("error", (error) => {
294
+ this.cleanupErrors.push(error);
295
+ });
296
+ const address = server.address();
297
+ const boundPort = typeof address === "object" && address
298
+ ? address.port
299
+ : port;
165
300
  resolve(boundPort);
166
- });
301
+ };
302
+ server.once("error", onStartupError);
303
+ server.once("listening", onListening);
304
+ server.listen(port);
167
305
  });
168
306
  }
169
- /** Stops the server, ending open event streams and destroying open connections. */
170
- stop() {
171
- for (const response of this.eventStreams.keys()) {
172
- try {
173
- response.end();
174
- }
175
- catch {
176
- // response already gone
307
+ /**
308
+ * Stops the server: closes all event streams (clearing their ping timers
309
+ * and the backend change-feed subscription), destroys open connections,
310
+ * and closes the node listener when one was started.
311
+ */
312
+ async stop() {
313
+ this.stopping = true;
314
+ const server = this.httpServer;
315
+ this.httpServer = null;
316
+ const listenerClosed = server
317
+ ? new Promise((resolve) => {
318
+ try {
319
+ server.close(() => resolve());
320
+ }
321
+ catch {
322
+ resolve();
323
+ }
324
+ })
325
+ : Promise.resolve();
326
+ for (const stream of Array.from(this.eventStreams)) {
327
+ this.closeStream(stream);
328
+ }
329
+ for (const controller of this.nodeRequestControllers) {
330
+ if (!controller.signal.aborted) {
331
+ controller.abort(new Error("JMAP server is shutting down."));
177
332
  }
178
333
  }
179
- this.eventStreams.clear();
180
334
  for (const socket of this.sockets) {
181
335
  socket.destroy();
182
336
  }
183
337
  this.sockets.clear();
184
- return new Promise((resolve) => {
185
- this.server.close(() => {
186
- resolve();
187
- });
188
- });
338
+ await listenerClosed;
339
+ while (this.activeNodeRequests.size) {
340
+ await Promise.allSettled([...this.activeNodeRequests]);
341
+ }
342
+ if (this.cleanupErrors.length) {
343
+ const errors = this.cleanupErrors.splice(0);
344
+ throw new AggregateError(errors, "JmapServer cleanup failed");
345
+ }
189
346
  }
190
347
  // ======================
191
- // http handling
348
+ // web-standard core
192
349
  // ======================
193
- handleRequest(req, res) {
350
+ /**
351
+ * Handles a JMAP request end to end and returns the Response. This is the
352
+ * runtime-agnostic core — mount it directly as a Deno/Bun fetch handler.
353
+ */
354
+ async fetchHandler(request) {
194
355
  try {
195
- const user = this.authenticate(req);
196
- if (!user) {
197
- res.writeHead(401, {
198
- 'www-authenticate': 'Bearer realm="jmap", Basic realm="jmap"',
199
- 'content-type': 'application/problem+json',
356
+ const principal = await this.authenticatePrincipal(request);
357
+ if (!principal) {
358
+ await this.cancelRequestBody(request, "authentication rejected");
359
+ return this.problemResponse(401, "about:blank", "Authentication required", {
360
+ "www-authenticate": this.authenticationChallenges,
200
361
  });
201
- res.end(JSON.stringify({ type: 'about:blank', status: 401, detail: 'Authentication required' }));
202
- return;
203
362
  }
204
- const url = new URL(req.url ?? '/', 'http://localhost');
363
+ const account = await this.backend.resolveAccount(principal);
364
+ if (!account) {
365
+ await this.cancelRequestBody(request, "account rejected");
366
+ return this.problemResponse(403, "about:blank", "No account for this principal");
367
+ }
368
+ const url = new URL(request.url);
205
369
  const pathname = url.pathname;
206
- if (req.method === 'GET' && (pathname === '/.well-known/jmap' || pathname === '/jmap/session')) {
207
- this.handleSession(user, res);
208
- return;
370
+ const method = request.method.toUpperCase();
371
+ if (method === "GET" &&
372
+ (pathname === "/.well-known/jmap" || pathname === "/jmap/session")) {
373
+ return this.handleSession(account, principal);
209
374
  }
210
- if (req.method === 'POST' && pathname === '/jmap/api') {
211
- let body = '';
212
- req.on('data', (chunk) => {
213
- body += chunk;
214
- });
215
- req.on('end', () => {
216
- this.handleApi(user, body, res);
217
- });
218
- return;
375
+ if (method === "POST" && pathname === "/jmap/api") {
376
+ return this.handleApi(account, request);
219
377
  }
220
- if (req.method === 'GET' && pathname === '/jmap/eventsource') {
221
- this.handleEventSource(user, req, res);
222
- return;
378
+ if (method === "POST" && pathname.startsWith("/jmap/upload/")) {
379
+ return this.handleUpload(account, principal, pathname, request);
223
380
  }
224
- if (req.method === 'GET' && pathname.startsWith('/jmap/download/')) {
225
- this.handleDownload(user, pathname, url, res);
226
- return;
381
+ if (method === "GET" && pathname.startsWith("/jmap/download/")) {
382
+ return this.handleDownload(account, pathname, url);
227
383
  }
228
- res.writeHead(404, { 'content-type': 'application/problem+json' });
229
- res.end(JSON.stringify({ type: 'about:blank', status: 404, detail: 'Not found' }));
384
+ if (method === "GET" && pathname === "/jmap/eventsource") {
385
+ return this.handleEventSource(account, url);
386
+ }
387
+ await this.cancelRequestBody(request, "route rejected");
388
+ return this.problemResponse(404, "about:blank", "Not found");
230
389
  }
231
390
  catch (error) {
232
391
  const message = error instanceof Error ? error.message : String(error);
233
- if (!res.headersSent) {
234
- res.writeHead(500, { 'content-type': 'application/problem+json' });
235
- }
236
- res.end(JSON.stringify({ type: 'about:blank', status: 500, detail: message }));
392
+ return this.problemResponse(500, "about:blank", message);
237
393
  }
238
394
  }
239
- authenticate(req) {
240
- const header = req.headers.authorization;
395
+ // ======================
396
+ // authentication
397
+ // ======================
398
+ async authenticatePrincipal(request) {
399
+ if (this.options.authenticate) {
400
+ return this.options.authenticate(request);
401
+ }
402
+ const header = request.headers.get("authorization");
241
403
  if (!header) {
242
404
  return null;
243
405
  }
244
- const spaceIndex = header.indexOf(' ');
406
+ const spaceIndex = header.indexOf(" ");
245
407
  if (spaceIndex === -1) {
246
408
  return null;
247
409
  }
248
410
  const scheme = header.slice(0, spaceIndex).toLowerCase();
249
411
  const value = header.slice(spaceIndex + 1).trim();
250
- if (scheme === 'bearer') {
251
- for (const user of this.users.values()) {
252
- if (user.bearerTokens.has(value)) {
253
- return user;
412
+ if (scheme === "bearer") {
413
+ for (const [username, entry] of this.registry) {
414
+ if (entry.bearerTokens.has(value)) {
415
+ return { username };
254
416
  }
255
417
  }
256
418
  return null;
257
419
  }
258
- if (scheme === 'basic') {
259
- const decoded = Buffer.from(value, 'base64').toString('utf8');
260
- const colonIndex = decoded.indexOf(':');
420
+ if (scheme === "basic") {
421
+ let decoded;
422
+ try {
423
+ const binary = atob(value);
424
+ decoded = new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
425
+ }
426
+ catch {
427
+ return null;
428
+ }
429
+ const colonIndex = decoded.indexOf(":");
261
430
  if (colonIndex === -1) {
262
431
  return null;
263
432
  }
264
433
  const username = decoded.slice(0, colonIndex);
265
434
  const password = decoded.slice(colonIndex + 1);
266
- const user = this.users.get(username);
267
- if (user && user.password === password) {
268
- return user;
435
+ const entry = this.registry.get(username);
436
+ if (entry && entry.password === password) {
437
+ return { username };
269
438
  }
270
439
  return null;
271
440
  }
272
441
  return null;
273
442
  }
274
- handleSession(user, res) {
443
+ // ======================
444
+ // session
445
+ // ======================
446
+ handleSession(account, principal) {
275
447
  const session = {
276
448
  capabilities: {
277
- 'urn:ietf:params:jmap:core': {
278
- maxSizeUpload: 50_000_000,
279
- maxConcurrentUpload: 4,
280
- maxSizeRequest: 10_000_000,
281
- maxConcurrentRequests: 4,
282
- maxCallsInRequest: 16,
283
- maxObjectsInGet: 500,
284
- maxObjectsInSet: 500,
285
- collationAlgorithms: ['i;ascii-numeric', 'i;ascii-casemap'],
449
+ [JMAP_CORE_CAPABILITY]: {
450
+ ...this.limits,
451
+ collationAlgorithms: ["i;ascii-casemap"],
286
452
  },
287
- 'urn:ietf:params:jmap:mail': {},
288
- 'urn:ietf:params:jmap:submission': {},
453
+ [JMAP_MAIL_CAPABILITY]: {},
454
+ [JMAP_SUBMISSION_CAPABILITY]: {},
289
455
  },
290
456
  accounts: {
291
- [user.accountId]: {
292
- name: user.username,
293
- isPersonal: true,
294
- isReadOnly: false,
457
+ [account.accountId]: {
458
+ name: account.name,
459
+ isPersonal: account.isPersonal ?? true,
460
+ isReadOnly: account.isReadOnly ?? false,
295
461
  accountCapabilities: {
296
- 'urn:ietf:params:jmap:mail': {},
297
- 'urn:ietf:params:jmap:submission': {},
462
+ [JMAP_MAIL_CAPABILITY]: {
463
+ maxMailboxesPerEmail: null,
464
+ maxMailboxDepth: null,
465
+ maxSizeMailboxName: 490,
466
+ maxSizeAttachmentsPerEmail: this.limits.maxSizeUpload,
467
+ emailQuerySortOptions: ["receivedAt"],
468
+ mayCreateTopLevelMailbox: false,
469
+ },
470
+ [JMAP_SUBMISSION_CAPABILITY]: {
471
+ maxDelayedSend: 0,
472
+ submissionExtensions: {},
473
+ },
298
474
  },
299
475
  },
300
476
  },
301
477
  primaryAccounts: {
302
- 'urn:ietf:params:jmap:core': user.accountId,
303
- 'urn:ietf:params:jmap:mail': user.accountId,
304
- 'urn:ietf:params:jmap:submission': user.accountId,
478
+ [JMAP_CORE_CAPABILITY]: account.accountId,
479
+ [JMAP_MAIL_CAPABILITY]: account.accountId,
480
+ [JMAP_SUBMISSION_CAPABILITY]: account.accountId,
305
481
  },
306
- username: user.username,
307
- apiUrl: '/jmap/api',
308
- downloadUrl: '/jmap/download/{accountId}/{blobId}/{name}?type={type}',
309
- uploadUrl: '/jmap/upload/{accountId}',
310
- eventSourceUrl: '/jmap/eventsource?types={types}&closeafter={closeafter}&ping={ping}',
311
- state: String(user.state),
482
+ username: principal.username,
483
+ apiUrl: this.buildUrl("/jmap/api"),
484
+ downloadUrl: this.buildUrl("/jmap/download/{accountId}/{blobId}/{name}?type={type}"),
485
+ uploadUrl: this.buildUrl("/jmap/upload/{accountId}"),
486
+ eventSourceUrl: this.buildUrl("/jmap/eventsource?types={types}&closeafter={closeafter}&ping={ping}"),
487
+ state: SESSION_STATE,
312
488
  };
313
- res.writeHead(200, { 'content-type': 'application/json' });
314
- res.end(JSON.stringify(session));
489
+ return this.jsonResponse(200, session);
315
490
  }
316
- handleApi(user, body, res) {
317
- let parsed;
318
- try {
319
- parsed = JSON.parse(body);
320
- }
321
- catch {
322
- res.writeHead(400, { 'content-type': 'application/problem+json' });
323
- res.end(JSON.stringify({
324
- type: 'urn:ietf:params:jmap:error:notJSON',
325
- status: 400,
326
- detail: 'The request body is not valid JSON.',
327
- }));
328
- return;
329
- }
330
- if (!Array.isArray(parsed?.methodCalls)) {
331
- res.writeHead(400, { 'content-type': 'application/problem+json' });
332
- res.end(JSON.stringify({
333
- type: 'urn:ietf:params:jmap:error:notRequest',
334
- status: 400,
335
- detail: 'The request body is not a valid JMAP request object.',
336
- }));
337
- return;
491
+ buildUrl(path) {
492
+ const base = this.options.baseUrl;
493
+ return base ? `${base.replace(/\/+$/, "")}${path}` : path;
494
+ }
495
+ // ======================
496
+ // api endpoint
497
+ // ======================
498
+ async handleApi(account, request) {
499
+ if (this.activeApiRequests >= this.limits.maxConcurrentRequests) {
500
+ await this.cancelRequestBody(request, "request concurrency limit reached");
501
+ return this.limitResponse(429, "maxConcurrentRequests", "Too many concurrent requests.");
338
502
  }
339
- const createdIds = new Map();
340
- const methodResponses = [];
341
- for (const call of parsed.methodCalls) {
342
- const [methodName, args, callId] = call;
503
+ this.activeApiRequests++;
504
+ try {
505
+ let bytes;
343
506
  try {
344
- const result = this.dispatchMethod(user, methodName, args ?? {}, createdIds);
345
- methodResponses.push([methodName, result, callId]);
507
+ bytes = await this.readRequestBodyBounded(request, this.limits.maxSizeRequest);
346
508
  }
347
509
  catch (error) {
348
- if (error instanceof JmapServerMethodError) {
349
- methodResponses.push([
350
- 'error',
351
- { type: error.type, description: error.message },
352
- callId,
353
- ]);
510
+ if (error instanceof JmapRequestBodyError) {
511
+ if (error.reason === "invalidLength") {
512
+ return this.problemResponse(400, "about:blank", "Invalid Content-Length header.");
513
+ }
514
+ return this.limitResponse(400, "maxSizeRequest", `The request is larger than ${this.limits.maxSizeRequest} bytes.`);
515
+ }
516
+ throw error;
517
+ }
518
+ let parsed;
519
+ try {
520
+ parsed = JSON.parse(new TextDecoder().decode(bytes));
521
+ }
522
+ catch {
523
+ return this.problemResponse(400, "urn:ietf:params:jmap:error:notJSON", "The request body is not valid JSON.");
524
+ }
525
+ if (!parsed ||
526
+ typeof parsed !== "object" ||
527
+ !Array.isArray(parsed.using) ||
528
+ !Array.isArray(parsed.methodCalls)) {
529
+ return this.problemResponse(400, "urn:ietf:params:jmap:error:notRequest", "The request body is not a valid JMAP request object.");
530
+ }
531
+ const knownCapabilities = new Set([
532
+ JMAP_CORE_CAPABILITY,
533
+ JMAP_MAIL_CAPABILITY,
534
+ JMAP_SUBMISSION_CAPABILITY,
535
+ ]);
536
+ const using = new Set(parsed.using);
537
+ for (const capability of using) {
538
+ if (!knownCapabilities.has(capability)) {
539
+ return this.problemResponse(400, "urn:ietf:params:jmap:error:unknownCapability", `The capability "${capability}" is not supported by this server.`);
540
+ }
541
+ }
542
+ if (parsed.methodCalls.length > this.limits.maxCallsInRequest) {
543
+ return this.limitResponse(400, "maxCallsInRequest", `The request has more than ${this.limits.maxCallsInRequest} method calls.`);
544
+ }
545
+ const createdIds = new Map(Object.entries((parsed.createdIds ?? {})));
546
+ const methodResponses = [];
547
+ let mutated = false;
548
+ for (const call of parsed.methodCalls) {
549
+ if (!Array.isArray(call) || typeof call[0] !== "string" ||
550
+ typeof call[2] !== "string") {
551
+ return this.problemResponse(400, "urn:ietf:params:jmap:error:notRequest", "Each method call must be a [name, arguments, callId] tuple.");
552
+ }
553
+ const [methodName, rawArgs, callId] = call;
554
+ try {
555
+ const args = this.resolveBackReferences(rawArgs ?? {}, methodResponses);
556
+ const results = await this.dispatchMethod(account, methodName, args, using, createdIds);
557
+ for (const entry of results) {
558
+ methodResponses.push([entry.name, entry.result, callId]);
559
+ if (entry.mutated) {
560
+ mutated = true;
561
+ }
562
+ }
354
563
  }
355
- else {
356
- const message = error instanceof Error ? error.message : String(error);
357
- methodResponses.push(['error', { type: 'serverFail', description: message }, callId]);
564
+ catch (error) {
565
+ if (error instanceof JmapServerMethodError) {
566
+ methodResponses.push([
567
+ "error",
568
+ { type: error.type, description: error.message },
569
+ callId,
570
+ ]);
571
+ }
572
+ else {
573
+ const message = error instanceof Error
574
+ ? error.message
575
+ : String(error);
576
+ methodResponses.push(["error", {
577
+ type: "serverFail",
578
+ description: message,
579
+ }, callId]);
580
+ }
358
581
  }
359
582
  }
583
+ if (mutated) {
584
+ await this.pushAfterMutation(account);
585
+ }
586
+ const responseBody = {
587
+ methodResponses,
588
+ sessionState: SESSION_STATE,
589
+ };
590
+ if (parsed.createdIds !== undefined) {
591
+ responseBody.createdIds = Object.fromEntries(createdIds);
592
+ }
593
+ return this.jsonResponse(200, responseBody);
360
594
  }
361
- res.writeHead(200, { 'content-type': 'application/json' });
362
- res.end(JSON.stringify({ methodResponses, sessionState: String(user.state) }));
363
- }
364
- handleEventSource(user, req, res) {
365
- res.writeHead(200, {
366
- 'content-type': 'text/event-stream',
367
- 'cache-control': 'no-cache',
368
- connection: 'keep-alive',
369
- });
370
- res.write(': jmap event stream\n\n');
371
- this.eventStreams.set(res, user);
372
- req.on('close', () => {
373
- this.eventStreams.delete(res);
374
- });
375
- }
376
- handleDownload(user, pathname, url, res) {
377
- // /jmap/download/{accountId}/{blobId}/{name}
378
- const segments = pathname.split('/').filter((segment) => segment.length > 0);
379
- const accountId = decodeURIComponent(segments[2] ?? '');
380
- const blobId = decodeURIComponent(segments[3] ?? '');
381
- if (accountId !== user.accountId) {
382
- res.writeHead(404, { 'content-type': 'application/problem+json' });
383
- res.end(JSON.stringify({ type: 'about:blank', status: 404, detail: 'Unknown account' }));
384
- return;
595
+ finally {
596
+ this.activeApiRequests--;
385
597
  }
386
- const blob = user.blobs.get(blobId);
387
- if (!blob) {
388
- res.writeHead(404, { 'content-type': 'application/problem+json' });
389
- res.end(JSON.stringify({ type: 'about:blank', status: 404, detail: 'Unknown blob' }));
390
- return;
598
+ }
599
+ /**
600
+ * Resolves `#argument` ResultReference objects (RFC 8620 §3.7) against the
601
+ * responses of earlier method calls in the same request.
602
+ */
603
+ resolveBackReferences(args, priorResponses) {
604
+ const resolved = {};
605
+ for (const [key, value] of Object.entries(args)) {
606
+ if (!key.startsWith("#")) {
607
+ resolved[key] = value;
608
+ continue;
609
+ }
610
+ const name = key.slice(1);
611
+ if (name in args) {
612
+ throw new JmapServerMethodError("invalidArguments", `The arguments contain both "${name}" and "#${name}".`);
613
+ }
614
+ if (!value ||
615
+ typeof value !== "object" ||
616
+ typeof value.resultOf !== "string" ||
617
+ typeof value.name !== "string" ||
618
+ typeof value.path !== "string") {
619
+ throw new JmapServerMethodError("invalidResultReference", `"#${name}" is not a valid ResultReference object.`);
620
+ }
621
+ const source = priorResponses.find((entry) => entry[2] === value.resultOf && entry[0] === value.name);
622
+ if (!source) {
623
+ throw new JmapServerMethodError("invalidResultReference", `No response found for resultOf "${value.resultOf}" and name "${value.name}".`);
624
+ }
625
+ try {
626
+ resolved[name] = evalJsonPointer(source[1], value.path);
627
+ }
628
+ catch (error) {
629
+ throw new JmapServerMethodError("invalidResultReference", error instanceof Error ? error.message : String(error));
630
+ }
391
631
  }
392
- const type = url.searchParams.get('type') ?? blob.type;
393
- res.writeHead(200, { 'content-type': type, 'content-length': blob.data.length });
394
- res.end(blob.data);
632
+ return resolved;
395
633
  }
396
634
  // ======================
397
- // jmap method dispatch
635
+ // method dispatch
398
636
  // ======================
399
- dispatchMethod(user, methodName, args, createdIds) {
637
+ async dispatchMethod(account, methodName, args, using, createdIds) {
638
+ const requiredCapability = {
639
+ "Core/echo": JMAP_CORE_CAPABILITY,
640
+ "Mailbox/get": JMAP_MAIL_CAPABILITY,
641
+ "Mailbox/query": JMAP_MAIL_CAPABILITY,
642
+ "Mailbox/changes": JMAP_MAIL_CAPABILITY,
643
+ "Thread/get": JMAP_MAIL_CAPABILITY,
644
+ "Email/get": JMAP_MAIL_CAPABILITY,
645
+ "Email/query": JMAP_MAIL_CAPABILITY,
646
+ "Email/changes": JMAP_MAIL_CAPABILITY,
647
+ "Email/queryChanges": JMAP_MAIL_CAPABILITY,
648
+ "Email/set": JMAP_MAIL_CAPABILITY,
649
+ "Identity/get": JMAP_SUBMISSION_CAPABILITY,
650
+ "EmailSubmission/set": JMAP_SUBMISSION_CAPABILITY,
651
+ };
652
+ const capability = requiredCapability[methodName];
653
+ if (!capability) {
654
+ throw new JmapServerMethodError("unknownMethod", `Unknown method "${methodName}".`);
655
+ }
656
+ if (!using.has(capability)) {
657
+ throw new JmapServerMethodError("unknownMethod", `Method "${methodName}" requires the capability "${capability}" in "using".`);
658
+ }
659
+ if (methodName !== "Core/echo") {
660
+ this.requireAccountId(account, args);
661
+ }
400
662
  switch (methodName) {
401
- case 'Core/echo':
402
- return args;
403
- case 'Mailbox/get':
404
- return this.methodMailboxGet(user, args);
405
- case 'Mailbox/query':
406
- return this.methodMailboxQuery(user, args);
407
- case 'Email/get':
408
- return this.methodEmailGet(user, args);
409
- case 'Email/query':
410
- return this.methodEmailQuery(user, args);
411
- case 'Email/changes':
412
- return this.methodEmailChanges(user, args);
413
- case 'Email/set':
414
- return this.methodEmailSet(user, args, createdIds);
415
- case 'Identity/get':
416
- return this.methodIdentityGet(user);
417
- case 'EmailSubmission/set':
418
- return this.methodEmailSubmissionSet(user, args, createdIds);
663
+ case "Core/echo":
664
+ return [{ name: methodName, result: args }];
665
+ case "Mailbox/get":
666
+ return [{
667
+ name: methodName,
668
+ result: await this.methodMailboxGet(account, args),
669
+ }];
670
+ case "Mailbox/query":
671
+ return [{
672
+ name: methodName,
673
+ result: await this.methodMailboxQuery(account, args),
674
+ }];
675
+ case "Mailbox/changes":
676
+ return [{
677
+ name: methodName,
678
+ result: await this.methodMailboxChanges(account, args),
679
+ }];
680
+ case "Thread/get":
681
+ return [{
682
+ name: methodName,
683
+ result: await this.methodThreadGet(account, args),
684
+ }];
685
+ case "Email/get":
686
+ return [{
687
+ name: methodName,
688
+ result: await this.methodEmailGet(account, args),
689
+ }];
690
+ case "Email/query":
691
+ return [{
692
+ name: methodName,
693
+ result: await this.methodEmailQuery(account, args),
694
+ }];
695
+ case "Email/changes":
696
+ return [{
697
+ name: methodName,
698
+ result: await this.methodEmailChanges(account, args),
699
+ }];
700
+ case "Email/queryChanges":
701
+ // Explicitly unsupported in phase 1: clients fall back to Email/query.
702
+ throw new JmapServerMethodError("cannotCalculateChanges", "Email/queryChanges is not supported; re-run the query instead.");
703
+ case "Email/set": {
704
+ const result = await this.methodEmailSet(account, args, createdIds);
705
+ return [{
706
+ name: methodName,
707
+ result,
708
+ mutated: result.newState !== result.oldState,
709
+ }];
710
+ }
711
+ case "Identity/get":
712
+ return [{
713
+ name: methodName,
714
+ result: await this.methodIdentityGet(account, args),
715
+ }];
716
+ case "EmailSubmission/set":
717
+ return this.methodEmailSubmissionSet(account, args, createdIds);
419
718
  default:
420
- throw new JmapServerMethodError('unknownMethod', `Unknown method "${methodName}".`);
719
+ throw new JmapServerMethodError("unknownMethod", `Unknown method "${methodName}".`);
421
720
  }
422
721
  }
423
- methodMailboxGet(user, args) {
424
- const all = Array.from(user.mailboxes.values());
425
- let list;
426
- const notFound = [];
427
- if (args.ids == null) {
428
- list = all;
722
+ requireAccountId(account, args) {
723
+ if (typeof args.accountId !== "string") {
724
+ throw new JmapServerMethodError("invalidArguments", "accountId is required.");
429
725
  }
430
- else {
431
- list = [];
432
- for (const id of args.ids) {
433
- const mailbox = user.mailboxes.get(id);
434
- if (mailbox) {
435
- list.push(mailbox);
436
- }
437
- else {
438
- notFound.push(id);
439
- }
726
+ if (args.accountId !== account.accountId) {
727
+ throw new JmapServerMethodError("accountNotFound", `Account "${args.accountId}" is not accessible with these credentials.`);
728
+ }
729
+ }
730
+ // ======================
731
+ // mailbox methods
732
+ // ======================
733
+ async methodMailboxGet(account, args) {
734
+ let ids = null;
735
+ if (args.ids !== null && args.ids !== undefined) {
736
+ if (!Array.isArray(args.ids)) {
737
+ throw new JmapServerMethodError("invalidArguments", "ids must be an array of ids or null.");
738
+ }
739
+ if (args.ids.length > this.limits.maxObjectsInGet) {
740
+ throw new JmapServerMethodError("requestTooLarge", `ids exceeds maxObjectsInGet (${this.limits.maxObjectsInGet}).`);
440
741
  }
742
+ ids = args.ids;
441
743
  }
442
- const augmented = list.map((mailbox) => {
443
- const emails = Array.from(user.emails.values()).filter((email) => email.mailboxIds?.[mailbox.id]);
444
- return {
744
+ const properties = this.validateProperties(args.properties, KNOWN_MAILBOX_PROPERTIES);
745
+ const result = await this.backend.getMailboxes(account.accountId, ids);
746
+ const list = result.list.map((mailbox) => {
747
+ const full = {
445
748
  ...mailbox,
446
- totalEmails: emails.length,
447
- unreadEmails: emails.filter((email) => !email.keywords?.$seen).length,
448
- totalThreads: emails.length,
449
- unreadThreads: emails.filter((email) => !email.keywords?.$seen).length,
450
- myRights: {
451
- mayReadItems: true,
452
- mayAddItems: true,
453
- mayRemoveItems: true,
454
- maySetSeen: true,
455
- maySetKeywords: true,
456
- mayCreateChild: true,
457
- mayRename: true,
458
- mayDelete: true,
459
- maySubmit: true,
460
- },
461
- isSubscribed: true,
749
+ isSubscribed: mailbox.isSubscribed ?? true,
750
+ myRights: mailbox.myRights ?? { ...DEFAULT_MAILBOX_RIGHTS },
462
751
  };
752
+ return this.projectObject(full, properties ?? MAILBOX_PROPERTIES);
463
753
  });
464
754
  return {
465
- accountId: user.accountId,
466
- state: String(user.state),
467
- list: augmented,
468
- notFound,
755
+ accountId: account.accountId,
756
+ state: result.state,
757
+ list,
758
+ notFound: result.notFound,
469
759
  };
470
760
  }
471
- methodMailboxQuery(user, args) {
472
- const filter = args.filter ?? {};
473
- let mailboxes = Array.from(user.mailboxes.values());
474
- if (typeof filter.role === 'string') {
761
+ async methodMailboxQuery(account, args) {
762
+ const filter = (args.filter ?? {});
763
+ if ("operator" in filter) {
764
+ throw new JmapServerMethodError("unsupportedFilter", "FilterOperator is not supported for Mailbox/query.");
765
+ }
766
+ for (const key of Object.keys(filter)) {
767
+ if (!["role", "name", "parentId"].includes(key)) {
768
+ throw new JmapServerMethodError("unsupportedFilter", `Mailbox filter condition "${key}" is not supported.`);
769
+ }
770
+ }
771
+ for (const comparator of (args.sort ?? [])) {
772
+ if (!["name", "sortOrder"].includes(comparator.property)) {
773
+ throw new JmapServerMethodError("unsupportedSort", `Mailbox sort property "${comparator.property}" is not supported.`);
774
+ }
775
+ }
776
+ const result = await this.backend.getMailboxes(account.accountId, null);
777
+ let mailboxes = result.list;
778
+ if (typeof filter.role === "string") {
475
779
  mailboxes = mailboxes.filter((mailbox) => mailbox.role === filter.role);
476
780
  }
477
- if (typeof filter.name === 'string') {
781
+ if (typeof filter.name === "string") {
478
782
  mailboxes = mailboxes.filter((mailbox) => mailbox.name === filter.name);
479
783
  }
480
- const ids = mailboxes.map((mailbox) => mailbox.id);
481
- return {
482
- accountId: user.accountId,
483
- queryState: String(user.state),
784
+ if ("parentId" in filter) {
785
+ mailboxes = mailboxes.filter((mailbox) => mailbox.parentId === filter.parentId);
786
+ }
787
+ const comparators = (args.sort ?? []);
788
+ if (comparators.length) {
789
+ mailboxes = [...mailboxes].sort((a, b) => {
790
+ for (const comparator of comparators) {
791
+ const direction = comparator.isAscending === false ? -1 : 1;
792
+ const property = comparator.property;
793
+ const left = a[property] ?? 0;
794
+ const right = b[property] ?? 0;
795
+ if (left < right) {
796
+ return -direction;
797
+ }
798
+ if (left > right) {
799
+ return direction;
800
+ }
801
+ }
802
+ return 0;
803
+ });
804
+ }
805
+ const position = this.validatePosition(args);
806
+ let ids = mailboxes.map((mailbox) => mailbox.id).slice(position);
807
+ if (typeof args.limit === "number") {
808
+ ids = ids.slice(0, args.limit);
809
+ }
810
+ const response = {
811
+ accountId: account.accountId,
812
+ queryState: result.state,
484
813
  canCalculateChanges: false,
485
- position: 0,
814
+ position,
486
815
  ids,
487
- total: ids.length,
488
816
  };
817
+ if (args.calculateTotal === true) {
818
+ response.total = mailboxes.length;
819
+ }
820
+ return response;
821
+ }
822
+ async methodMailboxChanges(account, args) {
823
+ const { sinceState, maxChanges } = this.validateChangesArgs(args);
824
+ const changes = await this.backend.getMailboxChanges(account.accountId, sinceState, maxChanges);
825
+ if (!changes) {
826
+ throw new JmapServerMethodError("cannotCalculateChanges", `Cannot calculate mailbox changes since state "${sinceState}".`);
827
+ }
828
+ return { accountId: account.accountId, ...changes };
489
829
  }
490
- methodEmailGet(user, args) {
830
+ // ======================
831
+ // thread methods
832
+ // ======================
833
+ async methodThreadGet(account, args) {
491
834
  if (!Array.isArray(args.ids)) {
492
- throw new JmapServerMethodError('invalidArguments', 'Email/get requires an ids array.');
835
+ throw new JmapServerMethodError("invalidArguments", "Thread/get requires an ids array.");
493
836
  }
494
- const list = [];
495
- const notFound = [];
496
- for (const id of args.ids) {
497
- const email = user.emails.get(id);
498
- if (email) {
499
- // Returned as a full superset of the requestable properties;
500
- // property projection is intentionally not implemented.
501
- list.push({ ...email });
502
- }
503
- else {
504
- notFound.push(id);
505
- }
837
+ if (args.ids.length > this.limits.maxObjectsInGet) {
838
+ throw new JmapServerMethodError("requestTooLarge", `ids exceeds maxObjectsInGet (${this.limits.maxObjectsInGet}).`);
506
839
  }
840
+ // Result-reference chains like Email/get -> /list/*/threadId commonly
841
+ // contain duplicates; deduplicate so each thread is returned once.
842
+ const ids = Array.from(new Set(args.ids));
843
+ const result = await this.backend.getThreads(account.accountId, ids);
507
844
  return {
508
- accountId: user.accountId,
509
- state: String(user.state),
510
- list,
511
- notFound,
845
+ accountId: account.accountId,
846
+ state: result.state,
847
+ list: result.list,
848
+ notFound: result.notFound,
512
849
  };
513
850
  }
514
- methodEmailQuery(user, args) {
515
- const filter = args.filter ?? {};
516
- let emails = Array.from(user.emails.values());
517
- if (typeof filter.inMailbox === 'string') {
518
- emails = emails.filter((email) => email.mailboxIds?.[filter.inMailbox]);
519
- }
520
- if (typeof filter.subject === 'string') {
521
- emails = emails.filter((email) => String(email.subject ?? '').toLowerCase().includes(filter.subject.toLowerCase()));
522
- }
523
- if (typeof filter.text === 'string') {
524
- const needle = filter.text.toLowerCase();
525
- emails = emails.filter((email) => String(email.subject ?? '').toLowerCase().includes(needle) ||
526
- String(email.bodyValues?.text?.value ?? '').toLowerCase().includes(needle));
527
- }
528
- const sort = Array.isArray(args.sort) && args.sort.length ? args.sort[0] : null;
529
- if (sort?.property === 'receivedAt') {
530
- emails.sort((a, b) => {
531
- const comparison = String(a.receivedAt ?? '').localeCompare(String(b.receivedAt ?? ''));
532
- return sort.isAscending === false ? -comparison : comparison;
533
- });
851
+ // ======================
852
+ // email methods
853
+ // ======================
854
+ async methodEmailGet(account, args) {
855
+ if (args.ids === null || args.ids === undefined) {
856
+ // RFC 8621 allows rejecting "fetch all" for the potentially huge Email type.
857
+ throw new JmapServerMethodError("requestTooLarge", "Email/get requires an explicit ids array on this server.");
534
858
  }
535
- const position = typeof args.position === 'number' ? args.position : 0;
536
- let ids = emails.map((email) => email.id).slice(position);
537
- const total = emails.length;
538
- if (typeof args.limit === 'number') {
539
- ids = ids.slice(0, args.limit);
859
+ if (!Array.isArray(args.ids)) {
860
+ throw new JmapServerMethodError("invalidArguments", "Email/get requires an ids array.");
861
+ }
862
+ if (args.ids.length > this.limits.maxObjectsInGet) {
863
+ throw new JmapServerMethodError("requestTooLarge", `ids exceeds maxObjectsInGet (${this.limits.maxObjectsInGet}).`);
540
864
  }
865
+ const properties = this.validateProperties(args.properties, KNOWN_EMAIL_PROPERTIES);
866
+ const result = await this.backend.getEmails(account.accountId, args.ids, properties);
867
+ const effectiveProperties = properties ?? DEFAULT_EMAIL_PROPERTIES;
868
+ const list = result.list.map((record) => {
869
+ const projected = this.projectObject(record, effectiveProperties);
870
+ if (effectiveProperties.includes("bodyValues")) {
871
+ projected.bodyValues = this.buildBodyValues(record, args);
872
+ }
873
+ return projected;
874
+ });
541
875
  return {
542
- accountId: user.accountId,
543
- queryState: String(user.state),
544
- canCalculateChanges: false,
545
- position,
546
- ids,
547
- total,
876
+ accountId: account.accountId,
877
+ state: result.state,
878
+ list,
879
+ notFound: result.notFound,
548
880
  };
549
881
  }
550
- methodEmailChanges(user, args) {
551
- const since = Number(args.sinceState);
552
- if (!Number.isFinite(since) || since < 0 || since > user.state) {
553
- throw new JmapServerMethodError('cannotCalculateChanges', `Cannot calculate changes since state "${args.sinceState}".`);
882
+ /** Applies the Email/get body-value fetch flags and maxBodyValueBytes truncation. */
883
+ buildBodyValues(record, args) {
884
+ const wanted = new Set();
885
+ if (args.fetchAllBodyValues === true) {
886
+ for (const partId of Object.keys(record.bodyValues)) {
887
+ wanted.add(partId);
888
+ }
554
889
  }
555
- const created = new Set();
556
- const updated = new Set();
557
- const destroyed = new Set();
558
- for (const entry of user.changes) {
559
- if (entry.state <= since) {
560
- continue;
890
+ if (args.fetchTextBodyValues === true) {
891
+ for (const part of record.textBody) {
892
+ if (part.partId != null) {
893
+ wanted.add(part.partId);
894
+ }
561
895
  }
562
- for (const id of entry.created) {
563
- created.add(id);
896
+ }
897
+ if (args.fetchHTMLBodyValues === true) {
898
+ for (const part of record.htmlBody) {
899
+ if (part.partId != null) {
900
+ wanted.add(part.partId);
901
+ }
564
902
  }
565
- for (const id of entry.updated) {
566
- updated.add(id);
903
+ }
904
+ const maxBytes = typeof args.maxBodyValueBytes === "number" && args.maxBodyValueBytes > 0
905
+ ? args.maxBodyValueBytes
906
+ : null;
907
+ const result = {};
908
+ for (const partId of wanted) {
909
+ const bodyValue = record.bodyValues[partId];
910
+ if (!bodyValue) {
911
+ continue;
567
912
  }
568
- for (const id of entry.destroyed) {
569
- if (created.has(id)) {
570
- // created and destroyed within the window: omit entirely
571
- created.delete(id);
913
+ let value = bodyValue.value;
914
+ let isTruncated = bodyValue.isTruncated === true;
915
+ if (maxBytes !== null) {
916
+ const truncated = truncateUtf8(value, maxBytes);
917
+ if (truncated.length < value.length) {
918
+ value = truncated;
919
+ isTruncated = true;
572
920
  }
573
- else {
574
- destroyed.add(id);
575
- }
576
- updated.delete(id);
577
921
  }
922
+ result[partId] = { value, isTruncated };
578
923
  }
579
- for (const id of created) {
580
- updated.delete(id);
924
+ return result;
925
+ }
926
+ async methodEmailQuery(account, args) {
927
+ const filter = (args.filter ?? {});
928
+ if ("operator" in filter) {
929
+ throw new JmapServerMethodError("unsupportedFilter", "FilterOperator is not supported; use a flat FilterCondition.");
581
930
  }
582
- return {
583
- accountId: user.accountId,
584
- oldState: String(since),
585
- newState: String(user.state),
586
- hasMoreChanges: false,
587
- created: Array.from(created),
588
- updated: Array.from(updated),
589
- destroyed: Array.from(destroyed),
931
+ for (const key of Object.keys(filter)) {
932
+ if (!SUPPORTED_EMAIL_FILTER_KEYS.has(key)) {
933
+ throw new JmapServerMethodError("unsupportedFilter", `Email filter condition "${key}" is not supported.`);
934
+ }
935
+ }
936
+ const sort = (args.sort ?? []);
937
+ for (const comparator of sort) {
938
+ if (comparator.property !== "receivedAt") {
939
+ throw new JmapServerMethodError("unsupportedSort", `Email sort property "${comparator.property}" is not supported.`);
940
+ }
941
+ }
942
+ if (args.anchor !== undefined && args.anchor !== null) {
943
+ throw new JmapServerMethodError("invalidArguments", "anchor is not supported.");
944
+ }
945
+ const position = this.validatePosition(args);
946
+ const result = await this.backend.queryEmails(account.accountId, {
947
+ filter: filter,
948
+ sort: sort,
949
+ position,
950
+ limit: typeof args.limit === "number" ? args.limit : null,
951
+ calculateTotal: args.calculateTotal === true,
952
+ });
953
+ const response = {
954
+ accountId: account.accountId,
955
+ queryState: result.queryState,
956
+ canCalculateChanges: false,
957
+ position: result.position,
958
+ ids: result.ids,
590
959
  };
960
+ if (args.calculateTotal === true) {
961
+ response.total = result.total ?? 0;
962
+ }
963
+ return response;
591
964
  }
592
- methodEmailSet(user, args, createdIds) {
593
- const oldState = String(user.state);
594
- const created = {};
595
- const notCreated = {};
596
- const updated = {};
597
- const notUpdated = {};
598
- const destroyed = [];
599
- const notDestroyed = {};
600
- const changedCreated = [];
601
- const changedUpdated = [];
602
- const changedDestroyed = [];
603
- for (const [creationId, spec] of Object.entries((args.create ?? {}))) {
604
- try {
605
- const email = this.createEmailFromSpec(user, spec);
606
- user.emails.set(email.id, email);
607
- createdIds.set(creationId, email.id);
608
- changedCreated.push(email.id);
609
- created[creationId] = {
610
- id: email.id,
611
- blobId: email.blobId,
612
- threadId: email.threadId,
613
- size: email.size,
614
- };
965
+ async methodEmailChanges(account, args) {
966
+ const { sinceState, maxChanges } = this.validateChangesArgs(args);
967
+ const changes = await this.backend.getEmailChanges(account.accountId, sinceState, maxChanges);
968
+ if (!changes) {
969
+ throw new JmapServerMethodError("cannotCalculateChanges", `Cannot calculate changes since state "${sinceState}".`);
970
+ }
971
+ return { accountId: account.accountId, ...changes };
972
+ }
973
+ async methodEmailSet(account, args, createdIds) {
974
+ const createEntries = Object.entries((args.create ?? {}));
975
+ const updateEntries = Object.entries((args.update ?? {}));
976
+ const destroyIds = (args.destroy ?? []);
977
+ if (createEntries.length + updateEntries.length + destroyIds.length >
978
+ this.limits.maxObjectsInSet) {
979
+ throw new JmapServerMethodError("requestTooLarge", `The set request exceeds maxObjectsInSet (${this.limits.maxObjectsInSet}).`);
980
+ }
981
+ if (typeof args.ifInState === "string") {
982
+ const current = await this.backend.getEmails(account.accountId, []);
983
+ if (current.state !== args.ifInState) {
984
+ throw new JmapServerMethodError("stateMismatch", `ifInState "${args.ifInState}" does not match the current state "${current.state}".`);
615
985
  }
616
- catch (error) {
617
- const message = error instanceof Error ? error.message : String(error);
618
- notCreated[creationId] = { type: 'invalidProperties', description: message };
986
+ }
987
+ const backendRequest = {};
988
+ const notUpdatedEarly = {};
989
+ if (createEntries.length) {
990
+ backendRequest.create = {};
991
+ for (const [creationId, spec] of createEntries) {
992
+ backendRequest.create[creationId] = spec;
619
993
  }
620
994
  }
621
- for (const [id, patch] of Object.entries((args.update ?? {}))) {
622
- const email = user.emails.get(id);
623
- if (!email) {
624
- notUpdated[id] = { type: 'notFound', description: `Email "${id}" does not exist.` };
995
+ if (updateEntries.length) {
996
+ backendRequest.update = {};
997
+ for (const [id, patch] of updateEntries) {
998
+ try {
999
+ backendRequest.update[id] = this.parseEmailUpdatePatch(patch);
1000
+ }
1001
+ catch (error) {
1002
+ notUpdatedEarly[id] = error instanceof JmapServerMethodError
1003
+ ? { type: error.type, description: error.message }
1004
+ : { type: "invalidPatch", description: String(error) };
1005
+ }
1006
+ }
1007
+ }
1008
+ if (destroyIds.length) {
1009
+ backendRequest.destroy = destroyIds;
1010
+ }
1011
+ const result = await this.backend.setEmails(account.accountId, backendRequest);
1012
+ const created = {};
1013
+ for (const [creationId, record] of Object.entries(result.created)) {
1014
+ createdIds.set(creationId, record.id);
1015
+ created[creationId] = {
1016
+ id: record.id,
1017
+ blobId: record.blobId,
1018
+ threadId: record.threadId,
1019
+ size: record.size,
1020
+ };
1021
+ }
1022
+ const updated = {};
1023
+ for (const id of result.updated) {
1024
+ updated[id] = null;
1025
+ }
1026
+ return {
1027
+ accountId: account.accountId,
1028
+ oldState: result.oldState,
1029
+ newState: result.newState,
1030
+ created,
1031
+ notCreated: result.notCreated,
1032
+ updated,
1033
+ notUpdated: { ...result.notUpdated, ...notUpdatedEarly },
1034
+ destroyed: result.destroyed,
1035
+ notDestroyed: result.notDestroyed,
1036
+ };
1037
+ }
1038
+ /**
1039
+ * Normalizes an Email/set update patch (RFC 8620 §5.3): full `keywords`/
1040
+ * `mailboxIds` replacements and single-key JSON-pointer patches
1041
+ * (`keywords/$seen`, `mailboxIds/<id>`). Email properties other than these
1042
+ * two are immutable (RFC 8621 §4.6).
1043
+ */
1044
+ parseEmailUpdatePatch(patch) {
1045
+ const update = {};
1046
+ const unescape = (token) => token.replaceAll("~1", "/").replaceAll("~0", "~");
1047
+ for (const [path, value] of Object.entries(patch)) {
1048
+ if (path === "keywords" || path === "mailboxIds") {
1049
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
1050
+ throw new JmapServerMethodError("invalidProperties", `"${path}" must be an object.`);
1051
+ }
1052
+ const normalized = {};
1053
+ for (const [key, entryValue] of Object.entries(value)) {
1054
+ if (entryValue !== true) {
1055
+ throw new JmapServerMethodError("invalidProperties", `Values in "${path}" must be true; remove entries instead of setting them false.`);
1056
+ }
1057
+ normalized[key] = true;
1058
+ }
1059
+ update[path] = normalized;
625
1060
  continue;
626
1061
  }
627
- try {
628
- this.applyPatch(email, patch);
629
- changedUpdated.push(id);
630
- updated[id] = null;
1062
+ const slashIndex = path.indexOf("/");
1063
+ if (slashIndex === -1) {
1064
+ throw new JmapServerMethodError("invalidProperties", `Email property "${path}" is immutable or unknown.`);
631
1065
  }
632
- catch (error) {
633
- const message = error instanceof Error ? error.message : String(error);
634
- notUpdated[id] = { type: 'invalidPatch', description: message };
1066
+ const property = path.slice(0, slashIndex);
1067
+ const rest = path.slice(slashIndex + 1);
1068
+ if ((property !== "keywords" && property !== "mailboxIds") ||
1069
+ rest.includes("/") || !rest) {
1070
+ throw new JmapServerMethodError("invalidPatch", `Unsupported patch path "${path}".`);
635
1071
  }
636
- }
637
- for (const id of (args.destroy ?? [])) {
638
- if (user.emails.delete(id)) {
639
- changedDestroyed.push(id);
640
- destroyed.push(id);
1072
+ const key = unescape(rest);
1073
+ const normalizedValue = value === true
1074
+ ? true
1075
+ : value === null || value === false
1076
+ ? null
1077
+ : undefined;
1078
+ if (normalizedValue === undefined) {
1079
+ throw new JmapServerMethodError("invalidPatch", `Patch value for "${path}" must be true or null.`);
1080
+ }
1081
+ if (property === "keywords") {
1082
+ update.keywordsPatch = update.keywordsPatch ?? {};
1083
+ update.keywordsPatch[key] = normalizedValue;
641
1084
  }
642
1085
  else {
643
- notDestroyed[id] = { type: 'notFound', description: `Email "${id}" does not exist.` };
1086
+ update.mailboxIdsPatch = update.mailboxIdsPatch ?? {};
1087
+ update.mailboxIdsPatch[key] = normalizedValue;
644
1088
  }
645
1089
  }
646
- if (changedCreated.length || changedUpdated.length || changedDestroyed.length) {
647
- this.bumpState(user, {
648
- created: changedCreated,
649
- updated: changedUpdated,
650
- destroyed: changedDestroyed,
651
- });
1090
+ if (update.keywords && update.keywordsPatch) {
1091
+ throw new JmapServerMethodError("invalidPatch", 'A patch must not set "keywords" and patch "keywords/..." at the same time.');
652
1092
  }
653
- return {
654
- accountId: user.accountId,
655
- oldState,
656
- newState: String(user.state),
657
- created,
658
- notCreated,
659
- updated,
660
- notUpdated,
661
- destroyed,
662
- notDestroyed,
663
- };
1093
+ if (update.mailboxIds && update.mailboxIdsPatch) {
1094
+ throw new JmapServerMethodError("invalidPatch", 'A patch must not set "mailboxIds" and patch "mailboxIds/..." at the same time.');
1095
+ }
1096
+ return update;
664
1097
  }
665
- methodIdentityGet(user) {
1098
+ // ======================
1099
+ // identity + submission methods
1100
+ // ======================
1101
+ async methodIdentityGet(account, args) {
1102
+ const result = await this.backend.getIdentities(account.accountId);
1103
+ let list = result.list;
1104
+ const notFound = [];
1105
+ if (Array.isArray(args.ids)) {
1106
+ const wanted = new Set(args.ids);
1107
+ list = list.filter((identity) => wanted.has(identity.id));
1108
+ for (const id of wanted) {
1109
+ if (!list.some((identity) => identity.id === id)) {
1110
+ notFound.push(id);
1111
+ }
1112
+ }
1113
+ }
666
1114
  return {
667
- accountId: user.accountId,
668
- state: '0',
669
- list: user.identities,
670
- notFound: [],
1115
+ accountId: account.accountId,
1116
+ state: result.state,
1117
+ list,
1118
+ notFound,
671
1119
  };
672
1120
  }
673
- methodEmailSubmissionSet(user, args, createdIds) {
1121
+ async methodEmailSubmissionSet(account, args, createdIds) {
674
1122
  const created = {};
675
1123
  const notCreated = {};
1124
+ const notUpdated = {};
1125
+ const notDestroyed = {};
1126
+ /** creationId -> { submissionId, emailId } for onSuccess* resolution. */
1127
+ const createdSubmissions = new Map();
1128
+ const identitiesResult = await this.backend.getIdentities(account.accountId);
676
1129
  for (const [creationId, spec] of Object.entries((args.create ?? {}))) {
677
1130
  let emailId = spec.emailId;
678
- if (typeof emailId === 'string' && emailId.startsWith('#')) {
1131
+ if (typeof emailId === "string" && emailId.startsWith("#")) {
679
1132
  const resolved = createdIds.get(emailId.slice(1));
680
1133
  if (!resolved) {
681
1134
  notCreated[creationId] = {
682
- type: 'invalidProperties',
1135
+ type: "invalidProperties",
683
1136
  description: `Unknown creation id reference "${emailId}".`,
684
1137
  };
685
1138
  continue;
686
1139
  }
687
1140
  emailId = resolved;
688
1141
  }
689
- if (!user.emails.has(emailId)) {
1142
+ const emailResult = await this.backend.getEmails(account.accountId, [
1143
+ emailId,
1144
+ ]);
1145
+ const email = emailResult.list[0];
1146
+ if (!email) {
690
1147
  notCreated[creationId] = {
691
- type: 'invalidProperties',
1148
+ type: "invalidProperties",
692
1149
  description: `Email "${emailId}" does not exist.`,
693
1150
  };
694
1151
  continue;
695
1152
  }
696
- const identity = user.identities.find((candidate) => candidate.id === spec.identityId);
1153
+ const identity = identitiesResult.list.find((candidate) => candidate.id === spec.identityId);
697
1154
  if (!identity) {
698
1155
  notCreated[creationId] = {
699
- type: 'invalidProperties',
1156
+ type: "invalidProperties",
700
1157
  description: `Identity "${spec.identityId}" does not exist.`,
701
1158
  };
702
1159
  continue;
703
1160
  }
704
- const id = `submission_${++user.idCounter}`;
705
- const submission = {
706
- id,
707
- emailId,
708
- identityId: identity.id,
709
- undoStatus: 'final',
710
- sendAt: new Date().toISOString(),
1161
+ const envelope = this.resolveEnvelope(spec.envelope, identity.email, email);
1162
+ if (!envelope.rcptTo.length) {
1163
+ notCreated[creationId] = {
1164
+ type: "noRecipients",
1165
+ description: "The email has no to/cc/bcc recipients and no envelope was given.",
1166
+ };
1167
+ continue;
1168
+ }
1169
+ const blob = await this.backend.getBlob(account.accountId, email.blobId);
1170
+ if (!blob) {
1171
+ notCreated[creationId] = {
1172
+ type: "invalidProperties",
1173
+ description: `Raw message blob "${email.blobId}" does not exist.`,
1174
+ };
1175
+ continue;
1176
+ }
1177
+ try {
1178
+ const submission = await this.backend.submitEmail(account.accountId, {
1179
+ emailId,
1180
+ identityId: identity.id,
1181
+ envelope,
1182
+ message: blob.data,
1183
+ });
1184
+ createdSubmissions.set(creationId, {
1185
+ submissionId: submission.id,
1186
+ emailId,
1187
+ });
1188
+ created[creationId] = {
1189
+ id: submission.id,
1190
+ undoStatus: submission.undoStatus,
1191
+ sendAt: submission.sendAt,
1192
+ };
1193
+ }
1194
+ catch (error) {
1195
+ notCreated[creationId] = {
1196
+ type: "forbiddenToSend",
1197
+ description: error instanceof Error ? error.message : String(error),
1198
+ };
1199
+ }
1200
+ }
1201
+ for (const id of Object.keys((args.update ?? {}))) {
1202
+ notUpdated[id] = {
1203
+ type: "forbidden",
1204
+ description: "EmailSubmission updates are not supported.",
1205
+ };
1206
+ }
1207
+ for (const id of (args.destroy ?? [])) {
1208
+ notDestroyed[id] = {
1209
+ type: "forbidden",
1210
+ description: "EmailSubmission destroys are not supported.",
711
1211
  };
712
- user.submissions.set(id, submission);
713
- created[creationId] = { id, undoStatus: submission.undoStatus, sendAt: submission.sendAt };
1212
+ }
1213
+ const responses = [
1214
+ {
1215
+ name: "EmailSubmission/set",
1216
+ result: {
1217
+ accountId: account.accountId,
1218
+ oldState: null,
1219
+ newState: "0",
1220
+ created,
1221
+ notCreated,
1222
+ updated: {},
1223
+ notUpdated,
1224
+ destroyed: [],
1225
+ notDestroyed,
1226
+ },
1227
+ mutated: createdSubmissions.size > 0,
1228
+ },
1229
+ ];
1230
+ // onSuccessUpdateEmail / onSuccessDestroyEmail (RFC 8621 §7.5): apply an
1231
+ // implicit Email/set for successfully created submissions and append its
1232
+ // response after the EmailSubmission/set response.
1233
+ const resolveSubmissionRef = (reference) => {
1234
+ if (reference.startsWith("#")) {
1235
+ return createdSubmissions.get(reference.slice(1)) ?? null;
1236
+ }
1237
+ for (const entry of createdSubmissions.values()) {
1238
+ if (entry.submissionId === reference) {
1239
+ return entry;
1240
+ }
1241
+ }
1242
+ return null;
1243
+ };
1244
+ const implicitSet = { accountId: account.accountId };
1245
+ let hasImplicitSet = false;
1246
+ if (args.onSuccessUpdateEmail && typeof args.onSuccessUpdateEmail === "object") {
1247
+ const update = {};
1248
+ for (const [reference, patch] of Object.entries(args.onSuccessUpdateEmail)) {
1249
+ const entry = resolveSubmissionRef(reference);
1250
+ if (entry) {
1251
+ update[entry.emailId] = patch;
1252
+ hasImplicitSet = true;
1253
+ }
1254
+ }
1255
+ implicitSet.update = update;
1256
+ }
1257
+ if (Array.isArray(args.onSuccessDestroyEmail)) {
1258
+ const destroy = [];
1259
+ for (const reference of args.onSuccessDestroyEmail) {
1260
+ const entry = resolveSubmissionRef(reference);
1261
+ if (entry) {
1262
+ destroy.push(entry.emailId);
1263
+ hasImplicitSet = true;
1264
+ }
1265
+ }
1266
+ implicitSet.destroy = destroy;
1267
+ }
1268
+ if (hasImplicitSet) {
1269
+ const result = await this.methodEmailSet(account, implicitSet, createdIds);
1270
+ responses.push({
1271
+ name: "Email/set",
1272
+ result,
1273
+ mutated: result.newState !== result.oldState,
1274
+ });
1275
+ }
1276
+ return responses;
1277
+ }
1278
+ /** Uses the client-provided envelope or derives it from the email's addresses. */
1279
+ resolveEnvelope(specEnvelope, identityEmail, email) {
1280
+ if (specEnvelope &&
1281
+ typeof specEnvelope === "object" &&
1282
+ specEnvelope.mailFrom?.email &&
1283
+ Array.isArray(specEnvelope.rcptTo)) {
1284
+ return {
1285
+ mailFrom: { email: String(specEnvelope.mailFrom.email) },
1286
+ rcptTo: specEnvelope.rcptTo
1287
+ .filter((recipient) => typeof recipient?.email === "string")
1288
+ .map((recipient) => ({ email: recipient.email })),
1289
+ };
1290
+ }
1291
+ const recipients = new Set();
1292
+ for (const list of [email.to, email.cc, email.bcc]) {
1293
+ for (const address of list ?? []) {
1294
+ recipients.add(address.email);
1295
+ }
714
1296
  }
715
1297
  return {
716
- accountId: user.accountId,
717
- oldState: String(user.state),
718
- newState: String(user.state),
719
- created,
720
- notCreated,
721
- updated: {},
722
- notUpdated: {},
723
- destroyed: [],
724
- notDestroyed: {},
1298
+ mailFrom: { email: email.from?.[0]?.email ?? identityEmail },
1299
+ rcptTo: Array.from(recipients).map((address) => ({ email: address })),
725
1300
  };
726
1301
  }
727
1302
  // ======================
728
- // internal helpers
1303
+ // upload + download
729
1304
  // ======================
730
- requireUser(username) {
731
- const user = this.users.get(username);
732
- if (!user) {
733
- throw new Error(`User "${username}" does not exist.`);
1305
+ async cancelRequestBody(request, reason) {
1306
+ try {
1307
+ if (request.body && !request.body.locked) {
1308
+ await request.body.cancel(reason);
1309
+ }
734
1310
  }
735
- return user;
736
- }
737
- createEmailFromSpec(user, spec) {
738
- const mailboxIds = spec.mailboxIds;
739
- if (!mailboxIds || !Object.keys(mailboxIds).length) {
740
- throw new Error('Email create requires mailboxIds.');
741
- }
742
- for (const mailboxId of Object.keys(mailboxIds)) {
743
- if (!user.mailboxes.has(mailboxId)) {
744
- throw new Error(`Mailbox "${mailboxId}" does not exist.`);
745
- }
746
- }
747
- const id = `email_${++user.idCounter}`;
748
- const receivedAt = new Date().toISOString();
749
- const bodyValues = (spec.bodyValues ?? {});
750
- const resolvePart = (part) => part?.partId != null ? bodyValues[part.partId]?.value ?? '' : '';
751
- const textBodyParts = (spec.textBody ?? []).map((part) => ({
752
- partId: part.partId ?? null,
753
- type: part.type ?? 'text/plain',
754
- size: resolvePart(part).length,
755
- }));
756
- const htmlBodyParts = (spec.htmlBody ?? []).map((part) => ({
757
- partId: part.partId ?? null,
758
- type: part.type ?? 'text/html',
759
- size: resolvePart(part).length,
760
- }));
761
- const textValue = textBodyParts.map((part) => bodyValues[part.partId ?? '']?.value ?? '').join('\n');
762
- const from = (spec.from ?? []);
763
- const to = (spec.to ?? []);
764
- const blobId = `blob_${id}`;
765
- const rawLines = [
766
- `From: ${from.map((address) => address.email).join(', ')}`,
767
- `To: ${to.map((address) => address.email).join(', ')}`,
768
- `Subject: ${spec.subject ?? ''}`,
769
- `Date: ${receivedAt}`,
770
- '',
771
- textValue,
772
- ];
773
- user.blobs.set(blobId, {
774
- data: Buffer.from(rawLines.join('\r\n'), 'utf8'),
775
- type: 'message/rfc822',
776
- name: `${id}.eml`,
777
- });
778
- const normalizedBodyValues = {};
779
- for (const [partId, bodyValue] of Object.entries(bodyValues)) {
780
- normalizedBodyValues[partId] = { value: bodyValue.value ?? '', isTruncated: false };
1311
+ catch {
1312
+ // The runtime or peer may already have closed the transport stream.
1313
+ }
1314
+ }
1315
+ async readRequestBodyBounded(request, maxBytes) {
1316
+ const declaredLength = request.headers.get("content-length");
1317
+ if (declaredLength !== null) {
1318
+ if (!/^\d+$/.test(declaredLength) ||
1319
+ !Number.isSafeInteger(Number(declaredLength))) {
1320
+ await this.cancelRequestBody(request, "invalid content length");
1321
+ throw new JmapRequestBodyError("invalidLength");
1322
+ }
1323
+ if (Number(declaredLength) > maxBytes) {
1324
+ await this.cancelRequestBody(request, "request body too large");
1325
+ throw new JmapRequestBodyError("tooLarge");
1326
+ }
1327
+ }
1328
+ if (!request.body) {
1329
+ return new Uint8Array();
1330
+ }
1331
+ const reader = request.body.getReader();
1332
+ const chunks = [];
1333
+ let total = 0;
1334
+ try {
1335
+ while (true) {
1336
+ const { done, value } = await reader.read();
1337
+ if (done)
1338
+ break;
1339
+ total += value.byteLength;
1340
+ if (total > maxBytes) {
1341
+ await reader.cancel("request body too large");
1342
+ throw new JmapRequestBodyError("tooLarge");
1343
+ }
1344
+ chunks.push(value);
1345
+ }
1346
+ }
1347
+ finally {
1348
+ reader.releaseLock();
781
1349
  }
1350
+ const data = new Uint8Array(total);
1351
+ let offset = 0;
1352
+ for (const chunk of chunks) {
1353
+ data.set(chunk, offset);
1354
+ offset += chunk.byteLength;
1355
+ }
1356
+ return data;
1357
+ }
1358
+ createExactUploadBody(request, expectedSize) {
1359
+ const abortController = new AbortController();
1360
+ let reader = null;
1361
+ let bytesRead = 0;
1362
+ let complete = false;
1363
+ let cancelled = false;
1364
+ const cancel = async (reason) => {
1365
+ if (cancelled || complete)
1366
+ return;
1367
+ cancelled = true;
1368
+ abortController.abort(reason);
1369
+ try {
1370
+ if (reader) {
1371
+ await reader.cancel(reason);
1372
+ }
1373
+ else if (request.body && !request.body.locked) {
1374
+ await request.body.cancel(reason);
1375
+ }
1376
+ }
1377
+ catch {
1378
+ // The peer or consumer may already have closed the stream.
1379
+ }
1380
+ };
1381
+ const onRequestAbort = () => {
1382
+ void cancel(request.signal.reason ?? new Error("Request aborted."));
1383
+ };
1384
+ request.signal.addEventListener("abort", onRequestAbort, { once: true });
1385
+ if (request.signal.aborted)
1386
+ onRequestAbort();
1387
+ const stream = new ReadableStream({
1388
+ async pull(controller) {
1389
+ if (cancelled) {
1390
+ controller.error(abortController.signal.reason ?? new Error("Upload cancelled."));
1391
+ return;
1392
+ }
1393
+ if (!request.body) {
1394
+ if (expectedSize === 0) {
1395
+ complete = true;
1396
+ controller.close();
1397
+ }
1398
+ else {
1399
+ const error = new JmapRequestBodyError("lengthMismatch");
1400
+ abortController.abort(error);
1401
+ controller.error(error);
1402
+ }
1403
+ return;
1404
+ }
1405
+ reader ??= request.body.getReader();
1406
+ const { done, value } = await reader.read();
1407
+ if (done) {
1408
+ if (bytesRead !== expectedSize) {
1409
+ const error = new JmapRequestBodyError("lengthMismatch");
1410
+ abortController.abort(error);
1411
+ controller.error(error);
1412
+ return;
1413
+ }
1414
+ complete = true;
1415
+ controller.close();
1416
+ return;
1417
+ }
1418
+ bytesRead += value.byteLength;
1419
+ if (bytesRead > expectedSize) {
1420
+ const error = new JmapRequestBodyError("lengthMismatch");
1421
+ await cancel(error);
1422
+ controller.error(error);
1423
+ return;
1424
+ }
1425
+ controller.enqueue(value);
1426
+ },
1427
+ cancel,
1428
+ }, { highWaterMark: 0 });
782
1429
  return {
783
- id,
784
- blobId,
785
- threadId: `thread_${id}`,
786
- mailboxIds: { ...mailboxIds },
787
- keywords: spec.keywords ?? {},
788
- size: textValue.length,
789
- receivedAt,
790
- sentAt: receivedAt,
791
- subject: spec.subject ?? null,
792
- from,
793
- to,
794
- cc: spec.cc ?? null,
795
- bcc: spec.bcc ?? null,
796
- replyTo: spec.replyTo ?? null,
797
- hasAttachment: false,
798
- preview: textValue.slice(0, 100),
799
- bodyValues: normalizedBodyValues,
800
- textBody: textBodyParts,
801
- htmlBody: htmlBodyParts,
802
- attachments: [],
1430
+ stream,
1431
+ signal: abortController.signal,
1432
+ isComplete: () => complete,
1433
+ cancel,
1434
+ dispose: () => request.signal.removeEventListener("abort", onRequestAbort),
803
1435
  };
804
1436
  }
805
- /**
806
- * Applies an Email/set update patch: either whole properties (e.g. keywords)
807
- * or JSON-pointer style paths like "keywords/$seen" (RFC 8620 §5.3).
808
- */
809
- applyPatch(email, patch) {
810
- for (const [path, value] of Object.entries(patch)) {
811
- const segments = path.split('/');
812
- if (segments.length === 1) {
813
- if (value === null) {
814
- delete email[path];
1437
+ mappedUploadErrorResponse(error) {
1438
+ const problem = this.options.mapUploadError?.(error);
1439
+ if (!problem)
1440
+ return null;
1441
+ if (!Number.isInteger(problem.status) || problem.status < 400 ||
1442
+ problem.status > 599 ||
1443
+ !problem.detail) {
1444
+ throw new Error("mapUploadError returned an invalid upload problem.");
1445
+ }
1446
+ const body = {
1447
+ type: problem.type ?? "about:blank",
1448
+ status: problem.status,
1449
+ detail: problem.detail,
1450
+ ...(problem.limit ? { limit: problem.limit } : {}),
1451
+ };
1452
+ const headers = {
1453
+ "content-type": "application/problem+json",
1454
+ };
1455
+ if (problem.retryAfterSeconds !== undefined) {
1456
+ headers["retry-after"] = String(problem.retryAfterSeconds);
1457
+ }
1458
+ return new Response(JSON.stringify(body), {
1459
+ status: problem.status,
1460
+ headers,
1461
+ });
1462
+ }
1463
+ requestBodyErrorResponse(error, limit) {
1464
+ if (error.reason === "invalidLength") {
1465
+ return this.problemResponse(400, "about:blank", "Invalid Content-Length header.");
1466
+ }
1467
+ if (error.reason === "lengthMismatch") {
1468
+ return this.problemResponse(400, "about:blank", "The request body does not match Content-Length.");
1469
+ }
1470
+ const maximum = limit === "maxSizeUpload"
1471
+ ? this.limits.maxSizeUpload
1472
+ : this.limits.maxSizeRequest;
1473
+ return this.limitResponse(400, limit, `The request is larger than ${maximum} bytes.`);
1474
+ }
1475
+ async handleStreamingUpload(account, request, type) {
1476
+ const contentLength = request.headers.get("content-length");
1477
+ if (contentLength === null) {
1478
+ await this.cancelRequestBody(request, "content length required");
1479
+ return this.problemResponse(411, "about:blank", "Content-Length is required.");
1480
+ }
1481
+ if (!/^\d+$/.test(contentLength) ||
1482
+ !Number.isSafeInteger(Number(contentLength))) {
1483
+ await this.cancelRequestBody(request, "invalid content length");
1484
+ return this.problemResponse(400, "about:blank", "Invalid Content-Length header.");
1485
+ }
1486
+ const declaredSize = Number(contentLength);
1487
+ if (declaredSize > this.limits.maxSizeUpload) {
1488
+ await this.cancelRequestBody(request, "request body too large");
1489
+ return this.limitResponse(400, "maxSizeUpload", `The upload is larger than ${this.limits.maxSizeUpload} bytes.`);
1490
+ }
1491
+ if (!request.body && declaredSize !== 0) {
1492
+ return this.problemResponse(400, "about:blank", "The request body does not match Content-Length.");
1493
+ }
1494
+ const body = this.createExactUploadBody(request, declaredSize);
1495
+ const upload = {
1496
+ stream: body.stream,
1497
+ size: declaredSize,
1498
+ type,
1499
+ signal: body.signal,
1500
+ };
1501
+ try {
1502
+ const result = await this.backend.uploadBlobStream(account.accountId, upload);
1503
+ if (!body.isComplete()) {
1504
+ await body.cancel(new JmapRequestBodyError("lengthMismatch"));
1505
+ return this.problemResponse(400, "about:blank", "The upload backend did not consume the exact request body.");
1506
+ }
1507
+ if (result.size !== declaredSize) {
1508
+ throw new Error(`Upload backend reported ${result.size} bytes for a ${declaredSize}-byte request.`);
1509
+ }
1510
+ return this.jsonResponse(200, {
1511
+ accountId: account.accountId,
1512
+ blobId: result.blobId,
1513
+ type,
1514
+ size: result.size,
1515
+ });
1516
+ }
1517
+ catch (error) {
1518
+ await body.cancel(error);
1519
+ if (error instanceof JmapRequestBodyError) {
1520
+ return this.requestBodyErrorResponse(error, "maxSizeUpload");
1521
+ }
1522
+ const mapped = this.mappedUploadErrorResponse(error);
1523
+ if (mapped)
1524
+ return mapped;
1525
+ throw error;
1526
+ }
1527
+ finally {
1528
+ body.dispose();
1529
+ }
1530
+ }
1531
+ async handleUpload(account, principal, pathname, request) {
1532
+ const segments = pathname.split("/").filter((segment) => segment.length > 0);
1533
+ const accountId = decodeURIComponent(segments[2] ?? "");
1534
+ if (accountId !== account.accountId) {
1535
+ await this.cancelRequestBody(request, "unknown account");
1536
+ return this.problemResponse(404, "about:blank", "Unknown account");
1537
+ }
1538
+ const principalUploads = this.activeUploadsByPrincipal.get(principal.username) ?? 0;
1539
+ if (principalUploads >= this.limits.maxConcurrentUpload ||
1540
+ this.activeUploadRequests >= this.maxConcurrentUploadServer) {
1541
+ await this.cancelRequestBody(request, "upload concurrency limit reached");
1542
+ return this.limitResponse(429, "maxConcurrentUpload", "Too many concurrent uploads.");
1543
+ }
1544
+ this.activeUploadRequests++;
1545
+ this.activeUploadsByPrincipal.set(principal.username, principalUploads + 1);
1546
+ try {
1547
+ const type = request.headers.get("content-type") ??
1548
+ "application/octet-stream";
1549
+ if (typeof this.backend.uploadBlobStream === "function") {
1550
+ return await this.handleStreamingUpload(account, request, type);
1551
+ }
1552
+ let data;
1553
+ try {
1554
+ data = await this.readRequestBodyBounded(request, this.limits.maxSizeUpload);
1555
+ }
1556
+ catch (error) {
1557
+ if (error instanceof JmapRequestBodyError) {
1558
+ return this.requestBodyErrorResponse(error, "maxSizeUpload");
1559
+ }
1560
+ throw error;
1561
+ }
1562
+ try {
1563
+ const { blobId, size } = await this.backend.uploadBlob(account.accountId, data, type);
1564
+ return this.jsonResponse(200, {
1565
+ accountId: account.accountId,
1566
+ blobId,
1567
+ type,
1568
+ size,
1569
+ });
1570
+ }
1571
+ catch (error) {
1572
+ const mapped = this.mappedUploadErrorResponse(error);
1573
+ if (mapped)
1574
+ return mapped;
1575
+ throw error;
1576
+ }
1577
+ }
1578
+ finally {
1579
+ this.activeUploadRequests--;
1580
+ const remainingPrincipalUploads = (this.activeUploadsByPrincipal.get(principal.username) ?? 1) - 1;
1581
+ if (remainingPrincipalUploads <= 0) {
1582
+ this.activeUploadsByPrincipal.delete(principal.username);
1583
+ }
1584
+ else {
1585
+ this.activeUploadsByPrincipal.set(principal.username, remainingPrincipalUploads);
1586
+ }
1587
+ }
1588
+ }
1589
+ async handleDownload(account, pathname, url) {
1590
+ // /jmap/download/{accountId}/{blobId}/{name}
1591
+ const segments = pathname.split("/").filter((segment) => segment.length > 0);
1592
+ const accountId = decodeURIComponent(segments[2] ?? "");
1593
+ const blobId = decodeURIComponent(segments[3] ?? "");
1594
+ const name = decodeURIComponent(segments[4] ?? "blob");
1595
+ if (accountId !== account.accountId) {
1596
+ return this.problemResponse(404, "about:blank", "Unknown account");
1597
+ }
1598
+ const blob = await this.backend.getBlob(account.accountId, blobId);
1599
+ if (!blob) {
1600
+ return this.problemResponse(404, "about:blank", "Unknown blob");
1601
+ }
1602
+ const type = url.searchParams.get("type") ?? blob.type;
1603
+ return new Response(asBodyBytes(blob.data), {
1604
+ status: 200,
1605
+ headers: {
1606
+ "content-type": type,
1607
+ "content-length": String(blob.data.length),
1608
+ "content-disposition": `attachment; filename="${name.replaceAll('"', "")}"`,
1609
+ },
1610
+ });
1611
+ }
1612
+ // ======================
1613
+ // event source (SSE)
1614
+ // ======================
1615
+ handleEventSource(account, url) {
1616
+ const typesParam = url.searchParams.get("types") ?? "*";
1617
+ const types = typesParam === "*" || typesParam === "" ? null : new Set(typesParam
1618
+ .split(",")
1619
+ .map((entry) => entry.trim())
1620
+ .filter((entry) => entry.length > 0));
1621
+ const closeAfterState = url.searchParams.get("closeafter") === "state";
1622
+ const pingRaw = Number(url.searchParams.get("ping") ?? "0");
1623
+ const pingSeconds = Number.isFinite(pingRaw) && pingRaw > 0
1624
+ ? Math.max(1, Math.floor(pingRaw))
1625
+ : 0;
1626
+ const state = {
1627
+ accountId: account.accountId,
1628
+ types,
1629
+ closeAfterState,
1630
+ controller: null,
1631
+ pingTimer: null,
1632
+ lastSent: new Map(),
1633
+ closed: false,
1634
+ };
1635
+ const stream = new ReadableStream({
1636
+ start: (controller) => {
1637
+ state.controller = controller;
1638
+ controller.enqueue(textEncoder.encode(": jmap event stream\n\n"));
1639
+ if (pingSeconds > 0) {
1640
+ state.pingTimer = setInterval(() => {
1641
+ this.writeToStream(state, `event: ping\ndata: {"interval":${pingSeconds}}\n\n`);
1642
+ }, pingSeconds * 1000);
815
1643
  }
816
- else {
817
- email[path] = value;
1644
+ try {
1645
+ this.registerStream(state);
818
1646
  }
1647
+ catch (error) {
1648
+ // a throwing backend.subscribeToChanges must not strand the ping timer
1649
+ this.unregisterStream(state);
1650
+ throw error;
1651
+ }
1652
+ },
1653
+ cancel: () => {
1654
+ this.unregisterStream(state);
1655
+ },
1656
+ });
1657
+ return new Response(stream, {
1658
+ status: 200,
1659
+ headers: {
1660
+ "content-type": "text/event-stream",
1661
+ "cache-control": "no-cache",
1662
+ },
1663
+ });
1664
+ }
1665
+ registerStream(state) {
1666
+ if (!this.changeFeedUnsubscribe) {
1667
+ this.changeFeedUnsubscribe = this.backend.subscribeToChanges((change) => {
1668
+ this.pushStateChange(change.accountId, change.changed);
1669
+ });
1670
+ }
1671
+ this.eventStreams.add(state);
1672
+ }
1673
+ unregisterStream(state) {
1674
+ state.closed = true;
1675
+ if (state.pingTimer) {
1676
+ clearInterval(state.pingTimer);
1677
+ state.pingTimer = null;
1678
+ }
1679
+ this.eventStreams.delete(state);
1680
+ if (!this.eventStreams.size && this.changeFeedUnsubscribe) {
1681
+ const unsubscribe = this.changeFeedUnsubscribe;
1682
+ this.changeFeedUnsubscribe = null;
1683
+ try {
1684
+ unsubscribe();
1685
+ }
1686
+ catch (error) {
1687
+ this.cleanupErrors.push(error);
1688
+ }
1689
+ }
1690
+ }
1691
+ closeStream(state) {
1692
+ this.unregisterStream(state);
1693
+ try {
1694
+ state.controller?.close();
1695
+ }
1696
+ catch {
1697
+ // already closed or errored
1698
+ }
1699
+ }
1700
+ writeToStream(state, payload) {
1701
+ if (state.closed || !state.controller) {
1702
+ return;
1703
+ }
1704
+ try {
1705
+ state.controller.enqueue(textEncoder.encode(payload));
1706
+ }
1707
+ catch {
1708
+ this.closeStream(state);
1709
+ }
1710
+ }
1711
+ /**
1712
+ * Pushes a StateChange to matching event streams. Per-type states are
1713
+ * deduplicated per stream, so a mutation notified both by the backend
1714
+ * change feed and by the post-request push is delivered once.
1715
+ */
1716
+ pushStateChange(accountId, changed) {
1717
+ for (const state of Array.from(this.eventStreams)) {
1718
+ if (state.accountId !== accountId) {
819
1719
  continue;
820
1720
  }
821
- let target = email;
822
- for (const segment of segments.slice(0, -1)) {
823
- if (typeof target[segment] !== 'object' || target[segment] === null) {
824
- target[segment] = {};
1721
+ const filtered = {};
1722
+ for (const [type, typeState] of Object.entries(changed)) {
1723
+ if (state.types && !state.types.has(type)) {
1724
+ continue;
825
1725
  }
826
- target = target[segment];
1726
+ if (state.lastSent.get(type) === typeState) {
1727
+ continue;
1728
+ }
1729
+ filtered[type] = typeState;
827
1730
  }
828
- const leaf = segments[segments.length - 1];
829
- if (value === null || value === false) {
830
- delete target[leaf];
1731
+ if (!Object.keys(filtered).length) {
1732
+ continue;
831
1733
  }
832
- else {
833
- target[leaf] = value;
1734
+ for (const [type, typeState] of Object.entries(filtered)) {
1735
+ state.lastSent.set(type, typeState);
1736
+ }
1737
+ const stateChange = {
1738
+ "@type": "StateChange",
1739
+ changed: { [accountId]: filtered },
1740
+ };
1741
+ this.writeToStream(state, `event: state\ndata: ${JSON.stringify(stateChange)}\n\n`);
1742
+ if (state.closeAfterState) {
1743
+ this.closeStream(state);
834
1744
  }
835
1745
  }
836
1746
  }
837
- /** Increments the account state, records the change, and pushes a StateChange to open event streams. */
838
- bumpState(user, change) {
839
- user.state += 1;
840
- user.changes.push({
841
- state: user.state,
842
- created: change.created ?? [],
843
- updated: change.updated ?? [],
844
- destroyed: change.destroyed ?? [],
1747
+ /**
1748
+ * Emits a StateChange after a mutating JMAP request, covering backends
1749
+ * whose change feed only reports out-of-band mutations. Deduplicated
1750
+ * against feed-driven pushes via the per-stream state tracking.
1751
+ */
1752
+ async pushAfterMutation(account) {
1753
+ if (!this.eventStreams.size) {
1754
+ return;
1755
+ }
1756
+ const [emails, mailboxes, threads] = await Promise.all([
1757
+ this.backend.getEmails(account.accountId, []),
1758
+ this.backend.getMailboxes(account.accountId, []),
1759
+ this.backend.getThreads(account.accountId, []),
1760
+ ]);
1761
+ this.pushStateChange(account.accountId, {
1762
+ Email: emails.state,
1763
+ Thread: threads.state,
1764
+ Mailbox: mailboxes.state,
845
1765
  });
846
- this.notifyStateChange(user);
847
- }
848
- notifyStateChange(user) {
849
- const stateChange = {
850
- '@type': 'StateChange',
851
- changed: {
852
- [user.accountId]: {
853
- Email: String(user.state),
854
- Mailbox: String(user.state),
855
- Thread: String(user.state),
856
- },
1766
+ }
1767
+ // ======================
1768
+ // node req/res adapter
1769
+ // ======================
1770
+ nodeRequestBody(req) {
1771
+ let closed = false;
1772
+ let cleanup = () => { };
1773
+ return new ReadableStream({
1774
+ start(controller) {
1775
+ req.pause();
1776
+ const onData = (chunk) => {
1777
+ if (closed)
1778
+ return;
1779
+ controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
1780
+ if ((controller.desiredSize ?? 0) <= 0)
1781
+ req.pause();
1782
+ };
1783
+ const onEnd = () => {
1784
+ if (closed)
1785
+ return;
1786
+ closed = true;
1787
+ cleanup();
1788
+ controller.close();
1789
+ };
1790
+ const onAborted = () => {
1791
+ if (closed)
1792
+ return;
1793
+ closed = true;
1794
+ cleanup();
1795
+ controller.error(new Error("Request body stream was aborted."));
1796
+ };
1797
+ const onError = (error) => {
1798
+ if (closed)
1799
+ return;
1800
+ closed = true;
1801
+ cleanup();
1802
+ controller.error(error);
1803
+ };
1804
+ cleanup = () => {
1805
+ req.off("data", onData);
1806
+ req.off("end", onEnd);
1807
+ req.off("aborted", onAborted);
1808
+ req.off("error", onError);
1809
+ };
1810
+ req.on("data", onData);
1811
+ req.once("end", onEnd);
1812
+ req.once("aborted", onAborted);
1813
+ req.once("error", onError);
857
1814
  },
1815
+ pull() {
1816
+ if (!closed)
1817
+ req.resume();
1818
+ },
1819
+ cancel() {
1820
+ if (closed)
1821
+ return;
1822
+ closed = true;
1823
+ cleanup();
1824
+ // Drain without buffering so the response can reuse the connection.
1825
+ req.resume();
1826
+ },
1827
+ });
1828
+ }
1829
+ async handleNodeRequest(req, res, requestAbortController) {
1830
+ const abortRequest = (reason) => {
1831
+ if (!requestAbortController.signal.aborted) {
1832
+ requestAbortController.abort(reason);
1833
+ }
858
1834
  };
859
- const payload = `event: state\ndata: ${JSON.stringify(stateChange)}\n\n`;
860
- for (const [response, streamUser] of this.eventStreams) {
861
- if (streamUser !== user) {
862
- continue;
1835
+ const onRequestAborted = () => {
1836
+ abortRequest(new Error("Node request was aborted by the client."));
1837
+ };
1838
+ const onRequestError = (error) => {
1839
+ abortRequest(error);
1840
+ };
1841
+ const onRequestClose = () => {
1842
+ // IncomingMessage emits close after normal completion too. Only a
1843
+ // close before the complete HTTP message is a transport abort.
1844
+ if (!req.complete)
1845
+ onRequestAborted();
1846
+ };
1847
+ const onResponseClose = () => {
1848
+ if (!res.writableEnded) {
1849
+ abortRequest(new Error("Node response connection closed before completion."));
1850
+ }
1851
+ };
1852
+ req.once("aborted", onRequestAborted);
1853
+ req.once("error", onRequestError);
1854
+ req.once("close", onRequestClose);
1855
+ res.once("close", onResponseClose);
1856
+ try {
1857
+ const method = (req.method ?? "GET").toUpperCase();
1858
+ const headers = new Headers();
1859
+ const skippedHeaders = new Set([
1860
+ "connection",
1861
+ "expect",
1862
+ "keep-alive",
1863
+ "proxy-connection",
1864
+ "transfer-encoding",
1865
+ "upgrade",
1866
+ ]);
1867
+ for (const [key, value] of Object.entries(req.headers)) {
1868
+ if (value === undefined || skippedHeaders.has(key.toLowerCase())) {
1869
+ continue;
1870
+ }
1871
+ headers.set(key, Array.isArray(value) ? value.join(", ") : value);
1872
+ }
1873
+ const host = req.headers.host ?? "127.0.0.1";
1874
+ const requestInit = {
1875
+ method,
1876
+ headers,
1877
+ signal: requestAbortController.signal,
1878
+ };
1879
+ if (method !== "GET" && method !== "HEAD") {
1880
+ requestInit.body = this.nodeRequestBody(req);
1881
+ requestInit.duplex = "half";
1882
+ }
1883
+ const request = new Request(`http://${host}${req.url ?? "/"}`, requestInit);
1884
+ const response = await this.fetchHandler(request);
1885
+ const responseHeaders = {};
1886
+ response.headers.forEach((value, key) => {
1887
+ responseHeaders[key] = value;
1888
+ });
1889
+ res.writeHead(response.status, responseHeaders);
1890
+ if (!response.body) {
1891
+ res.end();
1892
+ return;
863
1893
  }
1894
+ const reader = response.body.getReader();
1895
+ let clientClosed = false;
1896
+ res.on("close", () => {
1897
+ clientClosed = true;
1898
+ // Cancelling the reader triggers the stream's cancel handler, which
1899
+ // releases any per-stream resources (SSE registration, ping timer).
1900
+ void reader.cancel().catch(() => { });
1901
+ });
864
1902
  try {
865
- response.write(payload);
1903
+ while (true) {
1904
+ const { done, value } = await reader.read();
1905
+ if (done || clientClosed || res.destroyed) {
1906
+ break;
1907
+ }
1908
+ res.write(value);
1909
+ }
866
1910
  }
867
1911
  catch {
868
- this.eventStreams.delete(response);
1912
+ // stream cancelled or connection gone
1913
+ }
1914
+ if (!res.destroyed) {
1915
+ res.end();
1916
+ }
1917
+ }
1918
+ catch (error) {
1919
+ const message = error instanceof Error ? error.message : String(error);
1920
+ if (!res.headersSent) {
1921
+ res.writeHead(500, { "content-type": "application/problem+json" });
869
1922
  }
1923
+ res.end(JSON.stringify({ type: "about:blank", status: 500, detail: message }));
870
1924
  }
1925
+ finally {
1926
+ req.off("aborted", onRequestAborted);
1927
+ req.off("error", onRequestError);
1928
+ req.off("close", onRequestClose);
1929
+ res.off("close", onResponseClose);
1930
+ }
1931
+ }
1932
+ // ======================
1933
+ // shared validators + responses
1934
+ // ======================
1935
+ validateProperties(requested, known) {
1936
+ if (requested === null || requested === undefined) {
1937
+ return null;
1938
+ }
1939
+ if (!Array.isArray(requested)) {
1940
+ throw new JmapServerMethodError("invalidArguments", "properties must be an array or null.");
1941
+ }
1942
+ for (const property of requested) {
1943
+ if (typeof property !== "string" || !known.has(property)) {
1944
+ throw new JmapServerMethodError("invalidArguments", `Unknown property "${String(property)}".`);
1945
+ }
1946
+ }
1947
+ return requested.includes("id") ? requested : ["id", ...requested];
1948
+ }
1949
+ projectObject(source, properties) {
1950
+ const projected = {};
1951
+ for (const property of properties) {
1952
+ projected[property] = source[property] === undefined
1953
+ ? null
1954
+ : source[property];
1955
+ }
1956
+ return projected;
1957
+ }
1958
+ validatePosition(args) {
1959
+ if (args.position === undefined || args.position === null) {
1960
+ return 0;
1961
+ }
1962
+ if (!Number.isInteger(args.position) || args.position < 0) {
1963
+ throw new JmapServerMethodError("invalidArguments", "position must be a non-negative integer.");
1964
+ }
1965
+ return args.position;
1966
+ }
1967
+ validateChangesArgs(args) {
1968
+ if (typeof args.sinceState !== "string") {
1969
+ throw new JmapServerMethodError("invalidArguments", "sinceState is required.");
1970
+ }
1971
+ let maxChanges;
1972
+ if (args.maxChanges !== undefined && args.maxChanges !== null) {
1973
+ if (!Number.isInteger(args.maxChanges) || args.maxChanges <= 0) {
1974
+ throw new JmapServerMethodError("invalidArguments", "maxChanges must be a positive integer.");
1975
+ }
1976
+ maxChanges = args.maxChanges;
1977
+ }
1978
+ return { sinceState: args.sinceState, maxChanges };
1979
+ }
1980
+ jsonResponse(status, body) {
1981
+ return new Response(JSON.stringify(body), {
1982
+ status,
1983
+ headers: { "content-type": "application/json" },
1984
+ });
1985
+ }
1986
+ problemResponse(status, type, detail, extraHeaders = {}) {
1987
+ return new Response(JSON.stringify({ type, status, detail }), {
1988
+ status,
1989
+ headers: { "content-type": "application/problem+json", ...extraHeaders },
1990
+ });
1991
+ }
1992
+ limitResponse(status, limit, detail) {
1993
+ return new Response(JSON.stringify({
1994
+ type: "urn:ietf:params:jmap:error:limit",
1995
+ limit,
1996
+ status,
1997
+ detail,
1998
+ }), { status, headers: { "content-type": "application/problem+json" } });
871
1999
  }
872
2000
  }
873
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qbWFwc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5qbWFwc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFtRWxELDBGQUEwRjtBQUMxRixNQUFNLHFCQUFzQixTQUFRLEtBQUs7SUFDdkMsWUFBbUIsSUFBWSxFQUFFLFdBQW9CO1FBQ25ELEtBQUssQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLENBQUM7UUFEVixTQUFJLEdBQUosSUFBSSxDQUFRO0lBRS9CLENBQUM7Q0FDRjtBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFNckI7UUFMTyxVQUFLLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUM7UUFFL0MsWUFBTyxHQUE0QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzdDLGlCQUFZLEdBQXNELElBQUksR0FBRyxFQUFFLENBQUM7UUFHbEYsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUNuRCxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pCLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtnQkFDdEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDOUIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCx5QkFBeUI7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
2001
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qbWFwc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5qbWFwc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFDbEQsT0FBTyxFQUVMLG9CQUFvQixFQUNwQixvQkFBb0IsRUFDcEIsMEJBQTBCLEdBRTNCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQVlOLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFbkU7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFHLENBQVUsQ0FBQztBQXFENUQsNERBQTREO0FBQzVELE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFzQjtJQUNuRCxhQUFhLEVBQUUsVUFBVTtJQUN6QixtQkFBbUIsRUFBRSxDQUFDO0lBQ3RCLGNBQWMsRUFBRSxVQUFVO0lBQzFCLHFCQUFxQixFQUFFLENBQUM7SUFDeEIsaUJBQWlCLEVBQUUsRUFBRTtJQUNyQixlQUFlLEVBQUUsR0FBRztJQUNwQixlQUFlLEVBQUUsR0FBRztDQUNyQixDQUFDO0FBRUYsNkVBQTZFO0FBQzdFLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQztBQUUxQixzREFBc0Q7QUFDdEQsTUFBTSx3QkFBd0IsR0FBRztJQUMvQixJQUFJO0lBQ0osUUFBUTtJQUNSLFVBQVU7SUFDVixZQUFZO0lBQ1osVUFBVTtJQUNWLE1BQU07SUFDTixZQUFZO0lBQ1osV0FBVztJQUNYLFdBQVc7SUFDWCxZQUFZO0lBQ1osUUFBUTtJQUNSLE1BQU07SUFDTixJQUFJO0lBQ0osSUFBSTtJQUNKLEtBQUs7SUFDTCxTQUFTO0lBQ1QsU0FBUztJQUNULFFBQVE7SUFDUixlQUFlO0lBQ2YsU0FBUztJQUNULFlBQVk7SUFDWixVQUFVO0lBQ1YsVUFBVTtJQUNWLGFBQWE7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