Repository navigation
v0.0.12
Key takeaways
- [Feature] Search inside email bodies: On the Messages page, searching now also matches words inside the email body, not just the subject and sender, for new mail, and older mail follows once the body pass is started by hand.
- [Feature] Attachment previews: In the message drawer's Attachments section, tapping an image, PDF or text file now opens a preview, and a new List / Grid toggle shows image thumbnails.
- [Improvement] Page buttons for groups: On the Messages page, with Group by set to Sender or Domain, groups now come in pages with previous and next buttons (such as
1–50 of 1,240) instead of a "More groups" row. - [Fix] Filter values while grouped: On the Messages page, the filter menu now lists its values (such as each Domain) when Group by is on, so you can filter a grouped view.
- [Improvement] Mailbox is the record: This affects how every mailbox stores and opens mail: each message's location is now kept in the mailbox itself, so syncs and backfills no longer wait on Basin write access and opening a message needs no Basin lookup.
App
- Attachment preview opens in a dialog over the message drawer.
- Images have previous/next buttons, ← → keys, swipe and a thumbnail strip.
- PDFs are drawn page by page.
- Text, CSV and JSON show as text.
- Any other file shows its name, size and a Download button.
- The Attachments section has a List / Grid toggle. The grid loads image thumbnails lazily.
- Group by Sender or Domain on the Messages page now pages its groups with previous/next buttons and a total count. Labels, Category and Read still show all their groups at once.
- With Group by on, the filter menu lists real values again. Previously it showed zero for Sender, Domain and the rest.
- In Panes, an empty tab (for example Labels on an imported mbox archive) keeps the tabs in place and shows "No labels in this mailbox" inside the pane. Senders, Domains and Time work the same way.
- An archive with no mail now says "Nothing is imported into yet." instead of mentioning the backfill.
- In Settings ▸ Accounts, Open Backfill on an mbox archive's row now closes Settings instead of leaving it open on top of Backfill.
- The "Waiting for Basin write access" card is gone.
Search
- Email bodies are now searchable through a body word index kept in each mailbox. The bodies themselves stay in the raw files.
- Each search word can match the subject, sender or body, so words can be split across subject and body.
- Messages that match only in the body are marked as body hits.
- A new snippets request returns the matching text and hit count for the messages on screen.
- The MCP tools get body search automatically, with no change on their side.
- Indexed text prefers the plain-text part and strips HTML only when there is no plain part. It skips attachments, cuts quoted replies, and caps at 16 KB per message.
- A body pass indexes mail that is already archived.
- It reads raw files in ID order from a saved bookmark.
- It reads each pack once, or only the first 256 KB of a large message.
- It waits for the daily write guard between runs.
- It does not start on deploy. Someone starts it by hand once approved.
Sync
- Backfill copy, the 6-hourly sync and mbox import now index each batch straight into the mailbox as they copy, behind the daily write check.
- New mail gets its body text indexed in the same step.
- Syncs and backfills no longer wait for a Basin token, and the
basin_not_readyerror is gone. - The month committer now only lands months. The path for rows staged earlier is removed.
- Live sync still drains the one old queued file so it gets indexed.
Storage
- Each mailbox now holds every message's row plus the file, offset and length of its raw bytes.
- Opening a message is one mailbox read plus one ranged read of its file. If a location is missing, it falls back to the single raw file.
- Raw files are grouped into packs: 25 messages under 128 KB, 8 up to 2 MB, and larger messages alone.
- All 122,348 copied messages were located before the Basin code was removed, and sample opens succeeded.
- The Basin code, its helper pieces and the Parquet/Iceberg packages are removed.
- Deleting Basin's tables, catalog data and token is a separate step that waits for approval.
Infra
- The project is prepared to go public under an MIT license. Repository visibility is unchanged.
- The README now credits msgvault (Wes McKinney, MIT) and describes the architecture and measured costs. It notes that the costs came from the earlier version, which wrote more to R2.
- The setup guide and example variables now need only the R2 bucket (
ARCHIVE_BUCKET). R2 Data Catalog,BASIN_TOKEN, the catalog URI and the warehouse are no longer needed. - Deploy config no longer holds personal values (account ID, route, Access or admin settings). The live Worker keeps its current variables and its custom domain.
- CI and the release dry run skip fork pull requests, so outside code never runs on the self-hosted runner.
- Attachment previews are served inline only for images (not SVG), PDFs and text. They are sandboxed with a strict Content-Security-Policy and
nosniff. Every other type stays a download. - Previews cost no mailbox reads or writes, and responses are cached privately for a day.
Pull requests (10)
- #123 Search inside email bodies: body word index, body pass, snippets (@bchoor)
- #122 README and setup guide: the mailbox is the record, no Basin (@bchoor)
- #121 Remove Basin: the mailbox DO is the record (@bchoor)
- #120 Mailbox is the record: copy indexes straight into the DO (@bchoor)
- #119 Open source prep: MIT license, README, setup guide, no personal values in config (@bchoor)
- #118 Messages: page buttons for groups (@bchoor)
- #117 Panes: keep the tabs when a tab is empty (@bchoor)
- #116 Messages: filter values with Group by on (@bchoor)
- #115 Message drawer: preview attachments (images, PDFs, text) with a grid view (@bchoor)
- #114 Open Backfill from an archive's row closes Settings (@bchoor)
Full changelog: v0.0.11...v0.0.12