@bobfrankston/mailx 1.0.12 → 1.0.14

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 (172) hide show
  1. package/bin/mailx.js +52 -28
  2. package/client/app.js +113 -30
  3. package/client/components/folder-tree.js +84 -3
  4. package/client/components/message-list.js +164 -10
  5. package/client/components/message-viewer.js +130 -13
  6. package/client/compose/compose.html +4 -4
  7. package/client/compose/compose.js +53 -34
  8. package/client/index.html +50 -21
  9. package/client/lib/api-client.js +112 -31
  10. package/client/lib/mailxapi.js +123 -0
  11. package/client/package.json +1 -1
  12. package/client/styles/components.css +206 -16
  13. package/client/styles/layout.css +2 -1
  14. package/killmail.cmd +6 -0
  15. package/launch.ps1 +47 -5
  16. package/launcher/bin/mailx-app-linux +0 -0
  17. package/launcher/bin/mailx-app.exe +0 -0
  18. package/launcher/builder/build-config.json +11 -0
  19. package/launcher/builder/postinstall.js +81 -0
  20. package/package.json +2 -4
  21. package/packages/mailx-api/index.js +125 -29
  22. package/packages/mailx-core/index.d.ts +129 -0
  23. package/packages/mailx-core/index.js +323 -0
  24. package/packages/mailx-core/ipc.d.ts +13 -0
  25. package/packages/mailx-core/ipc.js +56 -0
  26. package/packages/mailx-core/package.json +18 -0
  27. package/packages/mailx-imap/index.d.ts +7 -1
  28. package/packages/mailx-imap/index.js +89 -14
  29. package/packages/mailx-server/index.js +42 -31
  30. package/packages/mailx-server/package.json +1 -2
  31. package/packages/mailx-settings/index.d.ts +1 -1
  32. package/packages/mailx-settings/index.js +21 -12
  33. package/packages/mailx-store/db.d.ts +6 -2
  34. package/packages/mailx-store/db.js +78 -16
  35. package/packages/mailx-store/file-store.d.ts +2 -8
  36. package/packages/mailx-store/file-store.js +7 -31
  37. package/packages/mailx-types/index.d.ts +3 -1
  38. package/.tswalk.json +0 -7396
  39. package/launcher/release.cmd +0 -4
  40. package/mailx.json +0 -9
  41. package/packages/mailx-api/node_modules/nodemailer/.ncurc.js +0 -9
  42. package/packages/mailx-api/node_modules/nodemailer/.prettierignore +0 -8
  43. package/packages/mailx-api/node_modules/nodemailer/.prettierrc +0 -12
  44. package/packages/mailx-api/node_modules/nodemailer/.prettierrc.js +0 -10
  45. package/packages/mailx-api/node_modules/nodemailer/.release-please-config.json +0 -9
  46. package/packages/mailx-api/node_modules/nodemailer/LICENSE +0 -16
  47. package/packages/mailx-api/node_modules/nodemailer/README.md +0 -86
  48. package/packages/mailx-api/node_modules/nodemailer/SECURITY.txt +0 -22
  49. package/packages/mailx-api/node_modules/nodemailer/eslint.config.js +0 -88
  50. package/packages/mailx-api/node_modules/nodemailer/lib/addressparser/index.js +0 -383
  51. package/packages/mailx-api/node_modules/nodemailer/lib/base64/index.js +0 -139
  52. package/packages/mailx-api/node_modules/nodemailer/lib/dkim/index.js +0 -253
  53. package/packages/mailx-api/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
  54. package/packages/mailx-api/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
  55. package/packages/mailx-api/node_modules/nodemailer/lib/dkim/sign.js +0 -117
  56. package/packages/mailx-api/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
  57. package/packages/mailx-api/node_modules/nodemailer/lib/fetch/index.js +0 -280
  58. package/packages/mailx-api/node_modules/nodemailer/lib/json-transport/index.js +0 -82
  59. package/packages/mailx-api/node_modules/nodemailer/lib/mail-composer/index.js +0 -629
  60. package/packages/mailx-api/node_modules/nodemailer/lib/mailer/index.js +0 -441
  61. package/packages/mailx-api/node_modules/nodemailer/lib/mailer/mail-message.js +0 -316
  62. package/packages/mailx-api/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
  63. package/packages/mailx-api/node_modules/nodemailer/lib/mime-funcs/mime-types.js +0 -2113
  64. package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/index.js +0 -1316
  65. package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/last-newline.js +0 -33
  66. package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/le-unix.js +0 -43
  67. package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/le-windows.js +0 -52
  68. package/packages/mailx-api/node_modules/nodemailer/lib/nodemailer.js +0 -157
  69. package/packages/mailx-api/node_modules/nodemailer/lib/punycode/index.js +0 -460
  70. package/packages/mailx-api/node_modules/nodemailer/lib/qp/index.js +0 -227
  71. package/packages/mailx-api/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
  72. package/packages/mailx-api/node_modules/nodemailer/lib/ses-transport/index.js +0 -234
  73. package/packages/mailx-api/node_modules/nodemailer/lib/shared/index.js +0 -754
  74. package/packages/mailx-api/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
  75. package/packages/mailx-api/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
  76. package/packages/mailx-api/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1870
  77. package/packages/mailx-api/node_modules/nodemailer/lib/smtp-pool/index.js +0 -652
  78. package/packages/mailx-api/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +0 -259
  79. package/packages/mailx-api/node_modules/nodemailer/lib/smtp-transport/index.js +0 -421
  80. package/packages/mailx-api/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
  81. package/packages/mailx-api/node_modules/nodemailer/lib/well-known/index.js +0 -47
  82. package/packages/mailx-api/node_modules/nodemailer/lib/well-known/services.json +0 -611
  83. package/packages/mailx-api/node_modules/nodemailer/lib/xoauth2/index.js +0 -427
  84. package/packages/mailx-api/node_modules/nodemailer/package.json +0 -47
  85. package/packages/mailx-imap/node_modules/nodemailer/.ncurc.js +0 -9
  86. package/packages/mailx-imap/node_modules/nodemailer/.prettierignore +0 -8
  87. package/packages/mailx-imap/node_modules/nodemailer/.prettierrc +0 -12
  88. package/packages/mailx-imap/node_modules/nodemailer/.prettierrc.js +0 -10
  89. package/packages/mailx-imap/node_modules/nodemailer/.release-please-config.json +0 -9
  90. package/packages/mailx-imap/node_modules/nodemailer/LICENSE +0 -16
  91. package/packages/mailx-imap/node_modules/nodemailer/README.md +0 -86
  92. package/packages/mailx-imap/node_modules/nodemailer/SECURITY.txt +0 -22
  93. package/packages/mailx-imap/node_modules/nodemailer/eslint.config.js +0 -88
  94. package/packages/mailx-imap/node_modules/nodemailer/lib/addressparser/index.js +0 -383
  95. package/packages/mailx-imap/node_modules/nodemailer/lib/base64/index.js +0 -139
  96. package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/index.js +0 -253
  97. package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
  98. package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
  99. package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/sign.js +0 -117
  100. package/packages/mailx-imap/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
  101. package/packages/mailx-imap/node_modules/nodemailer/lib/fetch/index.js +0 -280
  102. package/packages/mailx-imap/node_modules/nodemailer/lib/json-transport/index.js +0 -82
  103. package/packages/mailx-imap/node_modules/nodemailer/lib/mail-composer/index.js +0 -629
  104. package/packages/mailx-imap/node_modules/nodemailer/lib/mailer/index.js +0 -441
  105. package/packages/mailx-imap/node_modules/nodemailer/lib/mailer/mail-message.js +0 -316
  106. package/packages/mailx-imap/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
  107. package/packages/mailx-imap/node_modules/nodemailer/lib/mime-funcs/mime-types.js +0 -2113
  108. package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/index.js +0 -1316
  109. package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/last-newline.js +0 -33
  110. package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/le-unix.js +0 -43
  111. package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/le-windows.js +0 -52
  112. package/packages/mailx-imap/node_modules/nodemailer/lib/nodemailer.js +0 -157
  113. package/packages/mailx-imap/node_modules/nodemailer/lib/punycode/index.js +0 -460
  114. package/packages/mailx-imap/node_modules/nodemailer/lib/qp/index.js +0 -227
  115. package/packages/mailx-imap/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
  116. package/packages/mailx-imap/node_modules/nodemailer/lib/ses-transport/index.js +0 -234
  117. package/packages/mailx-imap/node_modules/nodemailer/lib/shared/index.js +0 -754
  118. package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
  119. package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
  120. package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1870
  121. package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-pool/index.js +0 -652
  122. package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +0 -259
  123. package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-transport/index.js +0 -421
  124. package/packages/mailx-imap/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
  125. package/packages/mailx-imap/node_modules/nodemailer/lib/well-known/index.js +0 -47
  126. package/packages/mailx-imap/node_modules/nodemailer/lib/well-known/services.json +0 -611
  127. package/packages/mailx-imap/node_modules/nodemailer/lib/xoauth2/index.js +0 -427
  128. package/packages/mailx-imap/node_modules/nodemailer/package.json +0 -47
  129. package/packages/mailx-send/node_modules/nodemailer/.ncurc.js +0 -9
  130. package/packages/mailx-send/node_modules/nodemailer/.prettierignore +0 -8
  131. package/packages/mailx-send/node_modules/nodemailer/.prettierrc +0 -12
  132. package/packages/mailx-send/node_modules/nodemailer/.prettierrc.js +0 -10
  133. package/packages/mailx-send/node_modules/nodemailer/.release-please-config.json +0 -9
  134. package/packages/mailx-send/node_modules/nodemailer/LICENSE +0 -16
  135. package/packages/mailx-send/node_modules/nodemailer/README.md +0 -86
  136. package/packages/mailx-send/node_modules/nodemailer/SECURITY.txt +0 -22
  137. package/packages/mailx-send/node_modules/nodemailer/eslint.config.js +0 -88
  138. package/packages/mailx-send/node_modules/nodemailer/lib/addressparser/index.js +0 -383
  139. package/packages/mailx-send/node_modules/nodemailer/lib/base64/index.js +0 -139
  140. package/packages/mailx-send/node_modules/nodemailer/lib/dkim/index.js +0 -253
  141. package/packages/mailx-send/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
  142. package/packages/mailx-send/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
  143. package/packages/mailx-send/node_modules/nodemailer/lib/dkim/sign.js +0 -117
  144. package/packages/mailx-send/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
  145. package/packages/mailx-send/node_modules/nodemailer/lib/fetch/index.js +0 -280
  146. package/packages/mailx-send/node_modules/nodemailer/lib/json-transport/index.js +0 -82
  147. package/packages/mailx-send/node_modules/nodemailer/lib/mail-composer/index.js +0 -629
  148. package/packages/mailx-send/node_modules/nodemailer/lib/mailer/index.js +0 -441
  149. package/packages/mailx-send/node_modules/nodemailer/lib/mailer/mail-message.js +0 -316
  150. package/packages/mailx-send/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
  151. package/packages/mailx-send/node_modules/nodemailer/lib/mime-funcs/mime-types.js +0 -2113
  152. package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/index.js +0 -1316
  153. package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/last-newline.js +0 -33
  154. package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/le-unix.js +0 -43
  155. package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/le-windows.js +0 -52
  156. package/packages/mailx-send/node_modules/nodemailer/lib/nodemailer.js +0 -157
  157. package/packages/mailx-send/node_modules/nodemailer/lib/punycode/index.js +0 -460
  158. package/packages/mailx-send/node_modules/nodemailer/lib/qp/index.js +0 -227
  159. package/packages/mailx-send/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
  160. package/packages/mailx-send/node_modules/nodemailer/lib/ses-transport/index.js +0 -234
  161. package/packages/mailx-send/node_modules/nodemailer/lib/shared/index.js +0 -754
  162. package/packages/mailx-send/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
  163. package/packages/mailx-send/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
  164. package/packages/mailx-send/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1870
  165. package/packages/mailx-send/node_modules/nodemailer/lib/smtp-pool/index.js +0 -652
  166. package/packages/mailx-send/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +0 -259
  167. package/packages/mailx-send/node_modules/nodemailer/lib/smtp-transport/index.js +0 -421
  168. package/packages/mailx-send/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
  169. package/packages/mailx-send/node_modules/nodemailer/lib/well-known/index.js +0 -47
  170. package/packages/mailx-send/node_modules/nodemailer/lib/well-known/services.json +0 -611
  171. package/packages/mailx-send/node_modules/nodemailer/lib/xoauth2/index.js +0 -427
  172. package/packages/mailx-send/node_modules/nodemailer/package.json +0 -47
