@rndmjoker/proton-mcp 0.4.4

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.
Files changed (141) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +405 -0
  3. package/dist/activity.d.ts +49 -0
  4. package/dist/activity.js +72 -0
  5. package/dist/activity.js.map +1 -0
  6. package/dist/bridge/certificate.d.ts +75 -0
  7. package/dist/bridge/certificate.js +176 -0
  8. package/dist/bridge/certificate.js.map +1 -0
  9. package/dist/bridge/connection.d.ts +99 -0
  10. package/dist/bridge/connection.js +244 -0
  11. package/dist/bridge/connection.js.map +1 -0
  12. package/dist/bridge/errors.d.ts +35 -0
  13. package/dist/bridge/errors.js +56 -0
  14. package/dist/bridge/errors.js.map +1 -0
  15. package/dist/config.d.ts +92 -0
  16. package/dist/config.js +142 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/credentials/availability.d.ts +62 -0
  19. package/dist/credentials/availability.js +107 -0
  20. package/dist/credentials/availability.js.map +1 -0
  21. package/dist/credentials/encrypted-file.d.ts +50 -0
  22. package/dist/credentials/encrypted-file.js +156 -0
  23. package/dist/credentials/encrypted-file.js.map +1 -0
  24. package/dist/credentials/keyring.d.ts +48 -0
  25. package/dist/credentials/keyring.js +97 -0
  26. package/dist/credentials/keyring.js.map +1 -0
  27. package/dist/credentials/plain-file.d.ts +24 -0
  28. package/dist/credentials/plain-file.js +78 -0
  29. package/dist/credentials/plain-file.js.map +1 -0
  30. package/dist/credentials/probe-keyring.d.ts +11 -0
  31. package/dist/credentials/probe-keyring.js +57 -0
  32. package/dist/credentials/probe-keyring.js.map +1 -0
  33. package/dist/credentials/session.d.ts +15 -0
  34. package/dist/credentials/session.js +21 -0
  35. package/dist/credentials/session.js.map +1 -0
  36. package/dist/credentials/store.d.ts +80 -0
  37. package/dist/credentials/store.js +94 -0
  38. package/dist/credentials/store.js.map +1 -0
  39. package/dist/in-flight.d.ts +33 -0
  40. package/dist/in-flight.js +78 -0
  41. package/dist/in-flight.js.map +1 -0
  42. package/dist/mail/actions.d.ts +116 -0
  43. package/dist/mail/actions.js +265 -0
  44. package/dist/mail/actions.js.map +1 -0
  45. package/dist/mail/attachments.d.ts +39 -0
  46. package/dist/mail/attachments.js +86 -0
  47. package/dist/mail/attachments.js.map +1 -0
  48. package/dist/mail/compose.d.ts +264 -0
  49. package/dist/mail/compose.js +395 -0
  50. package/dist/mail/compose.js.map +1 -0
  51. package/dist/mail/drafts.d.ts +138 -0
  52. package/dist/mail/drafts.js +449 -0
  53. package/dist/mail/drafts.js.map +1 -0
  54. package/dist/mail/ids.d.ts +78 -0
  55. package/dist/mail/ids.js +135 -0
  56. package/dist/mail/ids.js.map +1 -0
  57. package/dist/mail/labels.d.ts +61 -0
  58. package/dist/mail/labels.js +139 -0
  59. package/dist/mail/labels.js.map +1 -0
  60. package/dist/mail/markup.d.ts +91 -0
  61. package/dist/mail/markup.js +265 -0
  62. package/dist/mail/markup.js.map +1 -0
  63. package/dist/mail/messages.d.ts +147 -0
  64. package/dist/mail/messages.js +219 -0
  65. package/dist/mail/messages.js.map +1 -0
  66. package/dist/mail/quote.d.ts +65 -0
  67. package/dist/mail/quote.js +157 -0
  68. package/dist/mail/quote.js.map +1 -0
  69. package/dist/mail/search.d.ts +66 -0
  70. package/dist/mail/search.js +107 -0
  71. package/dist/mail/search.js.map +1 -0
  72. package/dist/mail/send.d.ts +61 -0
  73. package/dist/mail/send.js +132 -0
  74. package/dist/mail/send.js.map +1 -0
  75. package/dist/mime/parse.d.ts +110 -0
  76. package/dist/mime/parse.js +194 -0
  77. package/dist/mime/parse.js.map +1 -0
  78. package/dist/server.d.ts +13 -0
  79. package/dist/server.js +387 -0
  80. package/dist/server.js.map +1 -0
  81. package/dist/session.d.ts +86 -0
  82. package/dist/session.js +220 -0
  83. package/dist/session.js.map +1 -0
  84. package/dist/settings.d.ts +52 -0
  85. package/dist/settings.js +80 -0
  86. package/dist/settings.js.map +1 -0
  87. package/dist/tools/actions.d.ts +21 -0
  88. package/dist/tools/actions.js +133 -0
  89. package/dist/tools/actions.js.map +1 -0
  90. package/dist/tools/capabilities.d.ts +52 -0
  91. package/dist/tools/capabilities.js +96 -0
  92. package/dist/tools/capabilities.js.map +1 -0
  93. package/dist/tools/confirm.d.ts +84 -0
  94. package/dist/tools/confirm.js +212 -0
  95. package/dist/tools/confirm.js.map +1 -0
  96. package/dist/tools/drafts.d.ts +21 -0
  97. package/dist/tools/drafts.js +199 -0
  98. package/dist/tools/drafts.js.map +1 -0
  99. package/dist/tools/failures.d.ts +46 -0
  100. package/dist/tools/failures.js +157 -0
  101. package/dist/tools/failures.js.map +1 -0
  102. package/dist/tools/format.d.ts +55 -0
  103. package/dist/tools/format.js +220 -0
  104. package/dist/tools/format.js.map +1 -0
  105. package/dist/tools/guidance.d.ts +38 -0
  106. package/dist/tools/guidance.js +226 -0
  107. package/dist/tools/guidance.js.map +1 -0
  108. package/dist/tools/interface.d.ts +28 -0
  109. package/dist/tools/interface.js +63 -0
  110. package/dist/tools/interface.js.map +1 -0
  111. package/dist/tools/labels.d.ts +21 -0
  112. package/dist/tools/labels.js +92 -0
  113. package/dist/tools/labels.js.map +1 -0
  114. package/dist/tools/list-folders.d.ts +14 -0
  115. package/dist/tools/list-folders.js +70 -0
  116. package/dist/tools/list-folders.js.map +1 -0
  117. package/dist/tools/messages.d.ts +9 -0
  118. package/dist/tools/messages.js +221 -0
  119. package/dist/tools/messages.js.map +1 -0
  120. package/dist/tools/send.d.ts +29 -0
  121. package/dist/tools/send.js +236 -0
  122. package/dist/tools/send.js.map +1 -0
  123. package/dist/tools/sign-in-required.d.ts +94 -0
  124. package/dist/tools/sign-in-required.js +168 -0
  125. package/dist/tools/sign-in-required.js.map +1 -0
  126. package/dist/web/layout.d.ts +75 -0
  127. package/dist/web/layout.js +590 -0
  128. package/dist/web/layout.js.map +1 -0
  129. package/dist/web/pages.d.ts +79 -0
  130. package/dist/web/pages.js +284 -0
  131. package/dist/web/pages.js.map +1 -0
  132. package/dist/web/sections.d.ts +105 -0
  133. package/dist/web/sections.js +207 -0
  134. package/dist/web/sections.js.map +1 -0
  135. package/dist/web/security.d.ts +122 -0
  136. package/dist/web/security.js +180 -0
  137. package/dist/web/security.js.map +1 -0
  138. package/dist/web/server.d.ts +153 -0
  139. package/dist/web/server.js +622 -0
  140. package/dist/web/server.js.map +1 -0
  141. package/package.json +70 -0
