@push.rocks/smartjmap 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.smartconfig.json +4 -2
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/classes.jmapclient.d.ts +21 -0
- package/dist_ts/classes.jmapclient.js +37 -1
- package/dist_ts/classes.jmapserver.d.ts +111 -86
- package/dist_ts/classes.jmapserver.js +1250 -644
- package/dist_ts/classes.memorymailbackend.d.ts +109 -0
- package/dist_ts/classes.memorymailbackend.js +670 -0
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/interfaces.backend.d.ts +330 -0
- package/dist_ts/interfaces.backend.js +13 -0
- package/npmextra.json +4 -2
- package/package.json +4 -2
- package/readme.hints.md +25 -14
- package/readme.md +116 -16
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/classes.jmapclient.ts +58 -0
- package/ts/classes.jmapserver.ts +1548 -752
- package/ts/classes.memorymailbackend.ts +850 -0
- package/ts/index.ts +2 -0
- package/ts/interfaces.backend.ts +392 -0
|
@@ -1,4 +1,86 @@
|
|
|
1
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
|
+
/** The advertised — and enforced — RFC 8620 core limits. */
|
|
6
|
+
export const JMAP_SERVER_LIMITS = {
|
|
7
|
+
maxSizeUpload: 50_000_000,
|
|
8
|
+
maxConcurrentUpload: 4,
|
|
9
|
+
maxSizeRequest: 10_000_000,
|
|
10
|
+
maxConcurrentRequests: 4,
|
|
11
|
+
maxCallsInRequest: 16,
|
|
12
|
+
maxObjectsInGet: 500,
|
|
13
|
+
maxObjectsInSet: 500,
|
|
14
|
+
};
|
|
15
|
+
/** The session object never changes at runtime, so its state is constant. */
|
|
16
|
+
const SESSION_STATE = '0';
|
|
17
|
+
/** Default Email/get properties per RFC 8621 §4.2. */
|
|
18
|
+
const DEFAULT_EMAIL_PROPERTIES = [
|
|
19
|
+
'id',
|
|
20
|
+
'blobId',
|
|
21
|
+
'threadId',
|
|
22
|
+
'mailboxIds',
|
|
23
|
+
'keywords',
|
|
24
|
+
'size',
|
|
25
|
+
'receivedAt',
|
|
26
|
+
'messageId',
|
|
27
|
+
'inReplyTo',
|
|
28
|
+
'references',
|
|
29
|
+
'sender',
|
|
30
|
+
'from',
|
|
31
|
+
'to',
|
|
32
|
+
'cc',
|
|
33
|
+
'bcc',
|
|
34
|
+
'replyTo',
|
|
35
|
+
'subject',
|
|
36
|
+
'sentAt',
|
|
37
|
+
'hasAttachment',
|
|
38
|
+
'preview',
|
|
39
|
+
'bodyValues',
|
|
40
|
+
'textBody',
|
|
41
|
+
'htmlBody',
|
|
42
|
+
'attachments',
|
|
43
|
+
];
|
|
44
|
+
const KNOWN_EMAIL_PROPERTIES = new Set(DEFAULT_EMAIL_PROPERTIES);
|
|
45
|
+
const MAILBOX_PROPERTIES = [
|
|
46
|
+
'id',
|
|
47
|
+
'name',
|
|
48
|
+
'parentId',
|
|
49
|
+
'role',
|
|
50
|
+
'sortOrder',
|
|
51
|
+
'totalEmails',
|
|
52
|
+
'unreadEmails',
|
|
53
|
+
'totalThreads',
|
|
54
|
+
'unreadThreads',
|
|
55
|
+
'myRights',
|
|
56
|
+
'isSubscribed',
|
|
57
|
+
];
|
|
58
|
+
const KNOWN_MAILBOX_PROPERTIES = new Set(MAILBOX_PROPERTIES);
|
|
59
|
+
const SUPPORTED_EMAIL_FILTER_KEYS = new Set([
|
|
60
|
+
'inMailbox',
|
|
61
|
+
'text',
|
|
62
|
+
'subject',
|
|
63
|
+
'from',
|
|
64
|
+
'to',
|
|
65
|
+
'before',
|
|
66
|
+
'after',
|
|
67
|
+
'hasKeyword',
|
|
68
|
+
'notKeyword',
|
|
69
|
+
]);
|
|
70
|
+
const DEFAULT_MAILBOX_RIGHTS = {
|
|
71
|
+
mayReadItems: true,
|
|
72
|
+
mayAddItems: true,
|
|
73
|
+
mayRemoveItems: true,
|
|
74
|
+
maySetSeen: true,
|
|
75
|
+
maySetKeywords: true,
|
|
76
|
+
mayCreateChild: true,
|
|
77
|
+
mayRename: true,
|
|
78
|
+
mayDelete: true,
|
|
79
|
+
maySubmit: true,
|
|
80
|
+
};
|
|
81
|
+
const textEncoder = new TextEncoder();
|
|
82
|
+
/** Ensures bytes are backed by a plain ArrayBuffer so they satisfy BodyInit. */
|
|
83
|
+
const asBodyBytes = (data) => data.buffer instanceof ArrayBuffer ? data : new Uint8Array(data);
|
|
2
84
|
/** Error type used inside method dispatch; rendered as a JMAP `error` method response. */
|
|
3
85
|
class JmapServerMethodError extends Error {
|
|
4
86
|
constructor(type, description) {
|
|
@@ -6,238 +88,207 @@ class JmapServerMethodError extends Error {
|
|
|
6
88
|
this.type = type;
|
|
7
89
|
}
|
|
8
90
|
}
|
|
91
|
+
/** UTF-8-safe truncation: cuts at a codepoint boundary at or below maxBytes. */
|
|
92
|
+
const truncateUtf8 = (value, maxBytes) => {
|
|
93
|
+
const bytes = textEncoder.encode(value);
|
|
94
|
+
if (bytes.length <= maxBytes) {
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
let end = maxBytes;
|
|
98
|
+
while (end > 0 && (bytes[end] & 0b1100_0000) === 0b1000_0000) {
|
|
99
|
+
end--;
|
|
100
|
+
}
|
|
101
|
+
return new TextDecoder().decode(bytes.subarray(0, end));
|
|
102
|
+
};
|
|
9
103
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
104
|
+
* Evaluates an RFC 6901 JSON pointer with the RFC 8620 §3.7 extension: a `*`
|
|
105
|
+
* token applied to an array maps the rest of the pointer over every item,
|
|
106
|
+
* flattening one array level. Throws on any unresolvable path.
|
|
107
|
+
*/
|
|
108
|
+
const evalJsonPointer = (root, pointer) => {
|
|
109
|
+
if (pointer === '') {
|
|
110
|
+
return root;
|
|
111
|
+
}
|
|
112
|
+
if (!pointer.startsWith('/')) {
|
|
113
|
+
throw new Error(`Invalid JSON pointer "${pointer}".`);
|
|
114
|
+
}
|
|
115
|
+
const tokens = pointer.slice(1).split('/');
|
|
116
|
+
const evaluate = (value, index) => {
|
|
117
|
+
if (index === tokens.length) {
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
const token = tokens[index].replaceAll('~1', '/').replaceAll('~0', '~');
|
|
121
|
+
if (Array.isArray(value)) {
|
|
122
|
+
if (token === '*') {
|
|
123
|
+
const results = value.map((item) => evaluate(item, index + 1));
|
|
124
|
+
return results.some((result) => Array.isArray(result))
|
|
125
|
+
? results.flatMap((result) => (Array.isArray(result) ? result : [result]))
|
|
126
|
+
: results;
|
|
127
|
+
}
|
|
128
|
+
const arrayIndex = Number(token);
|
|
129
|
+
if (!Number.isInteger(arrayIndex) || arrayIndex < 0 || arrayIndex >= value.length) {
|
|
130
|
+
throw new Error(`JSON pointer index "${token}" is out of range.`);
|
|
131
|
+
}
|
|
132
|
+
return evaluate(value[arrayIndex], index + 1);
|
|
133
|
+
}
|
|
134
|
+
if (value !== null && typeof value === 'object' && token in value) {
|
|
135
|
+
return evaluate(value[token], index + 1);
|
|
136
|
+
}
|
|
137
|
+
throw new Error(`JSON pointer token "${token}" does not resolve.`);
|
|
138
|
+
};
|
|
139
|
+
return evaluate(root, 0);
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* A JMAP server core (RFC 8620) with the RFC 8621 mail method surface,
|
|
143
|
+
* dispatching all storage into a pluggable `IJmapMailBackend`.
|
|
144
|
+
*
|
|
145
|
+
* The primary API is the web-standard `fetchHandler(request)` — mount it in
|
|
146
|
+
* any Request/Response runtime (Deno, Bun, service workers, Node ≥18). The
|
|
147
|
+
* `start(port)`/`stop()` pair wraps it in a node:http server for convenience.
|
|
148
|
+
*
|
|
149
|
+
* Endpoints: session (`/.well-known/jmap`, `/jmap/session`), API
|
|
150
|
+
* (`/jmap/api`), upload (`/jmap/upload/{accountId}`), download
|
|
151
|
+
* (`/jmap/download/{accountId}/{blobId}/{name}?type=`), and event source
|
|
152
|
+
* (`/jmap/eventsource` — SSE StateChange pushes per RFC 8620 §7.3).
|
|
153
|
+
*
|
|
154
|
+
* With no options this behaves as the offline test helper: an in-memory
|
|
155
|
+
* backend plus a static credential registry (`addUser`/`addBearerToken`).
|
|
14
156
|
*/
|
|
15
157
|
export class JmapServer {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.
|
|
158
|
+
constructor(options = {}) {
|
|
159
|
+
this.registry = new Map();
|
|
160
|
+
this.httpServer = null;
|
|
18
161
|
this.sockets = new Set();
|
|
19
|
-
this.eventStreams = new
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.
|
|
24
|
-
this.sockets.add(socket);
|
|
25
|
-
socket.on('close', () => {
|
|
26
|
-
this.sockets.delete(socket);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
162
|
+
this.eventStreams = new Set();
|
|
163
|
+
this.changeFeedUnsubscribe = null;
|
|
164
|
+
this.activeApiRequests = 0;
|
|
165
|
+
this.options = options;
|
|
166
|
+
this.backend = options.backend ?? new MemoryMailBackend();
|
|
29
167
|
}
|
|
30
168
|
// ======================
|
|
31
|
-
//
|
|
169
|
+
// default auth registry
|
|
32
170
|
// ======================
|
|
171
|
+
/**
|
|
172
|
+
* Registers Basic credentials in the default authenticator's registry.
|
|
173
|
+
* Only consulted when no custom `authenticate` option is set. Account data
|
|
174
|
+
* itself lives in the backend (the memory backend auto-creates accounts).
|
|
175
|
+
*/
|
|
33
176
|
addUser(username, password) {
|
|
34
|
-
if (this.
|
|
177
|
+
if (this.registry.has(username)) {
|
|
35
178
|
throw new Error(`User "${username}" already exists.`);
|
|
36
179
|
}
|
|
37
|
-
|
|
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
|
-
});
|
|
180
|
+
this.registry.set(username, { password, bearerTokens: new Set() });
|
|
52
181
|
}
|
|
53
|
-
/** Registers a valid Bearer token for a user. */
|
|
182
|
+
/** Registers a valid Bearer token for a user in the default authenticator. */
|
|
54
183
|
addBearerToken(username, token) {
|
|
55
|
-
const
|
|
56
|
-
|
|
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
|
-
});
|
|
184
|
+
const entry = this.registry.get(username);
|
|
185
|
+
if (!entry) {
|
|
186
|
+
throw new Error(`User "${username}" does not exist.`);
|
|
128
187
|
}
|
|
129
|
-
|
|
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;
|
|
188
|
+
entry.bearerTokens.add(token);
|
|
154
189
|
}
|
|
155
190
|
// ======================
|
|
156
|
-
// lifecycle
|
|
191
|
+
// lifecycle (node wrapper)
|
|
157
192
|
// ======================
|
|
158
|
-
/** Starts
|
|
193
|
+
/** Starts a node:http server around fetchHandler. Resolves with the bound port (pass 0 for ephemeral). */
|
|
159
194
|
start(port) {
|
|
195
|
+
if (this.httpServer) {
|
|
196
|
+
throw new Error('JmapServer is already started.');
|
|
197
|
+
}
|
|
198
|
+
const server = plugins.http.createServer((req, res) => {
|
|
199
|
+
void this.handleNodeRequest(req, res);
|
|
200
|
+
});
|
|
201
|
+
server.on('connection', (socket) => {
|
|
202
|
+
this.sockets.add(socket);
|
|
203
|
+
socket.on('close', () => {
|
|
204
|
+
this.sockets.delete(socket);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
this.httpServer = server;
|
|
160
208
|
return new Promise((resolve, reject) => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const address =
|
|
209
|
+
server.once('error', reject);
|
|
210
|
+
server.listen(port, () => {
|
|
211
|
+
const address = server.address();
|
|
164
212
|
const boundPort = typeof address === 'object' && address ? address.port : port;
|
|
165
213
|
resolve(boundPort);
|
|
166
214
|
});
|
|
167
215
|
});
|
|
168
216
|
}
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
217
|
+
/**
|
|
218
|
+
* Stops the server: closes all event streams (clearing their ping timers
|
|
219
|
+
* and the backend change-feed subscription), destroys open connections,
|
|
220
|
+
* and closes the node listener when one was started.
|
|
221
|
+
*/
|
|
222
|
+
async stop() {
|
|
223
|
+
for (const stream of Array.from(this.eventStreams)) {
|
|
224
|
+
this.closeStream(stream);
|
|
178
225
|
}
|
|
179
|
-
this.eventStreams.clear();
|
|
180
226
|
for (const socket of this.sockets) {
|
|
181
227
|
socket.destroy();
|
|
182
228
|
}
|
|
183
229
|
this.sockets.clear();
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
230
|
+
const server = this.httpServer;
|
|
231
|
+
this.httpServer = null;
|
|
232
|
+
if (server) {
|
|
233
|
+
await new Promise((resolve) => {
|
|
234
|
+
server.close(() => {
|
|
235
|
+
resolve();
|
|
236
|
+
});
|
|
187
237
|
});
|
|
188
|
-
}
|
|
238
|
+
}
|
|
189
239
|
}
|
|
190
240
|
// ======================
|
|
191
|
-
//
|
|
241
|
+
// web-standard core
|
|
192
242
|
// ======================
|
|
193
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Handles a JMAP request end to end and returns the Response. This is the
|
|
245
|
+
* runtime-agnostic core — mount it directly as a Deno/Bun fetch handler.
|
|
246
|
+
*/
|
|
247
|
+
async fetchHandler(request) {
|
|
194
248
|
try {
|
|
195
|
-
const
|
|
196
|
-
if (!
|
|
197
|
-
|
|
249
|
+
const principal = await this.authenticatePrincipal(request);
|
|
250
|
+
if (!principal) {
|
|
251
|
+
return this.problemResponse(401, 'about:blank', 'Authentication required', {
|
|
198
252
|
'www-authenticate': 'Bearer realm="jmap", Basic realm="jmap"',
|
|
199
|
-
'content-type': 'application/problem+json',
|
|
200
253
|
});
|
|
201
|
-
res.end(JSON.stringify({ type: 'about:blank', status: 401, detail: 'Authentication required' }));
|
|
202
|
-
return;
|
|
203
254
|
}
|
|
204
|
-
const
|
|
255
|
+
const account = await this.backend.resolveAccount(principal);
|
|
256
|
+
if (!account) {
|
|
257
|
+
return this.problemResponse(403, 'about:blank', 'No account for this principal');
|
|
258
|
+
}
|
|
259
|
+
const url = new URL(request.url);
|
|
205
260
|
const pathname = url.pathname;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return;
|
|
261
|
+
const method = request.method.toUpperCase();
|
|
262
|
+
if (method === 'GET' && (pathname === '/.well-known/jmap' || pathname === '/jmap/session')) {
|
|
263
|
+
return this.handleSession(account, principal);
|
|
209
264
|
}
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
req.on('data', (chunk) => {
|
|
213
|
-
body += chunk;
|
|
214
|
-
});
|
|
215
|
-
req.on('end', () => {
|
|
216
|
-
this.handleApi(user, body, res);
|
|
217
|
-
});
|
|
218
|
-
return;
|
|
265
|
+
if (method === 'POST' && pathname === '/jmap/api') {
|
|
266
|
+
return this.handleApi(account, request);
|
|
219
267
|
}
|
|
220
|
-
if (
|
|
221
|
-
this.
|
|
222
|
-
return;
|
|
268
|
+
if (method === 'POST' && pathname.startsWith('/jmap/upload/')) {
|
|
269
|
+
return this.handleUpload(account, pathname, request);
|
|
223
270
|
}
|
|
224
|
-
if (
|
|
225
|
-
this.handleDownload(
|
|
226
|
-
|
|
271
|
+
if (method === 'GET' && pathname.startsWith('/jmap/download/')) {
|
|
272
|
+
return this.handleDownload(account, pathname, url);
|
|
273
|
+
}
|
|
274
|
+
if (method === 'GET' && pathname === '/jmap/eventsource') {
|
|
275
|
+
return this.handleEventSource(account, url);
|
|
227
276
|
}
|
|
228
|
-
|
|
229
|
-
res.end(JSON.stringify({ type: 'about:blank', status: 404, detail: 'Not found' }));
|
|
277
|
+
return this.problemResponse(404, 'about:blank', 'Not found');
|
|
230
278
|
}
|
|
231
279
|
catch (error) {
|
|
232
280
|
const message = error instanceof Error ? error.message : String(error);
|
|
233
|
-
|
|
234
|
-
res.writeHead(500, { 'content-type': 'application/problem+json' });
|
|
235
|
-
}
|
|
236
|
-
res.end(JSON.stringify({ type: 'about:blank', status: 500, detail: message }));
|
|
281
|
+
return this.problemResponse(500, 'about:blank', message);
|
|
237
282
|
}
|
|
238
283
|
}
|
|
239
|
-
|
|
240
|
-
|
|
284
|
+
// ======================
|
|
285
|
+
// authentication
|
|
286
|
+
// ======================
|
|
287
|
+
async authenticatePrincipal(request) {
|
|
288
|
+
if (this.options.authenticate) {
|
|
289
|
+
return this.options.authenticate(request);
|
|
290
|
+
}
|
|
291
|
+
const header = request.headers.get('authorization');
|
|
241
292
|
if (!header) {
|
|
242
293
|
return null;
|
|
243
294
|
}
|
|
@@ -248,431 +299,669 @@ export class JmapServer {
|
|
|
248
299
|
const scheme = header.slice(0, spaceIndex).toLowerCase();
|
|
249
300
|
const value = header.slice(spaceIndex + 1).trim();
|
|
250
301
|
if (scheme === 'bearer') {
|
|
251
|
-
for (const
|
|
252
|
-
if (
|
|
253
|
-
return
|
|
302
|
+
for (const [username, entry] of this.registry) {
|
|
303
|
+
if (entry.bearerTokens.has(value)) {
|
|
304
|
+
return { username };
|
|
254
305
|
}
|
|
255
306
|
}
|
|
256
307
|
return null;
|
|
257
308
|
}
|
|
258
309
|
if (scheme === 'basic') {
|
|
259
|
-
|
|
310
|
+
let decoded;
|
|
311
|
+
try {
|
|
312
|
+
const binary = atob(value);
|
|
313
|
+
decoded = new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
260
318
|
const colonIndex = decoded.indexOf(':');
|
|
261
319
|
if (colonIndex === -1) {
|
|
262
320
|
return null;
|
|
263
321
|
}
|
|
264
322
|
const username = decoded.slice(0, colonIndex);
|
|
265
323
|
const password = decoded.slice(colonIndex + 1);
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
return
|
|
324
|
+
const entry = this.registry.get(username);
|
|
325
|
+
if (entry && entry.password === password) {
|
|
326
|
+
return { username };
|
|
269
327
|
}
|
|
270
328
|
return null;
|
|
271
329
|
}
|
|
272
330
|
return null;
|
|
273
331
|
}
|
|
274
|
-
|
|
332
|
+
// ======================
|
|
333
|
+
// session
|
|
334
|
+
// ======================
|
|
335
|
+
handleSession(account, principal) {
|
|
275
336
|
const session = {
|
|
276
337
|
capabilities: {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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'],
|
|
338
|
+
[JMAP_CORE_CAPABILITY]: {
|
|
339
|
+
...JMAP_SERVER_LIMITS,
|
|
340
|
+
collationAlgorithms: ['i;ascii-casemap'],
|
|
286
341
|
},
|
|
287
|
-
|
|
288
|
-
|
|
342
|
+
[JMAP_MAIL_CAPABILITY]: {},
|
|
343
|
+
[JMAP_SUBMISSION_CAPABILITY]: {},
|
|
289
344
|
},
|
|
290
345
|
accounts: {
|
|
291
|
-
[
|
|
292
|
-
name:
|
|
293
|
-
isPersonal: true,
|
|
294
|
-
isReadOnly: false,
|
|
346
|
+
[account.accountId]: {
|
|
347
|
+
name: account.name,
|
|
348
|
+
isPersonal: account.isPersonal ?? true,
|
|
349
|
+
isReadOnly: account.isReadOnly ?? false,
|
|
295
350
|
accountCapabilities: {
|
|
296
|
-
|
|
297
|
-
|
|
351
|
+
[JMAP_MAIL_CAPABILITY]: {
|
|
352
|
+
maxMailboxesPerEmail: null,
|
|
353
|
+
maxMailboxDepth: null,
|
|
354
|
+
maxSizeMailboxName: 490,
|
|
355
|
+
maxSizeAttachmentsPerEmail: JMAP_SERVER_LIMITS.maxSizeUpload,
|
|
356
|
+
emailQuerySortOptions: ['receivedAt'],
|
|
357
|
+
mayCreateTopLevelMailbox: false,
|
|
358
|
+
},
|
|
359
|
+
[JMAP_SUBMISSION_CAPABILITY]: {
|
|
360
|
+
maxDelayedSend: 0,
|
|
361
|
+
submissionExtensions: {},
|
|
362
|
+
},
|
|
298
363
|
},
|
|
299
364
|
},
|
|
300
365
|
},
|
|
301
366
|
primaryAccounts: {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
367
|
+
[JMAP_CORE_CAPABILITY]: account.accountId,
|
|
368
|
+
[JMAP_MAIL_CAPABILITY]: account.accountId,
|
|
369
|
+
[JMAP_SUBMISSION_CAPABILITY]: account.accountId,
|
|
305
370
|
},
|
|
306
|
-
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:
|
|
371
|
+
username: principal.username,
|
|
372
|
+
apiUrl: this.buildUrl('/jmap/api'),
|
|
373
|
+
downloadUrl: this.buildUrl('/jmap/download/{accountId}/{blobId}/{name}?type={type}'),
|
|
374
|
+
uploadUrl: this.buildUrl('/jmap/upload/{accountId}'),
|
|
375
|
+
eventSourceUrl: this.buildUrl('/jmap/eventsource?types={types}&closeafter={closeafter}&ping={ping}'),
|
|
376
|
+
state: SESSION_STATE,
|
|
312
377
|
};
|
|
313
|
-
|
|
314
|
-
res.end(JSON.stringify(session));
|
|
378
|
+
return this.jsonResponse(200, session);
|
|
315
379
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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;
|
|
380
|
+
buildUrl(path) {
|
|
381
|
+
const base = this.options.baseUrl;
|
|
382
|
+
return base ? `${base.replace(/\/+$/, '')}${path}` : path;
|
|
383
|
+
}
|
|
384
|
+
// ======================
|
|
385
|
+
// api endpoint
|
|
386
|
+
// ======================
|
|
387
|
+
async handleApi(account, request) {
|
|
388
|
+
if (this.activeApiRequests >= JMAP_SERVER_LIMITS.maxConcurrentRequests) {
|
|
389
|
+
return this.limitResponse(429, 'maxConcurrentRequests', 'Too many concurrent requests.');
|
|
338
390
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
391
|
+
this.activeApiRequests++;
|
|
392
|
+
try {
|
|
393
|
+
const bytes = new Uint8Array(await request.arrayBuffer());
|
|
394
|
+
if (bytes.length > JMAP_SERVER_LIMITS.maxSizeRequest) {
|
|
395
|
+
return this.limitResponse(400, 'maxSizeRequest', `The request is larger than ${JMAP_SERVER_LIMITS.maxSizeRequest} bytes.`);
|
|
396
|
+
}
|
|
397
|
+
let parsed;
|
|
343
398
|
try {
|
|
344
|
-
|
|
345
|
-
methodResponses.push([methodName, result, callId]);
|
|
399
|
+
parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
346
400
|
}
|
|
347
|
-
catch
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
401
|
+
catch {
|
|
402
|
+
return this.problemResponse(400, 'urn:ietf:params:jmap:error:notJSON', 'The request body is not valid JSON.');
|
|
403
|
+
}
|
|
404
|
+
if (!parsed ||
|
|
405
|
+
typeof parsed !== 'object' ||
|
|
406
|
+
!Array.isArray(parsed.using) ||
|
|
407
|
+
!Array.isArray(parsed.methodCalls)) {
|
|
408
|
+
return this.problemResponse(400, 'urn:ietf:params:jmap:error:notRequest', 'The request body is not a valid JMAP request object.');
|
|
409
|
+
}
|
|
410
|
+
const knownCapabilities = new Set([
|
|
411
|
+
JMAP_CORE_CAPABILITY,
|
|
412
|
+
JMAP_MAIL_CAPABILITY,
|
|
413
|
+
JMAP_SUBMISSION_CAPABILITY,
|
|
414
|
+
]);
|
|
415
|
+
const using = new Set(parsed.using);
|
|
416
|
+
for (const capability of using) {
|
|
417
|
+
if (!knownCapabilities.has(capability)) {
|
|
418
|
+
return this.problemResponse(400, 'urn:ietf:params:jmap:error:unknownCapability', `The capability "${capability}" is not supported by this server.`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (parsed.methodCalls.length > JMAP_SERVER_LIMITS.maxCallsInRequest) {
|
|
422
|
+
return this.limitResponse(400, 'maxCallsInRequest', `The request has more than ${JMAP_SERVER_LIMITS.maxCallsInRequest} method calls.`);
|
|
423
|
+
}
|
|
424
|
+
const createdIds = new Map(Object.entries((parsed.createdIds ?? {})));
|
|
425
|
+
const methodResponses = [];
|
|
426
|
+
let mutated = false;
|
|
427
|
+
for (const call of parsed.methodCalls) {
|
|
428
|
+
if (!Array.isArray(call) || typeof call[0] !== 'string' || typeof call[2] !== 'string') {
|
|
429
|
+
return this.problemResponse(400, 'urn:ietf:params:jmap:error:notRequest', 'Each method call must be a [name, arguments, callId] tuple.');
|
|
430
|
+
}
|
|
431
|
+
const [methodName, rawArgs, callId] = call;
|
|
432
|
+
try {
|
|
433
|
+
const args = this.resolveBackReferences(rawArgs ?? {}, methodResponses);
|
|
434
|
+
const results = await this.dispatchMethod(account, methodName, args, using, createdIds);
|
|
435
|
+
for (const entry of results) {
|
|
436
|
+
methodResponses.push([entry.name, entry.result, callId]);
|
|
437
|
+
if (entry.mutated) {
|
|
438
|
+
mutated = true;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
354
441
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
442
|
+
catch (error) {
|
|
443
|
+
if (error instanceof JmapServerMethodError) {
|
|
444
|
+
methodResponses.push([
|
|
445
|
+
'error',
|
|
446
|
+
{ type: error.type, description: error.message },
|
|
447
|
+
callId,
|
|
448
|
+
]);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
452
|
+
methodResponses.push(['error', { type: 'serverFail', description: message }, callId]);
|
|
453
|
+
}
|
|
358
454
|
}
|
|
359
455
|
}
|
|
456
|
+
if (mutated) {
|
|
457
|
+
await this.pushAfterMutation(account);
|
|
458
|
+
}
|
|
459
|
+
const responseBody = {
|
|
460
|
+
methodResponses,
|
|
461
|
+
sessionState: SESSION_STATE,
|
|
462
|
+
};
|
|
463
|
+
if (parsed.createdIds !== undefined) {
|
|
464
|
+
responseBody.createdIds = Object.fromEntries(createdIds);
|
|
465
|
+
}
|
|
466
|
+
return this.jsonResponse(200, responseBody);
|
|
360
467
|
}
|
|
361
|
-
|
|
362
|
-
|
|
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;
|
|
468
|
+
finally {
|
|
469
|
+
this.activeApiRequests--;
|
|
385
470
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Resolves `#argument` ResultReference objects (RFC 8620 §3.7) against the
|
|
474
|
+
* responses of earlier method calls in the same request.
|
|
475
|
+
*/
|
|
476
|
+
resolveBackReferences(args, priorResponses) {
|
|
477
|
+
const resolved = {};
|
|
478
|
+
for (const [key, value] of Object.entries(args)) {
|
|
479
|
+
if (!key.startsWith('#')) {
|
|
480
|
+
resolved[key] = value;
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
const name = key.slice(1);
|
|
484
|
+
if (name in args) {
|
|
485
|
+
throw new JmapServerMethodError('invalidArguments', `The arguments contain both "${name}" and "#${name}".`);
|
|
486
|
+
}
|
|
487
|
+
if (!value ||
|
|
488
|
+
typeof value !== 'object' ||
|
|
489
|
+
typeof value.resultOf !== 'string' ||
|
|
490
|
+
typeof value.name !== 'string' ||
|
|
491
|
+
typeof value.path !== 'string') {
|
|
492
|
+
throw new JmapServerMethodError('invalidResultReference', `"#${name}" is not a valid ResultReference object.`);
|
|
493
|
+
}
|
|
494
|
+
const source = priorResponses.find((entry) => entry[2] === value.resultOf && entry[0] === value.name);
|
|
495
|
+
if (!source) {
|
|
496
|
+
throw new JmapServerMethodError('invalidResultReference', `No response found for resultOf "${value.resultOf}" and name "${value.name}".`);
|
|
497
|
+
}
|
|
498
|
+
try {
|
|
499
|
+
resolved[name] = evalJsonPointer(source[1], value.path);
|
|
500
|
+
}
|
|
501
|
+
catch (error) {
|
|
502
|
+
throw new JmapServerMethodError('invalidResultReference', error instanceof Error ? error.message : String(error));
|
|
503
|
+
}
|
|
391
504
|
}
|
|
392
|
-
|
|
393
|
-
res.writeHead(200, { 'content-type': type, 'content-length': blob.data.length });
|
|
394
|
-
res.end(blob.data);
|
|
505
|
+
return resolved;
|
|
395
506
|
}
|
|
396
507
|
// ======================
|
|
397
|
-
//
|
|
508
|
+
// method dispatch
|
|
398
509
|
// ======================
|
|
399
|
-
dispatchMethod(
|
|
510
|
+
async dispatchMethod(account, methodName, args, using, createdIds) {
|
|
511
|
+
const requiredCapability = {
|
|
512
|
+
'Core/echo': JMAP_CORE_CAPABILITY,
|
|
513
|
+
'Mailbox/get': JMAP_MAIL_CAPABILITY,
|
|
514
|
+
'Mailbox/query': JMAP_MAIL_CAPABILITY,
|
|
515
|
+
'Mailbox/changes': JMAP_MAIL_CAPABILITY,
|
|
516
|
+
'Thread/get': JMAP_MAIL_CAPABILITY,
|
|
517
|
+
'Email/get': JMAP_MAIL_CAPABILITY,
|
|
518
|
+
'Email/query': JMAP_MAIL_CAPABILITY,
|
|
519
|
+
'Email/changes': JMAP_MAIL_CAPABILITY,
|
|
520
|
+
'Email/queryChanges': JMAP_MAIL_CAPABILITY,
|
|
521
|
+
'Email/set': JMAP_MAIL_CAPABILITY,
|
|
522
|
+
'Identity/get': JMAP_SUBMISSION_CAPABILITY,
|
|
523
|
+
'EmailSubmission/set': JMAP_SUBMISSION_CAPABILITY,
|
|
524
|
+
};
|
|
525
|
+
const capability = requiredCapability[methodName];
|
|
526
|
+
if (!capability) {
|
|
527
|
+
throw new JmapServerMethodError('unknownMethod', `Unknown method "${methodName}".`);
|
|
528
|
+
}
|
|
529
|
+
if (!using.has(capability)) {
|
|
530
|
+
throw new JmapServerMethodError('unknownMethod', `Method "${methodName}" requires the capability "${capability}" in "using".`);
|
|
531
|
+
}
|
|
532
|
+
if (methodName !== 'Core/echo') {
|
|
533
|
+
this.requireAccountId(account, args);
|
|
534
|
+
}
|
|
400
535
|
switch (methodName) {
|
|
401
536
|
case 'Core/echo':
|
|
402
|
-
return args;
|
|
537
|
+
return [{ name: methodName, result: args }];
|
|
403
538
|
case 'Mailbox/get':
|
|
404
|
-
return this.methodMailboxGet(
|
|
539
|
+
return [{ name: methodName, result: await this.methodMailboxGet(account, args) }];
|
|
405
540
|
case 'Mailbox/query':
|
|
406
|
-
return this.methodMailboxQuery(
|
|
541
|
+
return [{ name: methodName, result: await this.methodMailboxQuery(account, args) }];
|
|
542
|
+
case 'Mailbox/changes':
|
|
543
|
+
return [{ name: methodName, result: await this.methodMailboxChanges(account, args) }];
|
|
544
|
+
case 'Thread/get':
|
|
545
|
+
return [{ name: methodName, result: await this.methodThreadGet(account, args) }];
|
|
407
546
|
case 'Email/get':
|
|
408
|
-
return this.methodEmailGet(
|
|
547
|
+
return [{ name: methodName, result: await this.methodEmailGet(account, args) }];
|
|
409
548
|
case 'Email/query':
|
|
410
|
-
return this.methodEmailQuery(
|
|
549
|
+
return [{ name: methodName, result: await this.methodEmailQuery(account, args) }];
|
|
411
550
|
case 'Email/changes':
|
|
412
|
-
return this.methodEmailChanges(
|
|
413
|
-
case 'Email/
|
|
414
|
-
|
|
551
|
+
return [{ name: methodName, result: await this.methodEmailChanges(account, args) }];
|
|
552
|
+
case 'Email/queryChanges':
|
|
553
|
+
// Explicitly unsupported in phase 1: clients fall back to Email/query.
|
|
554
|
+
throw new JmapServerMethodError('cannotCalculateChanges', 'Email/queryChanges is not supported; re-run the query instead.');
|
|
555
|
+
case 'Email/set': {
|
|
556
|
+
const result = await this.methodEmailSet(account, args, createdIds);
|
|
557
|
+
return [{ name: methodName, result, mutated: result.newState !== result.oldState }];
|
|
558
|
+
}
|
|
415
559
|
case 'Identity/get':
|
|
416
|
-
return this.methodIdentityGet(
|
|
560
|
+
return [{ name: methodName, result: await this.methodIdentityGet(account, args) }];
|
|
417
561
|
case 'EmailSubmission/set':
|
|
418
|
-
return this.methodEmailSubmissionSet(
|
|
562
|
+
return this.methodEmailSubmissionSet(account, args, createdIds);
|
|
419
563
|
default:
|
|
420
564
|
throw new JmapServerMethodError('unknownMethod', `Unknown method "${methodName}".`);
|
|
421
565
|
}
|
|
422
566
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
if (args.
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
567
|
+
requireAccountId(account, args) {
|
|
568
|
+
if (typeof args.accountId !== 'string') {
|
|
569
|
+
throw new JmapServerMethodError('invalidArguments', 'accountId is required.');
|
|
570
|
+
}
|
|
571
|
+
if (args.accountId !== account.accountId) {
|
|
572
|
+
throw new JmapServerMethodError('accountNotFound', `Account "${args.accountId}" is not accessible with these credentials.`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
// ======================
|
|
576
|
+
// mailbox methods
|
|
577
|
+
// ======================
|
|
578
|
+
async methodMailboxGet(account, args) {
|
|
579
|
+
let ids = null;
|
|
580
|
+
if (args.ids !== null && args.ids !== undefined) {
|
|
581
|
+
if (!Array.isArray(args.ids)) {
|
|
582
|
+
throw new JmapServerMethodError('invalidArguments', 'ids must be an array of ids or null.');
|
|
583
|
+
}
|
|
584
|
+
if (args.ids.length > JMAP_SERVER_LIMITS.maxObjectsInGet) {
|
|
585
|
+
throw new JmapServerMethodError('requestTooLarge', `ids exceeds maxObjectsInGet (${JMAP_SERVER_LIMITS.maxObjectsInGet}).`);
|
|
440
586
|
}
|
|
587
|
+
ids = args.ids;
|
|
441
588
|
}
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
589
|
+
const properties = this.validateProperties(args.properties, KNOWN_MAILBOX_PROPERTIES);
|
|
590
|
+
const result = await this.backend.getMailboxes(account.accountId, ids);
|
|
591
|
+
const list = result.list.map((mailbox) => {
|
|
592
|
+
const full = {
|
|
445
593
|
...mailbox,
|
|
446
|
-
|
|
447
|
-
|
|
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,
|
|
594
|
+
isSubscribed: mailbox.isSubscribed ?? true,
|
|
595
|
+
myRights: mailbox.myRights ?? { ...DEFAULT_MAILBOX_RIGHTS },
|
|
462
596
|
};
|
|
597
|
+
return this.projectObject(full, properties ?? MAILBOX_PROPERTIES);
|
|
463
598
|
});
|
|
464
599
|
return {
|
|
465
|
-
accountId:
|
|
466
|
-
state:
|
|
467
|
-
list
|
|
468
|
-
notFound,
|
|
600
|
+
accountId: account.accountId,
|
|
601
|
+
state: result.state,
|
|
602
|
+
list,
|
|
603
|
+
notFound: result.notFound,
|
|
469
604
|
};
|
|
470
605
|
}
|
|
471
|
-
methodMailboxQuery(
|
|
472
|
-
const filter = args.filter ?? {};
|
|
473
|
-
|
|
606
|
+
async methodMailboxQuery(account, args) {
|
|
607
|
+
const filter = (args.filter ?? {});
|
|
608
|
+
if ('operator' in filter) {
|
|
609
|
+
throw new JmapServerMethodError('unsupportedFilter', 'FilterOperator is not supported for Mailbox/query.');
|
|
610
|
+
}
|
|
611
|
+
for (const key of Object.keys(filter)) {
|
|
612
|
+
if (!['role', 'name', 'parentId'].includes(key)) {
|
|
613
|
+
throw new JmapServerMethodError('unsupportedFilter', `Mailbox filter condition "${key}" is not supported.`);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
for (const comparator of (args.sort ?? [])) {
|
|
617
|
+
if (!['name', 'sortOrder'].includes(comparator.property)) {
|
|
618
|
+
throw new JmapServerMethodError('unsupportedSort', `Mailbox sort property "${comparator.property}" is not supported.`);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
const result = await this.backend.getMailboxes(account.accountId, null);
|
|
622
|
+
let mailboxes = result.list;
|
|
474
623
|
if (typeof filter.role === 'string') {
|
|
475
624
|
mailboxes = mailboxes.filter((mailbox) => mailbox.role === filter.role);
|
|
476
625
|
}
|
|
477
626
|
if (typeof filter.name === 'string') {
|
|
478
627
|
mailboxes = mailboxes.filter((mailbox) => mailbox.name === filter.name);
|
|
479
628
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
629
|
+
if ('parentId' in filter) {
|
|
630
|
+
mailboxes = mailboxes.filter((mailbox) => mailbox.parentId === filter.parentId);
|
|
631
|
+
}
|
|
632
|
+
const comparators = (args.sort ?? []);
|
|
633
|
+
if (comparators.length) {
|
|
634
|
+
mailboxes = [...mailboxes].sort((a, b) => {
|
|
635
|
+
for (const comparator of comparators) {
|
|
636
|
+
const direction = comparator.isAscending === false ? -1 : 1;
|
|
637
|
+
const property = comparator.property;
|
|
638
|
+
const left = a[property] ?? 0;
|
|
639
|
+
const right = b[property] ?? 0;
|
|
640
|
+
if (left < right) {
|
|
641
|
+
return -direction;
|
|
642
|
+
}
|
|
643
|
+
if (left > right) {
|
|
644
|
+
return direction;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return 0;
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
const position = this.validatePosition(args);
|
|
651
|
+
let ids = mailboxes.map((mailbox) => mailbox.id).slice(position);
|
|
652
|
+
if (typeof args.limit === 'number') {
|
|
653
|
+
ids = ids.slice(0, args.limit);
|
|
654
|
+
}
|
|
655
|
+
const response = {
|
|
656
|
+
accountId: account.accountId,
|
|
657
|
+
queryState: result.state,
|
|
484
658
|
canCalculateChanges: false,
|
|
485
|
-
position
|
|
659
|
+
position,
|
|
486
660
|
ids,
|
|
487
|
-
total: ids.length,
|
|
488
661
|
};
|
|
662
|
+
if (args.calculateTotal === true) {
|
|
663
|
+
response.total = mailboxes.length;
|
|
664
|
+
}
|
|
665
|
+
return response;
|
|
489
666
|
}
|
|
490
|
-
|
|
667
|
+
async methodMailboxChanges(account, args) {
|
|
668
|
+
const { sinceState, maxChanges } = this.validateChangesArgs(args);
|
|
669
|
+
const changes = await this.backend.getMailboxChanges(account.accountId, sinceState, maxChanges);
|
|
670
|
+
if (!changes) {
|
|
671
|
+
throw new JmapServerMethodError('cannotCalculateChanges', `Cannot calculate mailbox changes since state "${sinceState}".`);
|
|
672
|
+
}
|
|
673
|
+
return { accountId: account.accountId, ...changes };
|
|
674
|
+
}
|
|
675
|
+
// ======================
|
|
676
|
+
// thread methods
|
|
677
|
+
// ======================
|
|
678
|
+
async methodThreadGet(account, args) {
|
|
491
679
|
if (!Array.isArray(args.ids)) {
|
|
492
|
-
throw new JmapServerMethodError('invalidArguments', '
|
|
680
|
+
throw new JmapServerMethodError('invalidArguments', 'Thread/get requires an ids array.');
|
|
493
681
|
}
|
|
494
|
-
|
|
495
|
-
|
|
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
|
-
}
|
|
682
|
+
if (args.ids.length > JMAP_SERVER_LIMITS.maxObjectsInGet) {
|
|
683
|
+
throw new JmapServerMethodError('requestTooLarge', `ids exceeds maxObjectsInGet (${JMAP_SERVER_LIMITS.maxObjectsInGet}).`);
|
|
506
684
|
}
|
|
685
|
+
// Result-reference chains like Email/get -> /list/*/threadId commonly
|
|
686
|
+
// contain duplicates; deduplicate so each thread is returned once.
|
|
687
|
+
const ids = Array.from(new Set(args.ids));
|
|
688
|
+
const result = await this.backend.getThreads(account.accountId, ids);
|
|
507
689
|
return {
|
|
508
|
-
accountId:
|
|
509
|
-
state:
|
|
510
|
-
list,
|
|
511
|
-
notFound,
|
|
690
|
+
accountId: account.accountId,
|
|
691
|
+
state: result.state,
|
|
692
|
+
list: result.list,
|
|
693
|
+
notFound: result.notFound,
|
|
512
694
|
};
|
|
513
695
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
-
});
|
|
696
|
+
// ======================
|
|
697
|
+
// email methods
|
|
698
|
+
// ======================
|
|
699
|
+
async methodEmailGet(account, args) {
|
|
700
|
+
if (args.ids === null || args.ids === undefined) {
|
|
701
|
+
// RFC 8621 allows rejecting "fetch all" for the potentially huge Email type.
|
|
702
|
+
throw new JmapServerMethodError('requestTooLarge', 'Email/get requires an explicit ids array on this server.');
|
|
534
703
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
if (
|
|
539
|
-
|
|
704
|
+
if (!Array.isArray(args.ids)) {
|
|
705
|
+
throw new JmapServerMethodError('invalidArguments', 'Email/get requires an ids array.');
|
|
706
|
+
}
|
|
707
|
+
if (args.ids.length > JMAP_SERVER_LIMITS.maxObjectsInGet) {
|
|
708
|
+
throw new JmapServerMethodError('requestTooLarge', `ids exceeds maxObjectsInGet (${JMAP_SERVER_LIMITS.maxObjectsInGet}).`);
|
|
540
709
|
}
|
|
710
|
+
const properties = this.validateProperties(args.properties, KNOWN_EMAIL_PROPERTIES);
|
|
711
|
+
const result = await this.backend.getEmails(account.accountId, args.ids, properties);
|
|
712
|
+
const effectiveProperties = properties ?? DEFAULT_EMAIL_PROPERTIES;
|
|
713
|
+
const list = result.list.map((record) => {
|
|
714
|
+
const projected = this.projectObject(record, effectiveProperties);
|
|
715
|
+
if (effectiveProperties.includes('bodyValues')) {
|
|
716
|
+
projected.bodyValues = this.buildBodyValues(record, args);
|
|
717
|
+
}
|
|
718
|
+
return projected;
|
|
719
|
+
});
|
|
541
720
|
return {
|
|
542
|
-
accountId:
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
ids,
|
|
547
|
-
total,
|
|
721
|
+
accountId: account.accountId,
|
|
722
|
+
state: result.state,
|
|
723
|
+
list,
|
|
724
|
+
notFound: result.notFound,
|
|
548
725
|
};
|
|
549
726
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
727
|
+
/** Applies the Email/get body-value fetch flags and maxBodyValueBytes truncation. */
|
|
728
|
+
buildBodyValues(record, args) {
|
|
729
|
+
const wanted = new Set();
|
|
730
|
+
if (args.fetchAllBodyValues === true) {
|
|
731
|
+
for (const partId of Object.keys(record.bodyValues)) {
|
|
732
|
+
wanted.add(partId);
|
|
733
|
+
}
|
|
554
734
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
continue;
|
|
735
|
+
if (args.fetchTextBodyValues === true) {
|
|
736
|
+
for (const part of record.textBody) {
|
|
737
|
+
if (part.partId != null) {
|
|
738
|
+
wanted.add(part.partId);
|
|
739
|
+
}
|
|
561
740
|
}
|
|
562
|
-
|
|
563
|
-
|
|
741
|
+
}
|
|
742
|
+
if (args.fetchHTMLBodyValues === true) {
|
|
743
|
+
for (const part of record.htmlBody) {
|
|
744
|
+
if (part.partId != null) {
|
|
745
|
+
wanted.add(part.partId);
|
|
746
|
+
}
|
|
564
747
|
}
|
|
565
|
-
|
|
566
|
-
|
|
748
|
+
}
|
|
749
|
+
const maxBytes = typeof args.maxBodyValueBytes === 'number' && args.maxBodyValueBytes > 0
|
|
750
|
+
? args.maxBodyValueBytes
|
|
751
|
+
: null;
|
|
752
|
+
const result = {};
|
|
753
|
+
for (const partId of wanted) {
|
|
754
|
+
const bodyValue = record.bodyValues[partId];
|
|
755
|
+
if (!bodyValue) {
|
|
756
|
+
continue;
|
|
567
757
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
758
|
+
let value = bodyValue.value;
|
|
759
|
+
let isTruncated = bodyValue.isTruncated === true;
|
|
760
|
+
if (maxBytes !== null) {
|
|
761
|
+
const truncated = truncateUtf8(value, maxBytes);
|
|
762
|
+
if (truncated.length < value.length) {
|
|
763
|
+
value = truncated;
|
|
764
|
+
isTruncated = true;
|
|
575
765
|
}
|
|
576
|
-
updated.delete(id);
|
|
577
766
|
}
|
|
767
|
+
result[partId] = { value, isTruncated };
|
|
578
768
|
}
|
|
579
|
-
|
|
580
|
-
|
|
769
|
+
return result;
|
|
770
|
+
}
|
|
771
|
+
async methodEmailQuery(account, args) {
|
|
772
|
+
const filter = (args.filter ?? {});
|
|
773
|
+
if ('operator' in filter) {
|
|
774
|
+
throw new JmapServerMethodError('unsupportedFilter', 'FilterOperator is not supported; use a flat FilterCondition.');
|
|
581
775
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
776
|
+
for (const key of Object.keys(filter)) {
|
|
777
|
+
if (!SUPPORTED_EMAIL_FILTER_KEYS.has(key)) {
|
|
778
|
+
throw new JmapServerMethodError('unsupportedFilter', `Email filter condition "${key}" is not supported.`);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
const sort = (args.sort ?? []);
|
|
782
|
+
for (const comparator of sort) {
|
|
783
|
+
if (comparator.property !== 'receivedAt') {
|
|
784
|
+
throw new JmapServerMethodError('unsupportedSort', `Email sort property "${comparator.property}" is not supported.`);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (args.anchor !== undefined && args.anchor !== null) {
|
|
788
|
+
throw new JmapServerMethodError('invalidArguments', 'anchor is not supported.');
|
|
789
|
+
}
|
|
790
|
+
const position = this.validatePosition(args);
|
|
791
|
+
const result = await this.backend.queryEmails(account.accountId, {
|
|
792
|
+
filter: filter,
|
|
793
|
+
sort: sort,
|
|
794
|
+
position,
|
|
795
|
+
limit: typeof args.limit === 'number' ? args.limit : null,
|
|
796
|
+
calculateTotal: args.calculateTotal === true,
|
|
797
|
+
});
|
|
798
|
+
const response = {
|
|
799
|
+
accountId: account.accountId,
|
|
800
|
+
queryState: result.queryState,
|
|
801
|
+
canCalculateChanges: false,
|
|
802
|
+
position: result.position,
|
|
803
|
+
ids: result.ids,
|
|
590
804
|
};
|
|
805
|
+
if (args.calculateTotal === true) {
|
|
806
|
+
response.total = result.total ?? 0;
|
|
807
|
+
}
|
|
808
|
+
return response;
|
|
591
809
|
}
|
|
592
|
-
|
|
593
|
-
const
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
const
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
threadId: email.threadId,
|
|
613
|
-
size: email.size,
|
|
614
|
-
};
|
|
810
|
+
async methodEmailChanges(account, args) {
|
|
811
|
+
const { sinceState, maxChanges } = this.validateChangesArgs(args);
|
|
812
|
+
const changes = await this.backend.getEmailChanges(account.accountId, sinceState, maxChanges);
|
|
813
|
+
if (!changes) {
|
|
814
|
+
throw new JmapServerMethodError('cannotCalculateChanges', `Cannot calculate changes since state "${sinceState}".`);
|
|
815
|
+
}
|
|
816
|
+
return { accountId: account.accountId, ...changes };
|
|
817
|
+
}
|
|
818
|
+
async methodEmailSet(account, args, createdIds) {
|
|
819
|
+
const createEntries = Object.entries((args.create ?? {}));
|
|
820
|
+
const updateEntries = Object.entries((args.update ?? {}));
|
|
821
|
+
const destroyIds = (args.destroy ?? []);
|
|
822
|
+
if (createEntries.length + updateEntries.length + destroyIds.length >
|
|
823
|
+
JMAP_SERVER_LIMITS.maxObjectsInSet) {
|
|
824
|
+
throw new JmapServerMethodError('requestTooLarge', `The set request exceeds maxObjectsInSet (${JMAP_SERVER_LIMITS.maxObjectsInSet}).`);
|
|
825
|
+
}
|
|
826
|
+
if (typeof args.ifInState === 'string') {
|
|
827
|
+
const current = await this.backend.getEmails(account.accountId, []);
|
|
828
|
+
if (current.state !== args.ifInState) {
|
|
829
|
+
throw new JmapServerMethodError('stateMismatch', `ifInState "${args.ifInState}" does not match the current state "${current.state}".`);
|
|
615
830
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
831
|
+
}
|
|
832
|
+
const backendRequest = {};
|
|
833
|
+
const notUpdatedEarly = {};
|
|
834
|
+
if (createEntries.length) {
|
|
835
|
+
backendRequest.create = {};
|
|
836
|
+
for (const [creationId, spec] of createEntries) {
|
|
837
|
+
backendRequest.create[creationId] = spec;
|
|
619
838
|
}
|
|
620
839
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
840
|
+
if (updateEntries.length) {
|
|
841
|
+
backendRequest.update = {};
|
|
842
|
+
for (const [id, patch] of updateEntries) {
|
|
843
|
+
try {
|
|
844
|
+
backendRequest.update[id] = this.parseEmailUpdatePatch(patch);
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
notUpdatedEarly[id] =
|
|
848
|
+
error instanceof JmapServerMethodError
|
|
849
|
+
? { type: error.type, description: error.message }
|
|
850
|
+
: { type: 'invalidPatch', description: String(error) };
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
if (destroyIds.length) {
|
|
855
|
+
backendRequest.destroy = destroyIds;
|
|
856
|
+
}
|
|
857
|
+
const result = await this.backend.setEmails(account.accountId, backendRequest);
|
|
858
|
+
const created = {};
|
|
859
|
+
for (const [creationId, record] of Object.entries(result.created)) {
|
|
860
|
+
createdIds.set(creationId, record.id);
|
|
861
|
+
created[creationId] = {
|
|
862
|
+
id: record.id,
|
|
863
|
+
blobId: record.blobId,
|
|
864
|
+
threadId: record.threadId,
|
|
865
|
+
size: record.size,
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
const updated = {};
|
|
869
|
+
for (const id of result.updated) {
|
|
870
|
+
updated[id] = null;
|
|
871
|
+
}
|
|
872
|
+
return {
|
|
873
|
+
accountId: account.accountId,
|
|
874
|
+
oldState: result.oldState,
|
|
875
|
+
newState: result.newState,
|
|
876
|
+
created,
|
|
877
|
+
notCreated: result.notCreated,
|
|
878
|
+
updated,
|
|
879
|
+
notUpdated: { ...result.notUpdated, ...notUpdatedEarly },
|
|
880
|
+
destroyed: result.destroyed,
|
|
881
|
+
notDestroyed: result.notDestroyed,
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Normalizes an Email/set update patch (RFC 8620 §5.3): full `keywords`/
|
|
886
|
+
* `mailboxIds` replacements and single-key JSON-pointer patches
|
|
887
|
+
* (`keywords/$seen`, `mailboxIds/<id>`). Email properties other than these
|
|
888
|
+
* two are immutable (RFC 8621 §4.6).
|
|
889
|
+
*/
|
|
890
|
+
parseEmailUpdatePatch(patch) {
|
|
891
|
+
const update = {};
|
|
892
|
+
const unescape = (token) => token.replaceAll('~1', '/').replaceAll('~0', '~');
|
|
893
|
+
for (const [path, value] of Object.entries(patch)) {
|
|
894
|
+
if (path === 'keywords' || path === 'mailboxIds') {
|
|
895
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
896
|
+
throw new JmapServerMethodError('invalidProperties', `"${path}" must be an object.`);
|
|
897
|
+
}
|
|
898
|
+
const normalized = {};
|
|
899
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
900
|
+
if (entryValue !== true) {
|
|
901
|
+
throw new JmapServerMethodError('invalidProperties', `Values in "${path}" must be true; remove entries instead of setting them false.`);
|
|
902
|
+
}
|
|
903
|
+
normalized[key] = true;
|
|
904
|
+
}
|
|
905
|
+
update[path] = normalized;
|
|
625
906
|
continue;
|
|
626
907
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
updated[id] = null;
|
|
908
|
+
const slashIndex = path.indexOf('/');
|
|
909
|
+
if (slashIndex === -1) {
|
|
910
|
+
throw new JmapServerMethodError('invalidProperties', `Email property "${path}" is immutable or unknown.`);
|
|
631
911
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
912
|
+
const property = path.slice(0, slashIndex);
|
|
913
|
+
const rest = path.slice(slashIndex + 1);
|
|
914
|
+
if ((property !== 'keywords' && property !== 'mailboxIds') || rest.includes('/') || !rest) {
|
|
915
|
+
throw new JmapServerMethodError('invalidPatch', `Unsupported patch path "${path}".`);
|
|
635
916
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
if (
|
|
639
|
-
|
|
640
|
-
|
|
917
|
+
const key = unescape(rest);
|
|
918
|
+
const normalizedValue = value === true ? true : value === null || value === false ? null : undefined;
|
|
919
|
+
if (normalizedValue === undefined) {
|
|
920
|
+
throw new JmapServerMethodError('invalidPatch', `Patch value for "${path}" must be true or null.`);
|
|
921
|
+
}
|
|
922
|
+
if (property === 'keywords') {
|
|
923
|
+
update.keywordsPatch = update.keywordsPatch ?? {};
|
|
924
|
+
update.keywordsPatch[key] = normalizedValue;
|
|
641
925
|
}
|
|
642
926
|
else {
|
|
643
|
-
|
|
927
|
+
update.mailboxIdsPatch = update.mailboxIdsPatch ?? {};
|
|
928
|
+
update.mailboxIdsPatch[key] = normalizedValue;
|
|
644
929
|
}
|
|
645
930
|
}
|
|
646
|
-
if (
|
|
647
|
-
|
|
648
|
-
created: changedCreated,
|
|
649
|
-
updated: changedUpdated,
|
|
650
|
-
destroyed: changedDestroyed,
|
|
651
|
-
});
|
|
931
|
+
if (update.keywords && update.keywordsPatch) {
|
|
932
|
+
throw new JmapServerMethodError('invalidPatch', 'A patch must not set "keywords" and patch "keywords/..." at the same time.');
|
|
652
933
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
created,
|
|
658
|
-
notCreated,
|
|
659
|
-
updated,
|
|
660
|
-
notUpdated,
|
|
661
|
-
destroyed,
|
|
662
|
-
notDestroyed,
|
|
663
|
-
};
|
|
934
|
+
if (update.mailboxIds && update.mailboxIdsPatch) {
|
|
935
|
+
throw new JmapServerMethodError('invalidPatch', 'A patch must not set "mailboxIds" and patch "mailboxIds/..." at the same time.');
|
|
936
|
+
}
|
|
937
|
+
return update;
|
|
664
938
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
939
|
+
// ======================
|
|
940
|
+
// identity + submission methods
|
|
941
|
+
// ======================
|
|
942
|
+
async methodIdentityGet(account, args) {
|
|
943
|
+
const result = await this.backend.getIdentities(account.accountId);
|
|
944
|
+
let list = result.list;
|
|
945
|
+
const notFound = [];
|
|
946
|
+
if (Array.isArray(args.ids)) {
|
|
947
|
+
const wanted = new Set(args.ids);
|
|
948
|
+
list = list.filter((identity) => wanted.has(identity.id));
|
|
949
|
+
for (const id of wanted) {
|
|
950
|
+
if (!list.some((identity) => identity.id === id)) {
|
|
951
|
+
notFound.push(id);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return { accountId: account.accountId, state: result.state, list, notFound };
|
|
672
956
|
}
|
|
673
|
-
methodEmailSubmissionSet(
|
|
957
|
+
async methodEmailSubmissionSet(account, args, createdIds) {
|
|
674
958
|
const created = {};
|
|
675
959
|
const notCreated = {};
|
|
960
|
+
const notUpdated = {};
|
|
961
|
+
const notDestroyed = {};
|
|
962
|
+
/** creationId -> { submissionId, emailId } for onSuccess* resolution. */
|
|
963
|
+
const createdSubmissions = new Map();
|
|
964
|
+
const identitiesResult = await this.backend.getIdentities(account.accountId);
|
|
676
965
|
for (const [creationId, spec] of Object.entries((args.create ?? {}))) {
|
|
677
966
|
let emailId = spec.emailId;
|
|
678
967
|
if (typeof emailId === 'string' && emailId.startsWith('#')) {
|
|
@@ -686,14 +975,16 @@ export class JmapServer {
|
|
|
686
975
|
}
|
|
687
976
|
emailId = resolved;
|
|
688
977
|
}
|
|
689
|
-
|
|
978
|
+
const emailResult = await this.backend.getEmails(account.accountId, [emailId]);
|
|
979
|
+
const email = emailResult.list[0];
|
|
980
|
+
if (!email) {
|
|
690
981
|
notCreated[creationId] = {
|
|
691
982
|
type: 'invalidProperties',
|
|
692
983
|
description: `Email "${emailId}" does not exist.`,
|
|
693
984
|
};
|
|
694
985
|
continue;
|
|
695
986
|
}
|
|
696
|
-
const identity =
|
|
987
|
+
const identity = identitiesResult.list.find((candidate) => candidate.id === spec.identityId);
|
|
697
988
|
if (!identity) {
|
|
698
989
|
notCreated[creationId] = {
|
|
699
990
|
type: 'invalidProperties',
|
|
@@ -701,173 +992,488 @@ export class JmapServer {
|
|
|
701
992
|
};
|
|
702
993
|
continue;
|
|
703
994
|
}
|
|
704
|
-
const
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
995
|
+
const envelope = this.resolveEnvelope(spec.envelope, identity.email, email);
|
|
996
|
+
if (!envelope.rcptTo.length) {
|
|
997
|
+
notCreated[creationId] = {
|
|
998
|
+
type: 'noRecipients',
|
|
999
|
+
description: 'The email has no to/cc/bcc recipients and no envelope was given.',
|
|
1000
|
+
};
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
const blob = await this.backend.getBlob(account.accountId, email.blobId);
|
|
1004
|
+
if (!blob) {
|
|
1005
|
+
notCreated[creationId] = {
|
|
1006
|
+
type: 'invalidProperties',
|
|
1007
|
+
description: `Raw message blob "${email.blobId}" does not exist.`,
|
|
1008
|
+
};
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
try {
|
|
1012
|
+
const submission = await this.backend.submitEmail(account.accountId, {
|
|
1013
|
+
emailId,
|
|
1014
|
+
identityId: identity.id,
|
|
1015
|
+
envelope,
|
|
1016
|
+
message: blob.data,
|
|
1017
|
+
});
|
|
1018
|
+
createdSubmissions.set(creationId, { submissionId: submission.id, emailId });
|
|
1019
|
+
created[creationId] = {
|
|
1020
|
+
id: submission.id,
|
|
1021
|
+
undoStatus: submission.undoStatus,
|
|
1022
|
+
sendAt: submission.sendAt,
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
catch (error) {
|
|
1026
|
+
notCreated[creationId] = {
|
|
1027
|
+
type: 'forbiddenToSend',
|
|
1028
|
+
description: error instanceof Error ? error.message : String(error),
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
for (const id of Object.keys((args.update ?? {}))) {
|
|
1033
|
+
notUpdated[id] = {
|
|
1034
|
+
type: 'forbidden',
|
|
1035
|
+
description: 'EmailSubmission updates are not supported.',
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
for (const id of (args.destroy ?? [])) {
|
|
1039
|
+
notDestroyed[id] = {
|
|
1040
|
+
type: 'forbidden',
|
|
1041
|
+
description: 'EmailSubmission destroys are not supported.',
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
const responses = [
|
|
1045
|
+
{
|
|
1046
|
+
name: 'EmailSubmission/set',
|
|
1047
|
+
result: {
|
|
1048
|
+
accountId: account.accountId,
|
|
1049
|
+
oldState: null,
|
|
1050
|
+
newState: '0',
|
|
1051
|
+
created,
|
|
1052
|
+
notCreated,
|
|
1053
|
+
updated: {},
|
|
1054
|
+
notUpdated,
|
|
1055
|
+
destroyed: [],
|
|
1056
|
+
notDestroyed,
|
|
1057
|
+
},
|
|
1058
|
+
mutated: createdSubmissions.size > 0,
|
|
1059
|
+
},
|
|
1060
|
+
];
|
|
1061
|
+
// onSuccessUpdateEmail / onSuccessDestroyEmail (RFC 8621 §7.5): apply an
|
|
1062
|
+
// implicit Email/set for successfully created submissions and append its
|
|
1063
|
+
// response after the EmailSubmission/set response.
|
|
1064
|
+
const resolveSubmissionRef = (reference) => {
|
|
1065
|
+
if (reference.startsWith('#')) {
|
|
1066
|
+
return createdSubmissions.get(reference.slice(1)) ?? null;
|
|
1067
|
+
}
|
|
1068
|
+
for (const entry of createdSubmissions.values()) {
|
|
1069
|
+
if (entry.submissionId === reference) {
|
|
1070
|
+
return entry;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
return null;
|
|
1074
|
+
};
|
|
1075
|
+
const implicitSet = { accountId: account.accountId };
|
|
1076
|
+
let hasImplicitSet = false;
|
|
1077
|
+
if (args.onSuccessUpdateEmail && typeof args.onSuccessUpdateEmail === 'object') {
|
|
1078
|
+
const update = {};
|
|
1079
|
+
for (const [reference, patch] of Object.entries(args.onSuccessUpdateEmail)) {
|
|
1080
|
+
const entry = resolveSubmissionRef(reference);
|
|
1081
|
+
if (entry) {
|
|
1082
|
+
update[entry.emailId] = patch;
|
|
1083
|
+
hasImplicitSet = true;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
implicitSet.update = update;
|
|
1087
|
+
}
|
|
1088
|
+
if (Array.isArray(args.onSuccessDestroyEmail)) {
|
|
1089
|
+
const destroy = [];
|
|
1090
|
+
for (const reference of args.onSuccessDestroyEmail) {
|
|
1091
|
+
const entry = resolveSubmissionRef(reference);
|
|
1092
|
+
if (entry) {
|
|
1093
|
+
destroy.push(entry.emailId);
|
|
1094
|
+
hasImplicitSet = true;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
implicitSet.destroy = destroy;
|
|
1098
|
+
}
|
|
1099
|
+
if (hasImplicitSet) {
|
|
1100
|
+
const result = await this.methodEmailSet(account, implicitSet, createdIds);
|
|
1101
|
+
responses.push({
|
|
1102
|
+
name: 'Email/set',
|
|
1103
|
+
result,
|
|
1104
|
+
mutated: result.newState !== result.oldState,
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
return responses;
|
|
1108
|
+
}
|
|
1109
|
+
/** Uses the client-provided envelope or derives it from the email's addresses. */
|
|
1110
|
+
resolveEnvelope(specEnvelope, identityEmail, email) {
|
|
1111
|
+
if (specEnvelope &&
|
|
1112
|
+
typeof specEnvelope === 'object' &&
|
|
1113
|
+
specEnvelope.mailFrom?.email &&
|
|
1114
|
+
Array.isArray(specEnvelope.rcptTo)) {
|
|
1115
|
+
return {
|
|
1116
|
+
mailFrom: { email: String(specEnvelope.mailFrom.email) },
|
|
1117
|
+
rcptTo: specEnvelope.rcptTo
|
|
1118
|
+
.filter((recipient) => typeof recipient?.email === 'string')
|
|
1119
|
+
.map((recipient) => ({ email: recipient.email })),
|
|
711
1120
|
};
|
|
712
|
-
|
|
713
|
-
|
|
1121
|
+
}
|
|
1122
|
+
const recipients = new Set();
|
|
1123
|
+
for (const list of [email.to, email.cc, email.bcc]) {
|
|
1124
|
+
for (const address of list ?? []) {
|
|
1125
|
+
recipients.add(address.email);
|
|
1126
|
+
}
|
|
714
1127
|
}
|
|
715
1128
|
return {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
newState: String(user.state),
|
|
719
|
-
created,
|
|
720
|
-
notCreated,
|
|
721
|
-
updated: {},
|
|
722
|
-
notUpdated: {},
|
|
723
|
-
destroyed: [],
|
|
724
|
-
notDestroyed: {},
|
|
1129
|
+
mailFrom: { email: email.from?.[0]?.email ?? identityEmail },
|
|
1130
|
+
rcptTo: Array.from(recipients).map((address) => ({ email: address })),
|
|
725
1131
|
};
|
|
726
1132
|
}
|
|
727
1133
|
// ======================
|
|
728
|
-
//
|
|
1134
|
+
// upload + download
|
|
729
1135
|
// ======================
|
|
730
|
-
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
|
|
1136
|
+
async handleUpload(account, pathname, request) {
|
|
1137
|
+
const segments = pathname.split('/').filter((segment) => segment.length > 0);
|
|
1138
|
+
const accountId = decodeURIComponent(segments[2] ?? '');
|
|
1139
|
+
if (accountId !== account.accountId) {
|
|
1140
|
+
return this.problemResponse(404, 'about:blank', 'Unknown account');
|
|
734
1141
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
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 };
|
|
1142
|
+
const data = new Uint8Array(await request.arrayBuffer());
|
|
1143
|
+
if (data.length > JMAP_SERVER_LIMITS.maxSizeUpload) {
|
|
1144
|
+
return this.limitResponse(400, 'maxSizeUpload', `The upload is larger than ${JMAP_SERVER_LIMITS.maxSizeUpload} bytes.`);
|
|
781
1145
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
1146
|
+
const type = request.headers.get('content-type') ?? 'application/octet-stream';
|
|
1147
|
+
const { blobId, size } = await this.backend.uploadBlob(account.accountId, data, type);
|
|
1148
|
+
return this.jsonResponse(200, { accountId: account.accountId, blobId, type, size });
|
|
1149
|
+
}
|
|
1150
|
+
async handleDownload(account, pathname, url) {
|
|
1151
|
+
// /jmap/download/{accountId}/{blobId}/{name}
|
|
1152
|
+
const segments = pathname.split('/').filter((segment) => segment.length > 0);
|
|
1153
|
+
const accountId = decodeURIComponent(segments[2] ?? '');
|
|
1154
|
+
const blobId = decodeURIComponent(segments[3] ?? '');
|
|
1155
|
+
const name = decodeURIComponent(segments[4] ?? 'blob');
|
|
1156
|
+
if (accountId !== account.accountId) {
|
|
1157
|
+
return this.problemResponse(404, 'about:blank', 'Unknown account');
|
|
1158
|
+
}
|
|
1159
|
+
const blob = await this.backend.getBlob(account.accountId, blobId);
|
|
1160
|
+
if (!blob) {
|
|
1161
|
+
return this.problemResponse(404, 'about:blank', 'Unknown blob');
|
|
1162
|
+
}
|
|
1163
|
+
const type = url.searchParams.get('type') ?? blob.type;
|
|
1164
|
+
return new Response(asBodyBytes(blob.data), {
|
|
1165
|
+
status: 200,
|
|
1166
|
+
headers: {
|
|
1167
|
+
'content-type': type,
|
|
1168
|
+
'content-length': String(blob.data.length),
|
|
1169
|
+
'content-disposition': `attachment; filename="${name.replaceAll('"', '')}"`,
|
|
1170
|
+
},
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
// ======================
|
|
1174
|
+
// event source (SSE)
|
|
1175
|
+
// ======================
|
|
1176
|
+
handleEventSource(account, url) {
|
|
1177
|
+
const typesParam = url.searchParams.get('types') ?? '*';
|
|
1178
|
+
const types = typesParam === '*' || typesParam === ''
|
|
1179
|
+
? null
|
|
1180
|
+
: new Set(typesParam
|
|
1181
|
+
.split(',')
|
|
1182
|
+
.map((entry) => entry.trim())
|
|
1183
|
+
.filter((entry) => entry.length > 0));
|
|
1184
|
+
const closeAfterState = url.searchParams.get('closeafter') === 'state';
|
|
1185
|
+
const pingRaw = Number(url.searchParams.get('ping') ?? '0');
|
|
1186
|
+
const pingSeconds = Number.isFinite(pingRaw) && pingRaw > 0 ? Math.max(1, Math.floor(pingRaw)) : 0;
|
|
1187
|
+
const state = {
|
|
1188
|
+
accountId: account.accountId,
|
|
1189
|
+
types,
|
|
1190
|
+
closeAfterState,
|
|
1191
|
+
controller: null,
|
|
1192
|
+
pingTimer: null,
|
|
1193
|
+
lastSent: new Map(),
|
|
1194
|
+
closed: false,
|
|
803
1195
|
};
|
|
1196
|
+
const stream = new ReadableStream({
|
|
1197
|
+
start: (controller) => {
|
|
1198
|
+
state.controller = controller;
|
|
1199
|
+
controller.enqueue(textEncoder.encode(': jmap event stream\n\n'));
|
|
1200
|
+
if (pingSeconds > 0) {
|
|
1201
|
+
state.pingTimer = setInterval(() => {
|
|
1202
|
+
this.writeToStream(state, `event: ping\ndata: {"interval":${pingSeconds}}\n\n`);
|
|
1203
|
+
}, pingSeconds * 1000);
|
|
1204
|
+
}
|
|
1205
|
+
try {
|
|
1206
|
+
this.registerStream(state);
|
|
1207
|
+
}
|
|
1208
|
+
catch (error) {
|
|
1209
|
+
// a throwing backend.subscribeToChanges must not strand the ping timer
|
|
1210
|
+
this.unregisterStream(state);
|
|
1211
|
+
throw error;
|
|
1212
|
+
}
|
|
1213
|
+
},
|
|
1214
|
+
cancel: () => {
|
|
1215
|
+
this.unregisterStream(state);
|
|
1216
|
+
},
|
|
1217
|
+
});
|
|
1218
|
+
return new Response(stream, {
|
|
1219
|
+
status: 200,
|
|
1220
|
+
headers: {
|
|
1221
|
+
'content-type': 'text/event-stream',
|
|
1222
|
+
'cache-control': 'no-cache',
|
|
1223
|
+
},
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
registerStream(state) {
|
|
1227
|
+
if (!this.changeFeedUnsubscribe) {
|
|
1228
|
+
this.changeFeedUnsubscribe = this.backend.subscribeToChanges((change) => {
|
|
1229
|
+
this.pushStateChange(change.accountId, change.changed);
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
this.eventStreams.add(state);
|
|
1233
|
+
}
|
|
1234
|
+
unregisterStream(state) {
|
|
1235
|
+
state.closed = true;
|
|
1236
|
+
if (state.pingTimer) {
|
|
1237
|
+
clearInterval(state.pingTimer);
|
|
1238
|
+
state.pingTimer = null;
|
|
1239
|
+
}
|
|
1240
|
+
this.eventStreams.delete(state);
|
|
1241
|
+
if (!this.eventStreams.size && this.changeFeedUnsubscribe) {
|
|
1242
|
+
this.changeFeedUnsubscribe();
|
|
1243
|
+
this.changeFeedUnsubscribe = null;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
closeStream(state) {
|
|
1247
|
+
this.unregisterStream(state);
|
|
1248
|
+
try {
|
|
1249
|
+
state.controller?.close();
|
|
1250
|
+
}
|
|
1251
|
+
catch {
|
|
1252
|
+
// already closed or errored
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
writeToStream(state, payload) {
|
|
1256
|
+
if (state.closed || !state.controller) {
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
try {
|
|
1260
|
+
state.controller.enqueue(textEncoder.encode(payload));
|
|
1261
|
+
}
|
|
1262
|
+
catch {
|
|
1263
|
+
this.closeStream(state);
|
|
1264
|
+
}
|
|
804
1265
|
}
|
|
805
1266
|
/**
|
|
806
|
-
*
|
|
807
|
-
*
|
|
1267
|
+
* Pushes a StateChange to matching event streams. Per-type states are
|
|
1268
|
+
* deduplicated per stream, so a mutation notified both by the backend
|
|
1269
|
+
* change feed and by the post-request push is delivered once.
|
|
808
1270
|
*/
|
|
809
|
-
|
|
810
|
-
for (const
|
|
811
|
-
|
|
812
|
-
if (segments.length === 1) {
|
|
813
|
-
if (value === null) {
|
|
814
|
-
delete email[path];
|
|
815
|
-
}
|
|
816
|
-
else {
|
|
817
|
-
email[path] = value;
|
|
818
|
-
}
|
|
1271
|
+
pushStateChange(accountId, changed) {
|
|
1272
|
+
for (const state of Array.from(this.eventStreams)) {
|
|
1273
|
+
if (state.accountId !== accountId) {
|
|
819
1274
|
continue;
|
|
820
1275
|
}
|
|
821
|
-
|
|
822
|
-
for (const
|
|
823
|
-
if (
|
|
824
|
-
|
|
1276
|
+
const filtered = {};
|
|
1277
|
+
for (const [type, typeState] of Object.entries(changed)) {
|
|
1278
|
+
if (state.types && !state.types.has(type)) {
|
|
1279
|
+
continue;
|
|
1280
|
+
}
|
|
1281
|
+
if (state.lastSent.get(type) === typeState) {
|
|
1282
|
+
continue;
|
|
825
1283
|
}
|
|
826
|
-
|
|
1284
|
+
filtered[type] = typeState;
|
|
827
1285
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
delete target[leaf];
|
|
1286
|
+
if (!Object.keys(filtered).length) {
|
|
1287
|
+
continue;
|
|
831
1288
|
}
|
|
832
|
-
|
|
833
|
-
|
|
1289
|
+
for (const [type, typeState] of Object.entries(filtered)) {
|
|
1290
|
+
state.lastSent.set(type, typeState);
|
|
1291
|
+
}
|
|
1292
|
+
const stateChange = {
|
|
1293
|
+
'@type': 'StateChange',
|
|
1294
|
+
changed: { [accountId]: filtered },
|
|
1295
|
+
};
|
|
1296
|
+
this.writeToStream(state, `event: state\ndata: ${JSON.stringify(stateChange)}\n\n`);
|
|
1297
|
+
if (state.closeAfterState) {
|
|
1298
|
+
this.closeStream(state);
|
|
834
1299
|
}
|
|
835
1300
|
}
|
|
836
1301
|
}
|
|
837
|
-
/**
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1302
|
+
/**
|
|
1303
|
+
* Emits a StateChange after a mutating JMAP request, covering backends
|
|
1304
|
+
* whose change feed only reports out-of-band mutations. Deduplicated
|
|
1305
|
+
* against feed-driven pushes via the per-stream state tracking.
|
|
1306
|
+
*/
|
|
1307
|
+
async pushAfterMutation(account) {
|
|
1308
|
+
if (!this.eventStreams.size) {
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
const [emails, mailboxes, threads] = await Promise.all([
|
|
1312
|
+
this.backend.getEmails(account.accountId, []),
|
|
1313
|
+
this.backend.getMailboxes(account.accountId, []),
|
|
1314
|
+
this.backend.getThreads(account.accountId, []),
|
|
1315
|
+
]);
|
|
1316
|
+
this.pushStateChange(account.accountId, {
|
|
1317
|
+
Email: emails.state,
|
|
1318
|
+
Thread: threads.state,
|
|
1319
|
+
Mailbox: mailboxes.state,
|
|
845
1320
|
});
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
1321
|
+
}
|
|
1322
|
+
// ======================
|
|
1323
|
+
// node req/res adapter
|
|
1324
|
+
// ======================
|
|
1325
|
+
async handleNodeRequest(req, res) {
|
|
1326
|
+
try {
|
|
1327
|
+
const method = (req.method ?? 'GET').toUpperCase();
|
|
1328
|
+
let body;
|
|
1329
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
1330
|
+
const chunks = [];
|
|
1331
|
+
let total = 0;
|
|
1332
|
+
// Cap request buffering at maxSizeUpload; larger requests never make
|
|
1333
|
+
// it to fetchHandler (which enforces the JMAP per-endpoint limits).
|
|
1334
|
+
const maxBuffered = JMAP_SERVER_LIMITS.maxSizeUpload + 1;
|
|
1335
|
+
for await (const chunk of req) {
|
|
1336
|
+
const buffer = chunk;
|
|
1337
|
+
total += buffer.length;
|
|
1338
|
+
if (total > maxBuffered) {
|
|
1339
|
+
res.writeHead(413, { 'content-type': 'application/problem+json' });
|
|
1340
|
+
res.end(JSON.stringify({
|
|
1341
|
+
type: 'urn:ietf:params:jmap:error:limit',
|
|
1342
|
+
limit: 'maxSizeUpload',
|
|
1343
|
+
status: 413,
|
|
1344
|
+
detail: 'Request body too large.',
|
|
1345
|
+
}));
|
|
1346
|
+
req.destroy();
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
chunks.push(buffer);
|
|
1350
|
+
}
|
|
1351
|
+
body = Buffer.concat(chunks);
|
|
863
1352
|
}
|
|
1353
|
+
const headers = new Headers();
|
|
1354
|
+
const skippedHeaders = new Set([
|
|
1355
|
+
'connection',
|
|
1356
|
+
'content-length',
|
|
1357
|
+
'expect',
|
|
1358
|
+
'keep-alive',
|
|
1359
|
+
'proxy-connection',
|
|
1360
|
+
'transfer-encoding',
|
|
1361
|
+
'upgrade',
|
|
1362
|
+
]);
|
|
1363
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
1364
|
+
if (value === undefined || skippedHeaders.has(key.toLowerCase())) {
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
headers.set(key, Array.isArray(value) ? value.join(', ') : value);
|
|
1368
|
+
}
|
|
1369
|
+
const host = req.headers.host ?? '127.0.0.1';
|
|
1370
|
+
const request = new Request(`http://${host}${req.url ?? '/'}`, {
|
|
1371
|
+
method,
|
|
1372
|
+
headers,
|
|
1373
|
+
body: body ? asBodyBytes(body) : undefined,
|
|
1374
|
+
});
|
|
1375
|
+
const response = await this.fetchHandler(request);
|
|
1376
|
+
const responseHeaders = {};
|
|
1377
|
+
response.headers.forEach((value, key) => {
|
|
1378
|
+
responseHeaders[key] = value;
|
|
1379
|
+
});
|
|
1380
|
+
res.writeHead(response.status, responseHeaders);
|
|
1381
|
+
if (!response.body) {
|
|
1382
|
+
res.end();
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
const reader = response.body.getReader();
|
|
1386
|
+
let clientClosed = false;
|
|
1387
|
+
res.on('close', () => {
|
|
1388
|
+
clientClosed = true;
|
|
1389
|
+
// Cancelling the reader triggers the stream's cancel handler, which
|
|
1390
|
+
// releases any per-stream resources (SSE registration, ping timer).
|
|
1391
|
+
void reader.cancel().catch(() => { });
|
|
1392
|
+
});
|
|
864
1393
|
try {
|
|
865
|
-
|
|
1394
|
+
while (true) {
|
|
1395
|
+
const { done, value } = await reader.read();
|
|
1396
|
+
if (done || clientClosed || res.destroyed) {
|
|
1397
|
+
break;
|
|
1398
|
+
}
|
|
1399
|
+
res.write(value);
|
|
1400
|
+
}
|
|
866
1401
|
}
|
|
867
1402
|
catch {
|
|
868
|
-
|
|
1403
|
+
// stream cancelled or connection gone
|
|
1404
|
+
}
|
|
1405
|
+
if (!res.destroyed) {
|
|
1406
|
+
res.end();
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
catch (error) {
|
|
1410
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1411
|
+
if (!res.headersSent) {
|
|
1412
|
+
res.writeHead(500, { 'content-type': 'application/problem+json' });
|
|
869
1413
|
}
|
|
1414
|
+
res.end(JSON.stringify({ type: 'about:blank', status: 500, detail: message }));
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
// ======================
|
|
1418
|
+
// shared validators + responses
|
|
1419
|
+
// ======================
|
|
1420
|
+
validateProperties(requested, known) {
|
|
1421
|
+
if (requested === null || requested === undefined) {
|
|
1422
|
+
return null;
|
|
1423
|
+
}
|
|
1424
|
+
if (!Array.isArray(requested)) {
|
|
1425
|
+
throw new JmapServerMethodError('invalidArguments', 'properties must be an array or null.');
|
|
1426
|
+
}
|
|
1427
|
+
for (const property of requested) {
|
|
1428
|
+
if (typeof property !== 'string' || !known.has(property)) {
|
|
1429
|
+
throw new JmapServerMethodError('invalidArguments', `Unknown property "${String(property)}".`);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
return requested.includes('id') ? requested : ['id', ...requested];
|
|
1433
|
+
}
|
|
1434
|
+
projectObject(source, properties) {
|
|
1435
|
+
const projected = {};
|
|
1436
|
+
for (const property of properties) {
|
|
1437
|
+
projected[property] = source[property] === undefined ? null : source[property];
|
|
870
1438
|
}
|
|
1439
|
+
return projected;
|
|
1440
|
+
}
|
|
1441
|
+
validatePosition(args) {
|
|
1442
|
+
if (args.position === undefined || args.position === null) {
|
|
1443
|
+
return 0;
|
|
1444
|
+
}
|
|
1445
|
+
if (!Number.isInteger(args.position) || args.position < 0) {
|
|
1446
|
+
throw new JmapServerMethodError('invalidArguments', 'position must be a non-negative integer.');
|
|
1447
|
+
}
|
|
1448
|
+
return args.position;
|
|
1449
|
+
}
|
|
1450
|
+
validateChangesArgs(args) {
|
|
1451
|
+
if (typeof args.sinceState !== 'string') {
|
|
1452
|
+
throw new JmapServerMethodError('invalidArguments', 'sinceState is required.');
|
|
1453
|
+
}
|
|
1454
|
+
let maxChanges;
|
|
1455
|
+
if (args.maxChanges !== undefined && args.maxChanges !== null) {
|
|
1456
|
+
if (!Number.isInteger(args.maxChanges) || args.maxChanges <= 0) {
|
|
1457
|
+
throw new JmapServerMethodError('invalidArguments', 'maxChanges must be a positive integer.');
|
|
1458
|
+
}
|
|
1459
|
+
maxChanges = args.maxChanges;
|
|
1460
|
+
}
|
|
1461
|
+
return { sinceState: args.sinceState, maxChanges };
|
|
1462
|
+
}
|
|
1463
|
+
jsonResponse(status, body) {
|
|
1464
|
+
return new Response(JSON.stringify(body), {
|
|
1465
|
+
status,
|
|
1466
|
+
headers: { 'content-type': 'application/json' },
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
problemResponse(status, type, detail, extraHeaders = {}) {
|
|
1470
|
+
return new Response(JSON.stringify({ type, status, detail }), {
|
|
1471
|
+
status,
|
|
1472
|
+
headers: { 'content-type': 'application/problem+json', ...extraHeaders },
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
limitResponse(status, limit, detail) {
|
|
1476
|
+
return new Response(JSON.stringify({ type: 'urn:ietf:params:jmap:error:limit', limit, status, detail }), { status, headers: { 'content-type': 'application/problem+json' } });
|
|
871
1477
|
}
|
|
872
1478
|
}
|
|
873
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qbWFwc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5qbWFwc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFtRWxELDBGQUEwRjtBQUMxRixNQUFNLHFCQUFzQixTQUFRLEtBQUs7SUFDdkMsWUFBbUIsSUFBWSxFQUFFLFdBQW9CO1FBQ25ELEtBQUssQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLENBQUM7UUFEVixTQUFJLEdBQUosSUFBSSxDQUFRO0lBRS9CLENBQUM7Q0FDRjtBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFNckI7UUFMTyxVQUFLLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUM7UUFFL0MsWUFBTyxHQUE0QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzdDLGlCQUFZLEdBQXNELElBQUksR0FBRyxFQUFFLENBQUM7UUFHbEYsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUNuRCxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pCLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtnQkFDdEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDOUIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCx5QkFBeUI7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
|
|
1479
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qbWFwc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5qbWFwc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFDbEQsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixvQkFBb0IsRUFDcEIsMEJBQTBCLEdBRzNCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQVdOLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFvQm5FLDREQUE0RDtBQUM1RCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRztJQUNoQyxhQUFhLEVBQUUsVUFBVTtJQUN6QixtQkFBbUIsRUFBRSxDQUFDO0lBQ3RCLGNBQWMsRUFBRSxVQUFVO0lBQzFCLHFCQUFxQixFQUFFLENBQUM7SUFDeEIsaUJBQWlCLEVBQUUsRUFBRTtJQUNyQixlQUFlLEVBQUUsR0FBRztJQUNwQixlQUFlLEVBQUUsR0FBRztDQUNyQixDQUFDO0FBRUYsNkVBQTZFO0FBQzdFLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQztBQUUxQixzREFBc0Q7QUFDdEQsTUFBTSx3QkFBd0IsR0FBRztJQUMvQixJQUFJO0lBQ0osUUFBUTtJQUNSLFVBQVU7SUFDVixZQUFZO0lBQ1osVUFBVTtJQUNWLE1BQU07SUFDTixZQUFZO0lBQ1osV0FBVztJQUNYLFdBQVc7SUFDWCxZQUFZO0lBQ1osUUFBUTtJQUNSLE1BQU07SUFDTixJQUFJO0lBQ0osSUFBSTtJQUNKLEtBQUs7SUFDTCxTQUFTO0lBQ1QsU0FBUztJQUNULFFBQVE7SUFDUixlQUFlO0lBQ2YsU0FBUztJQUNULFlBQVk7SUFDWixVQUFVO0lBQ1YsVUFBVTtJQUNWLGFBQWE7Q0FDZCxDQUFDO0FBQ0YsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyx3QkFBd0IsQ0FB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
|