@bobfrankston/rmfmail 1.2.263 → 1.2.270
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/TODO.md +1 -0
- package/client/android-bootstrap.bundle.js +34 -1
- package/client/android-bootstrap.bundle.js.map +2 -2
- package/client/app.bundle.js +54 -108
- package/client/app.bundle.js.map +3 -3
- package/client/app.js +59 -116
- package/client/app.js.map +1 -1
- package/client/app.ts +64 -93
- package/client/components/message-list.js +18 -3
- package/client/components/message-list.js.map +1 -1
- package/client/components/message-list.ts +18 -3
- package/client/components/message-viewer.js +14 -4
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +13 -3
- package/client/compose/compose.bundle.js +17 -6
- package/client/compose/compose.bundle.js.map +2 -2
- package/client/compose/compose.js +13 -7
- package/client/compose/compose.js.map +1 -1
- package/client/compose/compose.ts +13 -5
- package/client/lib/rmf-tiny.js +15 -1
- package/client/package.json +1 -1
- package/client/styles/components.css +9 -0
- package/docs/thundermail-jmap.md +291 -0
- package/package.json +11 -11
- package/packages/mailx-imap/index.d.ts.map +1 -1
- package/packages/mailx-imap/index.js +17 -1
- package/packages/mailx-imap/index.js.map +1 -1
- package/packages/mailx-imap/index.ts +17 -1
- package/packages/mailx-imap/package-lock.json +2 -2
- package/packages/mailx-imap/package.json +1 -1
- package/packages/mailx-settings/docs/thundermail-jmap.md +291 -0
- package/packages/mailx-settings/index.d.ts +1 -0
- package/packages/mailx-settings/index.d.ts.map +1 -1
- package/packages/mailx-settings/index.js +1 -0
- package/packages/mailx-settings/index.js.map +1 -1
- package/packages/mailx-settings/index.ts +1 -0
- package/packages/mailx-settings/package.json +1 -1
- package/packages/mailx-store/package.json +1 -1
- package/packages/mailx-store-web/package.json +1 -1
- package/packages/mailx-store-web/web-settings.d.ts +1 -0
- package/packages/mailx-store-web/web-settings.d.ts.map +1 -1
- package/packages/mailx-store-web/web-settings.js +1 -0
- package/packages/mailx-store-web/web-settings.js.map +1 -1
- package/packages/mailx-store-web/web-settings.ts +1 -0
- package/packages/mailx-types/index.d.ts +59 -1
- package/packages/mailx-types/index.d.ts.map +1 -1
- package/packages/mailx-types/index.js +72 -0
- package/packages/mailx-types/index.js.map +1 -1
- package/packages/mailx-types/index.ts +80 -1
- package/packages/mailx-types/package.json +1 -1
- /package/packages/mailx-imap/{node_modules.npmglobalize-stash-88864 → node_modules.npmglobalize-stash-18100}/.package-lock.json +0 -0
package/TODO.md
CHANGED
|
@@ -228,6 +228,7 @@ Items blocked on a design decision. Short-form question here; full context in th
|
|
|
228
228
|
| **C128** | OPEN | **Body pre-parse on prefetch** — first click on any unviewed message pays `simpleParser` + `sanitizeHtml` cost (~100–500 ms on rich HTML). The parsedCache (added 2026-05-09) eliminates 2nd-and-later view costs but not the first. Fix: extend prefetch to ALSO parse + sanitize the body during background fetch and store the result alongside the .eml (e.g., `<uuid>.parsed.json` next to `<uuid>.eml`, or a `body_html_cached` column). Click-time path reads pre-parsed JSON, no parser invocation. Touches `mailx-imap/index.ts` prefetch path + `mailx-store/file-store.ts` for the parsed-blob storage. |
|
|
229
229
|
| **C129** | OPEN | **Android prod/dev split via filename/URL channel** — User 2026-05-09 (revised): no separate MAUI project. Same source tree builds; output filenames distinguish channels: Phase 1 (start now) writes `rmfmaildev.apk` alongside today's `mailx-maui.apk`. Phase 2 (when a release is declared) switches to `rmfmail-<version>.apk` versioned + `rmfmaildev.apk` for latest, with promotion = re-pointing `rmfmail.apk` at a chosen version. Single APK contents per build; channel is runtime setting in AppUpdater (Settings toggle for which URL to poll). Side-by-side install on one device NOT supported by this design (single Android package id) — that's a separate need. See `docs/prod-android.md` for full plan. Phase 1 ~30 min; full flow ~2.5 hours when activated. |
|
|
230
230
|
| **C130** | OPEN | **Reset prefetch error budget after fresh sync** — Android: `errors`/`failedThisSession` accumulate within a prefetch session. Already resets on next syncAll cycle (since each `prefetchBodies(account)` call is fresh). Verify this works in practice via logit; if a long sync session burns through budget and stays stuck, add an explicit reset on `bodyAvailable` events that fire while prefetch is still running. |
|
|
231
|
+
| **C164** | RESEARCHED | **Thundermail / JMAP provider** — full protocol survey at [`docs/thundermail-jmap.md`](thundermail-jmap.md), probed live 2026-08-17. Thundermail is Stalwart, so there is no proprietary API: IMAP 993 / SMTP 465 work **today with zero code** (an `accounts.jsonc` entry and nothing else), CardDAV `/dav/card` + CalDAV `/dav/cal` are http-basic, and JMAP is live at `https://mail.thundermail.com/jmap/` advertising core / mail / submission / calendars / contacts / filenode / sieve / quota plus **WebSocket push** (`supportsPush: true`). JMAP is the attractive bet: it kills the IDLE lane, the 5-lane connection semaphore and the Dovecot 20-conn ceiling, needs no transport injection (one path for Android and desktop, cf. C125), and `Email/changes` is native set-difference sync. **From address: resolved — good.** The 15-alias cap is `@thundermail.com`/`@tb.pro` only; custom domains get unlimited aliases plus a catch-all (empty-name alias), and with catch-all on you can send from any prefix unregistered — their own example is the per-vendor pattern already used on `bob.ma`. mailx needs ~nothing here (per-message From identity shipped v1.2.201); only Stalwart-side `MAIL FROM`/DKIM validation for an unregistered prefix is untested. **Still blocking/staged:** JMAP-calendars and `filenode` are unratified drafts; OAuth `scopes_supported` covers mail only (no calendars/contacts scope); invite-only beta so there is nothing to test against; and **no Drive equivalent** — Thunderbird Send is one-shot file *sharing*, not a listable revisable store, so mailx's shared-config dependency (`accounts.jsonc` / `contacts.jsonc` / preferences / allowlist on GDrive) has no home. **C161 is therefore the prerequisite, not JMAP** — the `_rmfmail` hidden-IMAP-folder state channel removes the Drive dependency for every account type at once and keeps working unchanged if JMAP lands later. Until C161 ships, adopting Thundermail is a half-migration that trades a Google dependency for a Thunderbird one. |
|
|
231
232
|
|
|
232
233
|
<a id="concerns"></a>
|
|
233
234
|
|
|
@@ -2572,6 +2572,7 @@ __export(mailx_types_exports, {
|
|
|
2572
2572
|
answeredOf: () => answeredOf,
|
|
2573
2573
|
buildMimeMessage: () => buildMimeMessage,
|
|
2574
2574
|
deletedOf: () => deletedOf,
|
|
2575
|
+
displayNameClaimsOtherAddress: () => displayNameClaimsOtherAddress,
|
|
2575
2576
|
draftOf: () => draftOf,
|
|
2576
2577
|
encodeAddressHeader: () => encodeAddressHeader,
|
|
2577
2578
|
encodeHeaderWord: () => encodeHeaderWord,
|
|
@@ -2580,8 +2581,10 @@ __export(mailx_types_exports, {
|
|
|
2580
2581
|
extractAddress: () => extractAddress,
|
|
2581
2582
|
extractInlineImages: () => extractInlineImages,
|
|
2582
2583
|
flaggedOf: () => flaggedOf,
|
|
2584
|
+
formatSender: () => formatSender,
|
|
2583
2585
|
htmlToPlainText: () => htmlToPlainText,
|
|
2584
2586
|
isAddressToken: () => isAddressToken,
|
|
2587
|
+
isJunkPreviewText: () => isJunkPreviewText,
|
|
2585
2588
|
mergeReminderStates: () => mergeReminderStates,
|
|
2586
2589
|
normalizeReminderState: () => normalizeReminderState,
|
|
2587
2590
|
parseSearchQuery: () => parseSearchQuery,
|
|
@@ -2844,6 +2847,35 @@ function parseSearchQuery(query) {
|
|
|
2844
2847
|
}
|
|
2845
2848
|
return { conditions, params };
|
|
2846
2849
|
}
|
|
2850
|
+
function isJunkPreviewText(s) {
|
|
2851
|
+
const t = (s || "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
2852
|
+
if (!t)
|
|
2853
|
+
return true;
|
|
2854
|
+
return t === "undefined" || t === "null" || t === "nan" || t === "[object object]";
|
|
2855
|
+
}
|
|
2856
|
+
function displayNameClaimsOtherAddress(name, address) {
|
|
2857
|
+
const n = (name || "").trim();
|
|
2858
|
+
if (!n)
|
|
2859
|
+
return null;
|
|
2860
|
+
const real = (address || "").trim().toLowerCase();
|
|
2861
|
+
const m = n.match(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g);
|
|
2862
|
+
if (!m)
|
|
2863
|
+
return null;
|
|
2864
|
+
for (const claimed of m) {
|
|
2865
|
+
if (claimed.toLowerCase() !== real)
|
|
2866
|
+
return claimed;
|
|
2867
|
+
}
|
|
2868
|
+
return null;
|
|
2869
|
+
}
|
|
2870
|
+
function formatSender(addr) {
|
|
2871
|
+
const address = (addr?.address || "").trim();
|
|
2872
|
+
const name = (addr?.name || "").trim();
|
|
2873
|
+
if (!name)
|
|
2874
|
+
return { text: address, claimed: null };
|
|
2875
|
+
if (name.toLowerCase() === address.toLowerCase())
|
|
2876
|
+
return { text: address, claimed: null };
|
|
2877
|
+
return { text: `${name} <${address}>`, claimed: displayNameClaimsOtherAddress(name, address) };
|
|
2878
|
+
}
|
|
2847
2879
|
var _SEEN, _FLAGGED, _ANSWERED, _DRAFT, _DELETED, seenOf, flaggedOf, answeredOf, draftOf, deletedOf, setSeen, setFlagged, setAnswered, setDraft, toggleSeen, toggleFlagged;
|
|
2848
2880
|
var init_mailx_types = __esm({
|
|
2849
2881
|
"packages/mailx-types/index.js"() {
|
|
@@ -3440,7 +3472,8 @@ var init_web_settings = __esm({
|
|
|
3440
3472
|
editor: "quill",
|
|
3441
3473
|
folderWidth: 220,
|
|
3442
3474
|
listViewerSplit: 40,
|
|
3443
|
-
fontSize: 15
|
|
3475
|
+
fontSize: 15,
|
|
3476
|
+
composeFontSize: 20
|
|
3444
3477
|
},
|
|
3445
3478
|
sync: {
|
|
3446
3479
|
intervalMinutes: 5,
|