@@ -0,0 +1,622 @@
1
+ /**
2
+ * The local web interface.
3
+ *
4
+ * Built on node:http with no framework. For something that handles credentials,
5
+ * every dependency is attack surface, and the routing here fits on one screen.
6
+ *
7
+ * It serves no files from disk at all: every response is generated. That removes
8
+ * path traversal as a category rather than guarding against it.
9
+ *
10
+ * All security checks live in security.ts and run before any handler. See there
11
+ * for what each one defends against.
12
+ */
13
+ var _a;
14
+ import { createServer } from 'node:http';
15
+ import { STORE_DESCRIPTIONS } from '../credentials/store.js';
16
+ import { listStores, recommend, recommendationReason } from '../credentials/availability.js';
17
+ import { createSession, checkRequest, csrfToken, securityHeaders } from './security.js';
18
+ import { loginPage, rejectionPage, unlockPage } from './pages.js';
19
+ import { overviewSection, bridgeSection, credentialsSection, activitySection, mailboxSection, } from './sections.js';
20
+ /**
21
+ * Upper bound for a request body.
22
+ *
23
+ * The forms here carry an address, a password and a token. Anything larger is
24
+ * either a mistake or an attempt to make the process allocate memory.
25
+ */
26
+ const MAX_BODY_BYTES = 8 * 1024;
27
+ /** Only loopback. There is no option to change this, by design. */
28
+ const BIND_ADDRESS = '127.0.0.1';
29
+ /**
30
+ * Which address shows which section.
31
+ *
32
+ * One table rather than a chain of comparisons, so that a path nobody listed
33
+ * cannot quietly reach a renderer. Everything not in here falls through to the
34
+ * rejection at the end of the handler.
35
+ */
36
+ const SECTION_PATHS = {
37
+ '/': 'overview',
38
+ '/mailboxes': 'mailboxes',
39
+ '/bridge': 'bridge',
40
+ '/credentials': 'credentials',
41
+ '/activity': 'activity',
42
+ };
43
+ /** The same names as a set, for checking a section that arrived in a form. */
44
+ const SECTIONS = new Set(Object.values(SECTION_PATHS));
45
+ /**
46
+ * The port tried first.
47
+ *
48
+ * A fixed default rather than a random one, because the interface runs for as
49
+ * long as the server does and is meant to be opened again and again. A port that
50
+ * moved on every start would make that needlessly awkward.
51
+ */
52
+ export const DEFAULT_WEB_PORT = 7345;
53
+ /**
54
+ * How many consecutive ports to try.
55
+ *
56
+ * Several clients may each start their own server, and the second one must not
57
+ * fail over a port the first one took. Failing outright would be worse than
58
+ * moving up by one.
59
+ */
60
+ export const PORT_ATTEMPTS = 10;
61
+ /**
62
+ * Reads a form body, refusing anything oversized.
63
+ *
64
+ * The limit is enforced while reading rather than after, so an oversized body is
65
+ * never held in memory in full.
66
+ */
67
+ export function readBody(request, maxBytes = MAX_BODY_BYTES) {
68
+ return new Promise((resolve) => {
69
+ const chunks = [];
70
+ let size = 0;
71
+ let aborted = false;
72
+ request.on('data', (chunk) => {
73
+ if (aborted)
74
+ return;
75
+ size += chunk.length;
76
+ if (size > maxBytes) {
77
+ aborted = true;
78
+ chunks.length = 0;
79
+ // Deliberately not destroy(): that resets the connection and the client
80
+ // sees ECONNRESET instead of an explanation. The rest of the body is
81
+ // drained and discarded so the handler can still answer with 413.
82
+ request.resume();
83
+ resolve({ fields: {}, tooLarge: true });
84
+ return;
85
+ }
86
+ chunks.push(chunk);
87
+ });
88
+ request.on('end', () => {
89
+ if (aborted)
90
+ return;
91
+ const params = new URLSearchParams(Buffer.concat(chunks).toString('utf8'));
92
+ const fields = {};
93
+ for (const [key, value] of params)
94
+ fields[key] = value;
95
+ resolve({ fields, tooLarge: false });
96
+ });
97
+ request.on('error', () => {
98
+ if (!aborted)
99
+ resolve({ fields: {}, tooLarge: false });
100
+ });
101
+ });
102
+ }
103
+ export class WebInterface {
104
+ #server;
105
+ #secrets = createSession();
106
+ #port = 0;
107
+ #options;
108
+ #notify;
109
+ constructor(options) {
110
+ this.#options = options;
111
+ this.#notify = options.notify ?? ((m) => process.stderr.write(`proton-mcp: ${m}\n`));
112
+ }
113
+ /** The URL the user has to open, including the access token. */
114
+ get url() {
115
+ return `http://${BIND_ADDRESS}:${this.#port}/?token=${this.#secrets.accessToken}`;
116
+ }
117
+ get port() {
118
+ return this.#port;
119
+ }
120
+ get running() {
121
+ return this.#server?.listening === true;
122
+ }
123
+ async start() {
124
+ if (this.#server?.listening)
125
+ return this.url;
126
+ const build = () => {
127
+ const created = createServer((request, response) => {
128
+ void this.#handle(request, response).catch(() => {
129
+ // A handler that throws must not take the process down, and must not
130
+ // leak anything either.
131
+ this.#send(response, 500, 'text/plain; charset=utf-8', 'Internal error.');
132
+ });
133
+ });
134
+ // Slow clients must not be able to tie up the server indefinitely.
135
+ created.headersTimeout = 10_000;
136
+ created.requestTimeout = 30_000;
137
+ return created;
138
+ };
139
+ const wanted = this.#options.port ?? DEFAULT_WEB_PORT;
140
+ // Port 0 means "any free port" and needs no retry loop.
141
+ const attempts = wanted === 0 ? 1 : PORT_ATTEMPTS;
142
+ let server;
143
+ let lastError;
144
+ for (let i = 0; i < attempts; i++) {
145
+ const candidate = wanted === 0 ? 0 : wanted + i;
146
+ // A fresh instance per attempt: after a failed listen() the old one is not
147
+ // reliably reusable.
148
+ const attempt = build();
149
+ try {
150
+ await new Promise((resolve, reject) => {
151
+ const onError = (error) => reject(error);
152
+ attempt.once('error', onError);
153
+ // Explicitly loopback: binding to 0.0.0.0 would put a page that stores
154
+ // credentials onto the network.
155
+ attempt.listen(candidate, BIND_ADDRESS, () => {
156
+ attempt.removeListener('error', onError);
157
+ resolve();
158
+ });
159
+ });
160
+ server = attempt;
161
+ lastError = undefined;
162
+ break;
163
+ }
164
+ catch (error) {
165
+ attempt.close();
166
+ lastError = error;
167
+ if (error.code !== 'EADDRINUSE')
168
+ break;
169
+ // Taken, most likely by another instance of this server. Try the next.
170
+ }
171
+ }
172
+ if (!server || lastError) {
173
+ const code = lastError?.code;
174
+ throw new Error(code === 'EADDRINUSE'
175
+ ? `Ports ${wanted} to ${wanted + attempts - 1} are all in use, so the web interface ` +
176
+ 'could not start. Set PROTON_MCP_WEB_PORT to a free port.'
177
+ : `The web interface could not start: ${lastError?.message ?? 'unknown reason'}`);
178
+ }
179
+ const address = server.address();
180
+ this.#port = typeof address === 'object' && address ? address.port : 0;
181
+ this.#server = server;
182
+ return this.url;
183
+ }
184
+ async stop() {
185
+ const server = this.#server;
186
+ this.#server = undefined;
187
+ if (!server)
188
+ return;
189
+ // close() alone only stops accepting new connections and then waits for the
190
+ // existing ones. A browser keeps its connection alive, so a single open tab
191
+ // would hold the shutdown forever and the MCP server would never exit.
192
+ server.closeIdleConnections();
193
+ server.closeAllConnections();
194
+ await new Promise((resolve) => server.close(() => resolve()));
195
+ }
196
+ /** Invalidates the current link and issues a new one. */
197
+ rotateToken() {
198
+ this.#secrets = createSession();
199
+ return this.url;
200
+ }
201
+ #send(response, status, contentType, body) {
202
+ response.writeHead(status, { ...securityHeaders(), 'Content-Type': contentType });
203
+ response.end(body);
204
+ }
205
+ #reject(response, status = 404) {
206
+ // Always the same page and the same status, whatever the reason. Telling a
207
+ // caller which check failed would help them work around it.
208
+ this.#send(response, status, 'text/html; charset=utf-8', rejectionPage());
209
+ }
210
+ async #handle(request, response) {
211
+ const url = new URL(request.url ?? '/', `http://${BIND_ADDRESS}:${this.#port}`);
212
+ const path = url.pathname;
213
+ const method = request.method ?? 'GET';
214
+ const writing = method === 'POST';
215
+ if (method !== 'GET' && method !== 'POST') {
216
+ this.#reject(response, 405);
217
+ return;
218
+ }
219
+ // Answered before the token check and without a log line. Browsers ask for
220
+ // it on every page view, and each one would otherwise be recorded as a
221
+ // refused request, which buries the refusals that mean something.
222
+ if (path === '/favicon.ico') {
223
+ response.writeHead(404, { ...securityHeaders(), 'Content-Length': '0' });
224
+ response.end();
225
+ return;
226
+ }
227
+ // The body has to be read before the checks for a POST, because the CSRF
228
+ // token is in it. It is bounded, so this cannot be used to make us allocate.
229
+ const body = writing ? await readBody(request) : { fields: {}, tooLarge: false };
230
+ if (body.tooLarge) {
231
+ // Close the connection after answering: the client may still be sending,
232
+ // and keeping the socket alive would mean reading the rest for nothing.
233
+ response.setHeader('Connection', 'close');
234
+ this.#reject(response, 413);
235
+ return;
236
+ }
237
+ const purpose = path;
238
+ const check = checkRequest({
239
+ request,
240
+ secrets: this.#secrets,
241
+ port: this.#port,
242
+ presentedToken: url.searchParams.get('token') ?? undefined,
243
+ writing,
244
+ ...(writing ? { csrf: { purpose, presented: body.fields.csrf } } : {}),
245
+ });
246
+ if (!check.ok) {
247
+ // Worth a line on stderr: a rejected request on a loopback-only interface
248
+ // is either a mistake or something worth knowing about.
249
+ this.#notify(`web interface refused a ${method} to ${path} (${check.reason})`);
250
+ this.#reject(response);
251
+ return;
252
+ }
253
+ if (method === 'GET') {
254
+ const section = SECTION_PATHS[path];
255
+ if (section) {
256
+ await this.#render(section, response);
257
+ return;
258
+ }
259
+ }
260
+ if (writing && path === '/dismiss-notice') {
261
+ await this.#handleDismissNotice(response, body.fields);
262
+ return;
263
+ }
264
+ if (writing && path === '/settings') {
265
+ await this.#handlePorts(response, body.fields);
266
+ return;
267
+ }
268
+ if (writing && path === '/test-connection') {
269
+ await this.#handleTest(response);
270
+ return;
271
+ }
272
+ if (writing && path === '/sign-in') {
273
+ await this.#handleSignIn(response, body.fields);
274
+ return;
275
+ }
276
+ if (writing && path === '/unlock') {
277
+ await this.#handleUnlock(response, body.fields);
278
+ return;
279
+ }
280
+ if (writing && path === '/discard-encrypted') {
281
+ await this.#options.onDiscardEncrypted?.();
282
+ // Both of these end with nobody signed in, so the section asked for is
283
+ // beside the point: #render lands on the sign-in form either way.
284
+ await this.#render('overview', response);
285
+ return;
286
+ }
287
+ if (writing && path === '/sign-out') {
288
+ await this.#options.onSignOut();
289
+ await this.#render('overview', response);
290
+ return;
291
+ }
292
+ this.#reject(response);
293
+ }
294
+ /**
295
+ * Renders one section, or whichever page the current state demands instead.
296
+ *
297
+ * The state outranks the request: stored-but-locked leads to the unlock page
298
+ * and nothing stored to the sign-in form, whichever section was asked for.
299
+ * That is what puts a wrong master password on the unlock page and a refused
300
+ * Bridge login on the sign-in form without either having to say so, and it is
301
+ * also why no section has to check whether anybody is signed in.
302
+ */
303
+ async #render(section, response, outcome = {}) {
304
+ const { error, notice, address, store, showAdvanced } = outcome;
305
+ const status = await this.#options.getStatus();
306
+ const token = this.#secrets.accessToken;
307
+ const disclaimer = this.#disclaimerFor(section);
308
+ if (!status.connected && status.locked) {
309
+ const page = unlockPage({
310
+ token,
311
+ disclaimer,
312
+ csrf: csrfToken(this.#secrets, '/unlock'),
313
+ csrfDiscard: csrfToken(this.#secrets, '/discard-encrypted'),
314
+ path: status.encryptedPath ?? 'your user directory',
315
+ ...(error ? { error } : {}),
316
+ });
317
+ this.#send(response, 200, 'text/html; charset=utf-8', page);
318
+ return;
319
+ }
320
+ if (!status.connected) {
321
+ const stores = await listStores();
322
+ const page = loginPage({
323
+ token,
324
+ disclaimer,
325
+ csrf: csrfToken(this.#secrets, '/sign-in'),
326
+ stores,
327
+ suggested: recommend(stores),
328
+ suggestionReason: recommendationReason(stores),
329
+ bridgeHost: status.bridgeHost,
330
+ bridgeImapPort: status.bridgeImapPort,
331
+ bridgeSmtpPort: status.bridgeSmtpPort,
332
+ portsLocked: this.#options.onPorts === undefined,
333
+ ...(store ? { chosen: store } : {}),
334
+ ...(error ? { error } : {}),
335
+ ...(address ? { address } : {}),
336
+ ...(showAdvanced ? { showAdvanced } : {}),
337
+ });
338
+ this.#send(response, 200, 'text/html; charset=utf-8', page);
339
+ return;
340
+ }
341
+ const banners = {
342
+ disclaimer,
343
+ ...(error ? { error } : {}),
344
+ ...(notice ? { notice } : {}),
345
+ };
346
+ const storeTitle = status.storeKind
347
+ ? { storeTitle: STORE_DESCRIPTIONS[status.storeKind].title }
348
+ : {};
349
+ let page;
350
+ switch (section) {
351
+ case 'mailboxes':
352
+ page = await this.#renderMailboxes(token, banners);
353
+ break;
354
+ case 'bridge':
355
+ page = bridgeSection({
356
+ token,
357
+ csrfSettings: csrfToken(this.#secrets, '/settings'),
358
+ csrfTest: csrfToken(this.#secrets, '/test-connection'),
359
+ bridgeHost: status.bridgeHost,
360
+ bridgeImapPort: status.bridgeImapPort,
361
+ bridgeSmtpPort: status.bridgeSmtpPort,
362
+ // No handler means the ports are not ours to change.
363
+ portsLocked: this.#options.onPorts === undefined,
364
+ ...(status.certificate ? { certificate: status.certificate } : {}),
365
+ ...banners,
366
+ });
367
+ break;
368
+ case 'credentials':
369
+ page = credentialsSection({
370
+ token,
371
+ csrfSignOut: csrfToken(this.#secrets, '/sign-out'),
372
+ ...(status.address ? { address: status.address } : {}),
373
+ ...(status.storeKind ? { storeKind: status.storeKind } : {}),
374
+ ...storeTitle,
375
+ ...banners,
376
+ });
377
+ break;
378
+ case 'activity': {
379
+ const activity = this.#options.getActivity?.() ?? { running: [], recent: [] };
380
+ page = activitySection({ token, ...activity, ...banners });
381
+ break;
382
+ }
383
+ default:
384
+ page = overviewSection({
385
+ token,
386
+ connected: true,
387
+ ...(status.address ? { address: status.address } : {}),
388
+ ...storeTitle,
389
+ ...(status.mailboxCount !== undefined ? { mailboxCount: status.mailboxCount } : {}),
390
+ ...(status.messageCount !== undefined ? { messageCount: status.messageCount } : {}),
391
+ ...(status.unseenCount !== undefined ? { unseenCount: status.unseenCount } : {}),
392
+ bridgeHost: status.bridgeHost,
393
+ bridgeImapPort: status.bridgeImapPort,
394
+ bridgeSmtpPort: status.bridgeSmtpPort,
395
+ readOnly: status.readOnly === true,
396
+ webPort: this.#port,
397
+ uptimeMs: status.uptimeMs ?? 0,
398
+ ...banners,
399
+ });
400
+ }
401
+ this.#send(response, 200, 'text/html; charset=utf-8', page);
402
+ }
403
+ /**
404
+ * Whether the notice is shown, and whether it carries a button.
405
+ *
406
+ * A server wired without a way to remember the dismissal still shows the
407
+ * notice, just without the button. Silently dropping it because a handler is
408
+ * missing would be the one outcome nobody wants.
409
+ */
410
+ #disclaimerFor(section) {
411
+ if (this.#options.noticeDismissed?.() === true)
412
+ return 'dismissed';
413
+ if (!this.#options.onDismissNotice)
414
+ return 'plain';
415
+ return { csrf: csrfToken(this.#secrets, '/dismiss-notice'), from: section };
416
+ }
417
+ /**
418
+ * Sends the notice away for good.
419
+ *
420
+ * The section it was dismissed from travels in the form, so the answer is the
421
+ * page the user was already on rather than a jump back to the overview. An
422
+ * unknown value falls back to the overview instead of being trusted.
423
+ */
424
+ async #handleDismissNotice(response, fields) {
425
+ await this.#options.onDismissNotice?.();
426
+ const from = SECTIONS.has(fields.from ?? '') ? fields.from : 'overview';
427
+ await this.#render(from, response);
428
+ }
429
+ /**
430
+ * The folders and labels, only ever on this page.
431
+ *
432
+ * Never folded into another section: these names belong to the whole Proton
433
+ * account and give away banks, employers and authorities on their own. The
434
+ * caller has already established that somebody is signed in, so the only
435
+ * question left here is whether the Bridge answers.
436
+ */
437
+ async #renderMailboxes(token, banners) {
438
+ let mailboxes = [];
439
+ let error = banners.error;
440
+ if (this.#options.getMailboxes) {
441
+ try {
442
+ mailboxes = await this.#options.getMailboxes();
443
+ }
444
+ catch (failure) {
445
+ error = failure.message;
446
+ }
447
+ }
448
+ return mailboxSection({
449
+ token,
450
+ mailboxes,
451
+ disclaimer: banners.disclaimer,
452
+ ...(error ? { error } : {}),
453
+ ...(banners.notice ? { notice: banners.notice } : {}),
454
+ });
455
+ }
456
+ /**
457
+ * Reads a pair of ports out of a form.
458
+ *
459
+ * One place for it, because two forms carry them now: the bridge section and
460
+ * the advanced block of the sign-in page. A port that is wrong has to be
461
+ * caught before anything tries to connect with it, or the answer is
462
+ * "connection refused" and the cause is invisible.
463
+ */
464
+ static #readPorts(fields) {
465
+ const parsed = { imapPort: 0, smtpPort: 0 };
466
+ for (const field of ['imapPort', 'smtpPort']) {
467
+ const raw = (fields[field] ?? '').trim();
468
+ const value = Number(raw);
469
+ if (!raw || !Number.isInteger(value) || value < 1 || value > 65535) {
470
+ return {
471
+ error: `"${raw}" is not a usable port for ${field === 'imapPort' ? 'IMAP' : 'SMTP'}. ` +
472
+ 'Expected a whole number between 1 and 65535.',
473
+ };
474
+ }
475
+ parsed[field] = value;
476
+ }
477
+ return { ports: parsed };
478
+ }
479
+ async #handlePorts(response, fields) {
480
+ if (!this.#options.onPorts) {
481
+ await this.#render('bridge', response, {
482
+ error: 'The ports are set through the environment on this server.',
483
+ });
484
+ return;
485
+ }
486
+ const read = _a.#readPorts(fields);
487
+ if ('error' in read) {
488
+ await this.#render('bridge', response, { error: read.error });
489
+ return;
490
+ }
491
+ const parsed = read.ports;
492
+ const error = await this.#options.onPorts(parsed);
493
+ await this.#render('bridge', response, {
494
+ ...(error
495
+ ? { error }
496
+ : { notice: `Ports saved: IMAP ${parsed.imapPort}, SMTP ${parsed.smtpPort}.` }),
497
+ });
498
+ }
499
+ async #handleTest(response) {
500
+ if (!this.#options.onTest) {
501
+ await this.#render('bridge', response, { error: 'This server cannot test the connection.' });
502
+ return;
503
+ }
504
+ const result = await this.#options.onTest();
505
+ await this.#render('bridge', response, result.ok ? { notice: result.message } : { error: result.message });
506
+ }
507
+ async #handleUnlock(response, fields) {
508
+ const master = fields.master ?? '';
509
+ if (!master) {
510
+ await this.#render('overview', response, { error: 'The master password is required.' });
511
+ return;
512
+ }
513
+ if (!this.#options.onUnlock) {
514
+ await this.#render('overview', response, {
515
+ error: 'This server cannot open encrypted credential files.',
516
+ });
517
+ return;
518
+ }
519
+ const error = await this.#options.onUnlock(master);
520
+ await this.#render('overview', response, { ...(error ? { error } : {}) });
521
+ }
522
+ /**
523
+ * Reads the storage option out of the form.
524
+ *
525
+ * It arrives as a radio value now rather than being remembered from an
526
+ * earlier post, so it is ordinary untrusted input: a name that is not one of
527
+ * the four, or one that cannot work on this machine, falls back to the
528
+ * recommendation rather than being passed on.
529
+ */
530
+ async #storeFromForm(fields) {
531
+ const stores = await listStores();
532
+ const wanted = fields.store;
533
+ if (!wanted || !(wanted in STORE_DESCRIPTIONS))
534
+ return { store: recommend(stores) };
535
+ const kind = wanted;
536
+ const entry = stores.find((s) => s.kind === kind);
537
+ if (!entry?.available) {
538
+ return {
539
+ store: recommend(stores),
540
+ error: `${STORE_DESCRIPTIONS[kind].title} cannot be used on this machine. ${entry?.reason ?? ''}`,
541
+ };
542
+ }
543
+ return { store: kind };
544
+ }
545
+ async #handleSignIn(response, fields) {
546
+ const address = (fields.address ?? '').trim();
547
+ const password = fields.password ?? '';
548
+ const { store, error: storeError } = await this.#storeFromForm(fields);
549
+ if (storeError) {
550
+ await this.#render('overview', response, { error: storeError, address, store });
551
+ return;
552
+ }
553
+ // The ports come first, before the credentials are tried. Somebody whose
554
+ // Bridge listens elsewhere would otherwise be told their password is wrong,
555
+ // because the attempt went to a port with nothing behind it. Only when the
556
+ // form carries them: the block is read-only when the environment decided.
557
+ if (this.#options.onPorts && fields.imapPort !== undefined) {
558
+ const read = _a.#readPorts(fields);
559
+ if ('error' in read) {
560
+ await this.#render('overview', response, {
561
+ error: read.error,
562
+ address,
563
+ store,
564
+ showAdvanced: true,
565
+ });
566
+ return;
567
+ }
568
+ const failed = await this.#options.onPorts(read.ports);
569
+ if (failed) {
570
+ await this.#render('overview', response, {
571
+ error: failed,
572
+ address,
573
+ store,
574
+ showAdvanced: true,
575
+ });
576
+ return;
577
+ }
578
+ }
579
+ if (!address || !password) {
580
+ await this.#render('overview', response, {
581
+ error: 'Both the address and the Bridge password are required.',
582
+ address,
583
+ store,
584
+ });
585
+ return;
586
+ }
587
+ // Checked here rather than in the session, because this is where the second
588
+ // field exists to compare against. A typo in a password nothing can recover
589
+ // has to be caught before it is used to encrypt anything.
590
+ //
591
+ // Read only for the store that uses it. The field is in the document for
592
+ // every option now, hidden by CSS, so a value left behind by switching
593
+ // options would otherwise be taken for a choice.
594
+ let master;
595
+ if (store === 'encrypted-file') {
596
+ master = fields.master ?? '';
597
+ if (!master) {
598
+ await this.#render('overview', response, {
599
+ error: 'The encrypted file needs a master password to encrypt the credentials with.',
600
+ address,
601
+ store,
602
+ });
603
+ return;
604
+ }
605
+ if (master !== (fields.masterRepeat ?? '')) {
606
+ await this.#render('overview', response, {
607
+ error: 'The two master passwords do not match.',
608
+ address,
609
+ store,
610
+ });
611
+ return;
612
+ }
613
+ }
614
+ const error = await this.#options.onSignIn({ user: address, pass: password }, store, master);
615
+ // No password is kept anywhere in this class, whatever the outcome.
616
+ await this.#render('overview', response, {
617
+ ...(error ? { error, address, store } : {}),
618
+ });
619
+ }
620
+ }
621
+ _a = WebInterface;
622
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"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"}