@@ -241,8 +241,43 @@ export class MailxDB {
241
241
  }));
242
242
  return { items, total, page, pageSize };
243
243
  }
244
- getMessageByUid(accountId, uid) {
245
- const r = this.db.prepare("SELECT * FROM messages WHERE account_id = ? AND uid = ?").get(accountId, uid);
244
+ /** Unified inbox: all inbox folders across accounts, sorted by date, paginated in SQL */
245
+ getUnifiedInbox(page = 1, pageSize = 50) {
246
+ const offset = (page - 1) * pageSize;
247
+ // Find all inbox folder IDs
248
+ const inboxRows = this.db.prepare("SELECT id FROM folders WHERE special_use = 'inbox'").all();
249
+ if (inboxRows.length === 0)
250
+ return { items: [], total: 0, page, pageSize };
251
+ const placeholders = inboxRows.map(() => "?").join(",");
252
+ const folderIds = inboxRows.map((r) => r.id);
253
+ const total = this.db.prepare(`SELECT COUNT(*) as cnt FROM messages WHERE folder_id IN (${placeholders})`).get(...folderIds).cnt;
254
+ const rows = this.db.prepare(`SELECT * FROM messages WHERE folder_id IN (${placeholders}) ORDER BY date DESC LIMIT ? OFFSET ?`).all(...folderIds, pageSize, offset);
255
+ const items = rows.map(r => ({
256
+ id: r.id,
257
+ accountId: r.account_id,
258
+ folderId: r.folder_id,
259
+ uid: r.uid,
260
+ messageId: r.message_id || "",
261
+ inReplyTo: r.in_reply_to || "",
262
+ references: JSON.parse(r.refs || "[]"),
263
+ date: r.date,
264
+ subject: r.subject,
265
+ from: { name: r.from_name, address: r.from_address },
266
+ to: JSON.parse(r.to_json),
267
+ cc: JSON.parse(r.cc_json),
268
+ flags: JSON.parse(r.flags_json),
269
+ size: r.size,
270
+ hasAttachments: !!r.has_attachments,
271
+ preview: r.preview
272
+ }));
273
+ return { items, total, page, pageSize };
274
+ }
275
+ getMessageByUid(accountId, uid, folderId) {
276
+ const sql = folderId != null
277
+ ? "SELECT * FROM messages WHERE account_id = ? AND uid = ? AND folder_id = ?"
278
+ : "SELECT * FROM messages WHERE account_id = ? AND uid = ?";
279
+ const params = folderId != null ? [accountId, uid, folderId] : [accountId, uid];
280
+ const r = this.db.prepare(sql).get(...params);
246
281
  if (!r)
247
282
  return null;
248
283
  return {
@@ -282,7 +317,19 @@ export class MailxDB {
282
317
  }
283
318
  /** Delete a message by account + UID */
284
319
  deleteMessage(accountId, uid) {
320
+ // Get folderId before deleting so we can update counts
321
+ const msg = this.db.prepare("SELECT folder_id FROM messages WHERE account_id = ? AND uid = ?").get(accountId, uid);
285
322
  this.db.prepare("DELETE FROM messages WHERE account_id = ? AND uid = ?").run(accountId, uid);
323
+ // Refresh folder counts
324
+ if (msg)
325
+ this.recalcFolderCounts(msg.folder_id);
326
+ }
327
+ /** Recalculate folder total/unread counts from actual messages */
328
+ recalcFolderCounts(folderId) {
329
+ const counts = this.db.prepare(`SELECT COUNT(*) as total,
330
+ SUM(CASE WHEN flags_json NOT LIKE '%\\\\Seen%' THEN 1 ELSE 0 END) as unread
331
+ FROM messages WHERE folder_id = ?`).get(folderId);
332
+ this.updateFolderCounts(folderId, counts?.total || 0, counts?.unread || 0);
286
333
  }
287
334
  /** Bulk insert within a transaction for sync performance */
288
335
  beginTransaction() { this.db.exec("BEGIN"); }
@@ -328,7 +375,7 @@ export class MailxDB {
328
375
  }
329
376
  // ── Search ──
330
377
  /** Full-text search across all messages. Supports qualifiers: from:, to:, subject: */
331
- searchMessages(query, page = 1, pageSize = 50) {
378
+ searchMessages(query, page = 1, pageSize = 50, accountId, folderId) {
332
379
  // Parse qualifiers
333
380
  let ftsQuery = "";
334
381
  const parts = query.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
@@ -358,13 +405,23 @@ export class MailxDB {
358
405
  return { items: [], total: 0, page, pageSize };
359
406
  const offset = (page - 1) * pageSize;
360
407
  try {
361
- const countRow = this.db.prepare("SELECT COUNT(*) as cnt FROM messages_fts WHERE messages_fts MATCH ?").get(ftsQuery);
408
+ let scopeWhere = "";
409
+ const scopeParams = [];
410
+ if (accountId && folderId) {
411
+ scopeWhere = " AND m.account_id = ? AND m.folder_id = ?";
412
+ scopeParams.push(accountId, folderId);
413
+ }
414
+ else if (accountId) {
415
+ scopeWhere = " AND m.account_id = ?";
416
+ scopeParams.push(accountId);
417
+ }
418
+ const countRow = this.db.prepare(`SELECT COUNT(*) as cnt FROM messages m JOIN messages_fts fts ON m.id = fts.rowid WHERE messages_fts MATCH ?${scopeWhere}`).get(ftsQuery, ...scopeParams);
362
419
  const total = countRow?.cnt || 0;
363
420
  const rows = this.db.prepare(`SELECT m.* FROM messages m
364
421
  JOIN messages_fts fts ON m.id = fts.rowid
365
- WHERE messages_fts MATCH ?
422
+ WHERE messages_fts MATCH ?${scopeWhere}
366
423
  ORDER BY m.date DESC
367
- LIMIT ? OFFSET ?`).all(ftsQuery, pageSize, offset);
424
+ LIMIT ? OFFSET ?`).all(ftsQuery, ...scopeParams, pageSize, offset);
368
425
  const items = rows.map(r => ({
369
426
  id: r.id,
370
427
  accountId: r.account_id,
@@ -401,19 +458,24 @@ export class MailxDB {
401
458
  subject, from_name, from_address, to_text, cc_text, body_text,
402
459
  content=messages, content_rowid=id
403
460
  )`);
461
+ // Use a single transaction + prepared statement for speed (~50x faster than individual inserts)
462
+ const insert = this.db.prepare("INSERT INTO messages_fts (rowid, subject, from_name, from_address, to_text, cc_text, body_text) VALUES (?, ?, ?, ?, ?, ?, ?)");
404
463
  const rows = this.db.prepare("SELECT id, subject, from_name, from_address, to_json, cc_json, preview FROM messages").all();
405
464
  let count = 0;
406
- for (const r of rows) {
407
- const to = JSON.parse(r.to_json || "[]");
408
- const cc = JSON.parse(r.cc_json || "[]");
409
- const toText = to.map((a) => `${a.name} ${a.address}`).join(" ");
410
- const ccText = cc.map((a) => `${a.name} ${a.address}`).join(" ");
411
- try {
412
- this.db.prepare("INSERT INTO messages_fts (rowid, subject, from_name, from_address, to_text, cc_text, body_text) VALUES (?, ?, ?, ?, ?, ?, ?)").run(r.id, r.subject, r.from_name, r.from_address, toText, ccText, r.preview);
413
- count++;
465
+ const batchInsert = this.db.transaction(() => {
466
+ for (const r of rows) {
467
+ const to = JSON.parse(r.to_json || "[]");
468
+ const cc = JSON.parse(r.cc_json || "[]");
469
+ const toText = to.map((a) => `${a.name} ${a.address}`).join(" ");
470
+ const ccText = cc.map((a) => `${a.name} ${a.address}`).join(" ");
471
+ try {
472
+ insert.run(r.id, r.subject, r.from_name, r.from_address, toText, ccText, r.preview);
473
+ count++;
474
+ }
475
+ catch { /* skip duplicates */ }
414
476
  }
415
- catch { /* skip duplicates */ }
416
- }
477
+ });
478
+ batchInsert();
417
479
  return count;
418
480
  }
419
481
  // ── Sync Actions ──
@@ -1,19 +1,13 @@
1
1
  /**
2
2
  * File-per-message body storage backend.
3
- * Messages stored as: {basePath}/{accountId}/{folderName}/{uid}.eml
4
- * Legacy: also checks {basePath}/{accountId}/{folderId}/{uid}.eml
3
+ * Messages stored as: {basePath}/{accountId}/{folderId}/{uid}.eml
4
+ * Folder IDs are numeric (from SQLite), not names.
5
5
  */
6
6
  import type { MessageStore } from "@bobfrankston/mailx-types";
7
7
  export declare class FileMessageStore implements MessageStore {
8
8
  private basePath;
9
- private folderNames;
10
9
  constructor(basePath: string);
11
- /** Register folder ID → path mapping for human-readable directory names */
12
- registerFolder(folderId: number, folderPath: string): void;
13
- private folderDir;
14
10
  private messagePath;
15
- /** Check legacy path (numeric folder ID) */
16
- private legacyPath;
17
11
  putMessage(accountId: string, folderId: number, uid: number, raw: Buffer): Promise<string>;
18
12
  getMessage(accountId: string, folderId: number, uid: number): Promise<Buffer>;
19
13
  deleteMessage(accountId: string, folderId: number, uid: number): Promise<void>;
@@ -1,34 +1,17 @@
1
1
  /**
2
2
  * File-per-message body storage backend.
3
- * Messages stored as: {basePath}/{accountId}/{folderName}/{uid}.eml
4
- * Legacy: also checks {basePath}/{accountId}/{folderId}/{uid}.eml
3
+ * Messages stored as: {basePath}/{accountId}/{folderId}/{uid}.eml
4
+ * Folder IDs are numeric (from SQLite), not names.
5
5
  */
6
6
  import * as fs from "node:fs";
7
7
  import * as path from "node:path";
8
- /** Sanitize folder path for use as directory name — replace delimiters with _ */
9
- function sanitizeFolderName(folderPath) {
10
- return folderPath.replace(/[\/\\.:]/g, "_");
11
- }
12
8
  export class FileMessageStore {
13
9
  basePath;
14
- folderNames = new Map();
15
10
  constructor(basePath) {
16
11
  this.basePath = basePath;
17
12
  fs.mkdirSync(basePath, { recursive: true });
18
13
  }
19
- /** Register folder ID → path mapping for human-readable directory names */
20
- registerFolder(folderId, folderPath) {
21
- this.folderNames.set(folderId, sanitizeFolderName(folderPath));
22
- }
23
- folderDir(accountId, folderId) {
24
- const name = this.folderNames.get(folderId) || String(folderId);
25
- return path.join(this.basePath, accountId, name);
26
- }
27
14
  messagePath(accountId, folderId, uid) {
28
- return path.join(this.folderDir(accountId, folderId), `${uid}.eml`);
29
- }
30
- /** Check legacy path (numeric folder ID) */
31
- legacyPath(accountId, folderId, uid) {
32
15
  return path.join(this.basePath, accountId, String(folderId), `${uid}.eml`);
33
16
  }
34
17
  async putMessage(accountId, folderId, uid, raw) {
@@ -38,22 +21,15 @@ export class FileMessageStore {
38
21
  return filePath;
39
22
  }
40
23
  async getMessage(accountId, folderId, uid) {
41
- const filePath = this.messagePath(accountId, folderId, uid);
42
- if (fs.existsSync(filePath))
43
- return fs.readFileSync(filePath);
44
- // Fallback to legacy path
45
- const legacy = this.legacyPath(accountId, folderId, uid);
46
- return fs.readFileSync(legacy);
24
+ return fs.readFileSync(this.messagePath(accountId, folderId, uid));
47
25
  }
48
26
  async deleteMessage(accountId, folderId, uid) {
49
- for (const p of [this.messagePath(accountId, folderId, uid), this.legacyPath(accountId, folderId, uid)]) {
50
- if (fs.existsSync(p))
51
- fs.unlinkSync(p);
52
- }
27
+ const filePath = this.messagePath(accountId, folderId, uid);
28
+ if (fs.existsSync(filePath))
29
+ fs.unlinkSync(filePath);
53
30
  }
54
31
  async hasMessage(accountId, folderId, uid) {
55
- return fs.existsSync(this.messagePath(accountId, folderId, uid)) ||
56
- fs.existsSync(this.legacyPath(accountId, folderId, uid));
32
+ return fs.existsSync(this.messagePath(accountId, folderId, uid));
57
33
  }
58
34
  }
59
35
  //# sourceMappingURL=file-store.js.map
@@ -8,7 +8,8 @@ export type AuthMethod = "password" | "oauth2";
8
8
  /** Mail account configuration */
9
9
  export interface AccountConfig {
10
10
  id: string; /** Unique account identifier (e.g., "iecc", "gmail-bob") */
11
- name: string; /** Display name */
11
+ name: string; /** Sender name for From header (e.g., "Bob Frankston") */
12
+ label?: string; /** UI label for account list (e.g., "Gmail"). Falls back to name if not set */
12
13
  email: string; /** Email address */
13
14
  imap: {
14
15
  host: string;
@@ -28,6 +29,7 @@ export interface AccountConfig {
28
29
  password?: string;
29
30
  };
30
31
  enabled: boolean;
32
+ defaultSend?: boolean; /** Use this account's SMTP when From doesn't match any account */
31
33
  }
32
34
  /** Standard IMAP special-use folder types */
33
35
  export type SpecialUse = "inbox" | "sent" | "drafts" | "trash" | "junk" | "archive" | "all";