@bobfrankston/mailx-store 0.1.28 → 0.1.30
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/db.d.ts +9 -3
- package/db.js +20 -10
- package/package.json +5 -5
- package/store.js +2 -2
package/db.d.ts
CHANGED
|
@@ -259,9 +259,15 @@ export declare class MailxDB {
|
|
|
259
259
|
/** Backfill the FTS5 `body_text` column for a message after its body
|
|
260
260
|
* has been parsed. Capped at ~64 KB of text per row — FTS5 stores the
|
|
261
261
|
* raw text and indexes tokens; we don't need every byte of a 1 MB
|
|
262
|
-
* marketing email to find a word in the first paragraph.
|
|
263
|
-
*
|
|
264
|
-
|
|
262
|
+
* marketing email to find a word in the first paragraph.
|
|
263
|
+
*
|
|
264
|
+
* Keyed on the FTS rowid (= messages.id) directly. The earlier
|
|
265
|
+
* (account, folder_id, uid) lookup keyed on the LEGACY messages.folder_id
|
|
266
|
+
* column — a message can live in several folders via message_folders,
|
|
267
|
+
* so that lookup could miss the row entirely and silently leave the
|
|
268
|
+
* body un-indexed (Bob 2026-05-18: "mcdade" in an opened message's
|
|
269
|
+
* body, search found nothing). */
|
|
270
|
+
updateFtsBody(rowId: number, bodyText: string): void;
|
|
265
271
|
/** List view: messages currently in (account, folder).
|
|
266
272
|
* Joins through `message_folders` so the UID + folder location come
|
|
267
273
|
* from membership rows, not from the legacy messages.folder_id /
|
package/db.js
CHANGED
|
@@ -1355,13 +1355,18 @@ export class MailxDB {
|
|
|
1355
1355
|
// quoted-strings (RFC-strictly forbidden, common in the wild). Run
|
|
1356
1356
|
// libmime over Subject and every address display name once; safe
|
|
1357
1357
|
// to call on already-decoded text (no `=?...?=` markers → no-op).
|
|
1358
|
+
// The `address` is decoded too: a legit address never carries an
|
|
1359
|
+
// encoded-word, so it's a no-op there — but spam sometimes packs the
|
|
1360
|
+
// whole `name <addr>` into the mailbox local-part as one encoded
|
|
1361
|
+
// word (`=?utf-8?q?...=3C...=40...=3E?=@host`). Decoding it at least
|
|
1362
|
+
// renders readable text instead of raw `=3C`/`=C3=A9` gibberish.
|
|
1358
1363
|
msg.subject = decodeHeaderWords(msg.subject);
|
|
1359
1364
|
if (msg.from)
|
|
1360
|
-
msg.from = { name: decodeHeaderWords(msg.from.name || ""), address: msg.from.address || "" };
|
|
1365
|
+
msg.from = { name: decodeHeaderWords(msg.from.name || ""), address: decodeHeaderWords(msg.from.address || "") };
|
|
1361
1366
|
if (msg.to)
|
|
1362
|
-
msg.to = msg.to.map(a => ({ name: decodeHeaderWords(a.name || ""), address: a.address || "" }));
|
|
1367
|
+
msg.to = msg.to.map(a => ({ name: decodeHeaderWords(a.name || ""), address: decodeHeaderWords(a.address || "") }));
|
|
1363
1368
|
if (msg.cc)
|
|
1364
|
-
msg.cc = msg.cc.map(a => ({ name: decodeHeaderWords(a.name || ""), address: a.address || "" }));
|
|
1369
|
+
msg.cc = msg.cc.map(a => ({ name: decodeHeaderWords(a.name || ""), address: decodeHeaderWords(a.address || "") }));
|
|
1365
1370
|
const existing = this.db.prepare("SELECT id, provider_id FROM messages WHERE account_id = ? AND folder_id = ? AND uid = ?").get(msg.accountId, msg.folderId, msg.uid);
|
|
1366
1371
|
if (existing) {
|
|
1367
1372
|
// Backfill provider_id on existing rows that predate this column —
|
|
@@ -1496,15 +1501,20 @@ export class MailxDB {
|
|
|
1496
1501
|
/** Backfill the FTS5 `body_text` column for a message after its body
|
|
1497
1502
|
* has been parsed. Capped at ~64 KB of text per row — FTS5 stores the
|
|
1498
1503
|
* raw text and indexes tokens; we don't need every byte of a 1 MB
|
|
1499
|
-
* marketing email to find a word in the first paragraph.
|
|
1500
|
-
*
|
|
1501
|
-
|
|
1504
|
+
* marketing email to find a word in the first paragraph.
|
|
1505
|
+
*
|
|
1506
|
+
* Keyed on the FTS rowid (= messages.id) directly. The earlier
|
|
1507
|
+
* (account, folder_id, uid) lookup keyed on the LEGACY messages.folder_id
|
|
1508
|
+
* column — a message can live in several folders via message_folders,
|
|
1509
|
+
* so that lookup could miss the row entirely and silently leave the
|
|
1510
|
+
* body un-indexed (Bob 2026-05-18: "mcdade" in an opened message's
|
|
1511
|
+
* body, search found nothing). */
|
|
1512
|
+
updateFtsBody(rowId, bodyText) {
|
|
1513
|
+
if (!rowId)
|
|
1514
|
+
return;
|
|
1502
1515
|
try {
|
|
1503
|
-
const row = this.db.prepare("SELECT id FROM messages WHERE account_id = ? AND folder_id = ? AND uid = ?").get(accountId, folderId, uid);
|
|
1504
|
-
if (!row)
|
|
1505
|
-
return;
|
|
1506
1516
|
const capped = bodyText.length > 64_000 ? bodyText.slice(0, 64_000) : bodyText;
|
|
1507
|
-
this.db.prepare("UPDATE messages_fts SET body_text = ? WHERE rowid = ?").run(capped,
|
|
1517
|
+
this.db.prepare("UPDATE messages_fts SET body_text = ? WHERE rowid = ?").run(capped, rowId);
|
|
1508
1518
|
}
|
|
1509
1519
|
catch { /* FTS update is best-effort */ }
|
|
1510
1520
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-store",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
13
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
12
|
+
"@bobfrankston/mailx-types": "^0.1.17",
|
|
13
|
+
"@bobfrankston/mailx-settings": "^0.1.20",
|
|
14
14
|
"@bobfrankston/mailx-bus": "^0.1.2",
|
|
15
15
|
"mailparser": "^3.7.2"
|
|
16
16
|
},
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
".transformedSnapshot": {
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
33
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
32
|
+
"@bobfrankston/mailx-types": "^0.1.17",
|
|
33
|
+
"@bobfrankston/mailx-settings": "^0.1.20",
|
|
34
34
|
"@bobfrankston/mailx-bus": "^0.1.2",
|
|
35
35
|
"mailparser": "^3.7.2"
|
|
36
36
|
}
|
package/store.js
CHANGED
|
@@ -305,9 +305,9 @@ export class Store {
|
|
|
305
305
|
// backfill, searches miss any word that only appears deeper in the
|
|
306
306
|
// body. Fire-and-forget — failures are non-fatal, never block the
|
|
307
307
|
// user's preview render.
|
|
308
|
-
if (bodyText) {
|
|
308
|
+
if (bodyText && envelope.id) {
|
|
309
309
|
try {
|
|
310
|
-
this.db.
|
|
310
|
+
this.db.updateFtsBody(envelope.id, bodyText);
|
|
311
311
|
}
|
|
312
312
|
catch { /* */ }
|
|
313
313
|
}
|