Commit log

6684bd6 fix: SMTP HELO hostname (#1284)

Click to expand commit body
## What?

Fixes #1084 by using the local OS hostname for the SMTP `HELO`/`EHLO`
greeting instead of always sending `localhost`.

Both normal message sending and calendar replies now call a shared
helper that returns `os.Hostname()` when available, with `localhost`
kept as the fallback for hostname lookup failures or empty hostnames.

## Why?

Some SMTP anti-spam checks reject or penalize public clients that
identify as `localhost`. Sending the real client hostname matches the
issue's requested behavior while preserving a safe fallback if hostname
lookup is unavailable.

---------

Signed-off-by: Nanook <nanookclaw@users.noreply.github.com>

nanookclaw created

1b72ab2 test: check daemon unmarshal errors (#1296)

Click to expand commit body
## What?

- Check JSON unmarshal errors in daemon handler tests.
- Fail clearly when a response body cannot be decoded instead of
ignoring the error.
- Keep the change limited to daemon tests.

## Why?

Ignoring `json.Unmarshal` errors can let malformed test responses pass
into later assertions with less useful failures. This makes the daemon
tests report decode problems at the source.

Fixes #718

mehmet turac created

4876a93 fix: mailing-list addresses in a slice (#1277)

Click to expand commit body
## What?

`SearchContacts` builds mailing-list virtual contacts by jamming
`strings.Join(list.Addresses, ", ")` into `Contact.Email`. That breaks
the field's single-address invariant: `normalizeContactEmail` lowercases
and trims commas off the joined string (corrupting the data), and any
exact-match lookup against the contact will never find it.

This adds a dedicated `Addresses []string` field to `Contact`, populates
it for mailing-list virtual contacts, and leaves `Email` empty so the
invariant holds. The composer learns to detect mailing lists via
`len(selected.Addresses) > 0` instead of "does the email field contain a
comma", joins the addresses at insertion time, and renders the
suggestion as `Name (addr1, addr2, ...)` so it's clear that a single
suggestion expands to multiple recipients.

The cache file format is backwards-compatible: the new field is
`omitempty`, and saved contacts (added via `AddContact`) never carry
`Addresses` because they're built from a single email parameter.
Mailing-list virtual contacts are constructed in-memory on every search
and never written to disk.

## Why?

Closes #1123. The reporter pointed out the data-integrity bug; this
implements option 2 of the two fixes they suggested (dedicated
`Addresses` slice, keep `Email` empty), which is the smaller of the two
and doesn't require a separate "virtual contact" type.

Matt Van Horn created

86dbe96 feat: in-memory LRU email body cache (#1281)

Click to expand commit body
## What?

Replaces the disk-only email body cache with an in-memory LRU cache
backed by write-through disk persistence.

- Single global LRU instance shared across all folders via `sync.Once`
singleton.
- Fast `Get()` and `Put()` operations — `O(1)` via hashmap +
doubly-linked list.
- Write-through: every `Get()` and `Put()` immediately persists to disk,
so no data is lost on crash.
- Eviction removes least-recently-used entries from both memory and disk
atomically.
- On the first `GetLRUInstance()` call, `LoadFromDisk()` restores LRU
order using `LastAccessedAt` timestamps sorted oldest-first, so the most
recently accessed email ends up at the front.

## Why?

The previous disk-only approach had two bottlenecks:
`GetCachedEmailBody()` read the entire folder JSON file on every call,
and `pruneEmailBodyCacheSize()` loaded all folder files on every
`SaveEmailBody()` call. With multiple accounts and many folders, this
becomes expensive.

Related #1171

Mohamed Mahmoud created

b6cdc83 fix(clib): escape markdown fallback (#1290)

Click to expand commit body
## What?

Adds a safe HTML fallback for Markdown conversion failures. When
`MarkdownToHTML` fails in either the cgo `md4c` path or the no-cgo
`goldmark` path, it now logs the failure and returns escaped plain text
wrapped in `<pre>` instead of returning raw Markdown bytes.

Also adds a focused test for the fallback escaping behavior.

## Why?

Closes #571

Previously, failed Markdown conversion returned the original Markdown
bytes. The email viewer then tried to parse those raw bytes as HTML,
which could render poorly and treat HTML-looking plain text as markup.

The new fallback keeps failed conversions readable in the HTML viewer
while escaping unsafe HTML-like input.

FromSi created

b68b88c fix: nix pkgs bump

Drew Smirnoff created

6e2d9e7 fix: nixpkgs bump (#1294)

Drew Smirnoff created

af72aaa ci: nixpkgs-bump staging sync (#1294)

Drew Smirnoff created

bcf6ecc ci: correct nix pr bump (#1294)

Click to expand commit body
## What?

Fixes vendor hash problem

## Why?

Workflow failing

Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

c4cfeeb docs: update demo.gif (#1288)

Floatpane Bot created

71ff42b docs: update feature screenshots (#1289)

Floatpane Bot created

e23b193 ci: nixpkgs-bump.yml token

Drew Smirnoff created

626ddee chore: update flake.lock (#1286)

Floatpane Bot created

e5aa910 chore: sync gomod2nix.toml (#1287)

Floatpane Bot created

ddf3a5e feat: maildir support (#1283)

Click to expand commit body
## What?

Adds a new `maildir` protocol to matcha's backend registry so accounts
can point at a local Maildir tree on disk instead of an IMAP/JMAP/POP3
server. After picking the protocol in the add-account wizard and
supplying a path (e.g. `~/Mail` or `/var/mail/user`), the inbox renders
messages parsed directly from the filesystem, alongside any existing
remote accounts. The implementation honors the standard Maildir layout —
top-level `cur/new/tmp` is treated as INBOX, and Maildir++ dot-prefixed
siblings (`.Sent`, `.Archive`, `.Drafts`, …) surface as additional
folders. Reading a folder promotes anything sitting in `new/` over to
`cur/` (matching mutt's semantics), marking a message as read appends
the `S` flag to its filename, deletion unlinks the file, and
move/archive shuffle entries between Maildir folders using the
emersion/go-maildir library's atomic operations. Server-side search is
implemented as a local header/body scan, which is plenty fast on a local
FS. Sending email and IDLE-style push notifications are unsupported and
return `backend.ErrNotSupported`, since a Maildir is just a directory —
no transport, no event channel. The `Capabilities()` report reflects
this so the UI can dim send actions, and a `CanArchive` bit flips on
automatically when a `.Archive` folder exists in the tree.

## Why?

Closes #1183 
Closes #1140

---------

Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

cb1e7d8 chore(deps): cachix/install-nix-action ^ v31.10.6 (#1285)

Click to expand commit body
## What?

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[cachix/install-nix-action](https://redirect.github.com/cachix/install-nix-action)
| action | major | `v30` → `v31` |

---

### Release Notes

<details>
<summary>cachix/install-nix-action (cachix/install-nix-action)</summary>

###
[`v31.10.6`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.6)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.10.5...v31.10.6)

#### What's Changed

- nix: 2.34.6 -> 2.34.7 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;275](https://redirect.github.com/cachix/install-nix-action/pull/275)

**[GHSA-vh5x-56v6-4368](https://redirect.github.com/NixOS/nix/security/advisories/GHSA-vh5x-56v6-4368)**:
Fixes a coroutine stack-to-heap overflow via unbounded recursion in the
NAR directory parser. **Severity: High.**

**[GHSA-gr92-w2r5-qw5p](https://redirect.github.com/NixOS/nix/security/advisories/GHSA-gr92-w2r5-qw5p)**:
Fixes an absolute path traversal vulnerability when unpacking archives
to disk. Severity: Moderate.

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.10.6>

###
[`v31.10.5`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.5)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.10.4...v31.10.5)

#### What's Changed

- nix: 2.34.5 -> 2.34.6 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;274](https://redirect.github.com/cachix/install-nix-action/pull/274)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.10.5>

###
[`v31.10.4`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.4)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.10.3...v31.10.4)

#### What's Changed

- nix: 2.34.4 -> 2.34.5 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;273](https://redirect.github.com/cachix/install-nix-action/pull/273)
**\[SECURITY]** Fixes a root privilege escalation vulnerability via
sandbox escape
<https://github.com/NixOS/nix/security/advisories/GHSA-g3g9-5vj6-r3gj>

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.10.3...v31.10.4>

###
[`v31.10.3`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.3)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.10.2...v31.10.3)

#### What's Changed

- nix: 2.34.2 -> 2.34.4 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;271](https://redirect.github.com/cachix/install-nix-action/pull/271)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.10.3>

###
[`v31.10.2`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.2)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.10.1...v31.10.2)

#### What's Changed

- nix: 2.34.1 -> 2.34.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;270](https://redirect.github.com/cachix/install-nix-action/pull/270)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.10.2>

###
[`v31.10.1`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.1)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.10.0...v31.10.1)

#### What's Changed

- nix: 2.34.0 -> 2.34.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;269](https://redirect.github.com/cachix/install-nix-action/pull/269)
Fixes a bug introduced in 2.34.0 that made the Nix daemon fail to load
authentication keys configured by `cachix-action`.

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.10.0...v31.10.1>

###
[`v31.10.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.10.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.9.1...v31.10.0)

#### What's Changed

- nix: 2.33.3 -> 2.34.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;267](https://redirect.github.com/cachix/install-nix-action/pull/267)
Release notes: <https://discourse.nixos.org/t/nix-2-34-0-released/75818>

⚠️ Nix 2.34.0 contains a regression that, under certain scenarios (a
`trusted-user` + a client-side `netrc-file`), breaks authentication with
private caches that rely on `netrc` files. This regression affects
`cachix/cachix-action`.

**UPD: 2.34.1 has been released with a patch for the authentication
issue**

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.9.1...v31.10.0>

###
[`v31.9.1`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.9.1)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.9.0...v31.9.1)

#### What's Changed

- nix: 2.33.0 -> 2.33.3 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;266](https://redirect.github.com/cachix/install-nix-action/pull/266)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.9.1>

###
[`v31.9.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.9.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.8.4...v31.9.0)

#### What's Changed

- nix: 2.32.4 -> 2.33.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;264](https://redirect.github.com/cachix/install-nix-action/pull/264)
- chore(deps): bump peter-evans/create-pull-request from 7 to 8 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;263](https://redirect.github.com/cachix/install-nix-action/pull/263)
- chore(deps): bump actions/checkout from 5 to 6 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;262](https://redirect.github.com/cachix/install-nix-action/pull/262)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.8.4...v31.9.0>

###
[`v31.8.4`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.8.4)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.8.3...v31.8.4)

#### What's Changed

- nix: 2.32.3 -> 2.32.4 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;261](https://redirect.github.com/cachix/install-nix-action/pull/261)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.8.3...v31.8.4>

###
[`v31.8.3`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.8.3)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.8.2...v31.8.3)

#### What's Changed

- nix: 2.32.2 -> 2.32.3 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;260](https://redirect.github.com/cachix/install-nix-action/pull/260)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.8.2...v31.8.3>

###
[`v31.8.2`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.8.2)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.8.1...v31.8.2)

#### What's Changed

- nix: 2.32.1 -> 2.32.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;259](https://redirect.github.com/cachix/install-nix-action/pull/259)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.8.1...v31.8.2>

###
[`v31.8.1`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.8.1)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.8.0...v31.8.1)

#### What's Changed

- nix: 2.32.0 -> 2.32.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;258](https://redirect.github.com/cachix/install-nix-action/pull/258)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.8.1>

###
[`v31.8.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.8.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.7.0...v31.8.0)

#### What's Changed

- nix: 2.31.2 -> 2.32.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;257](https://redirect.github.com/cachix/install-nix-action/pull/257)
Release notes: <https://discourse.nixos.org/t/nix-2-32-0-released/70528>

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.7.0...v31.8.0>

###
[`v31.7.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.7.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.6.2...v31.7.0)

#### What's Changed

- feat: set up the environment based on the installer shell scripts by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;251](https://redirect.github.com/cachix/install-nix-action/pull/251)

  Configures the following environment variables:

  - `NIX_PROFILES`
  - `NIX_SSL_CERT_FILE` (if not set)

  Adds the bin directory from the user's profile to `$PATH`.

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.6.2...v31.7.0>

###
[`v31.6.2`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.6.2)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.6.1...v31.6.2)

#### What's Changed

- nix: 2.31.1 -> 2.31.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;256](https://redirect.github.com/cachix/install-nix-action/pull/256)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.6.2>

###
[`v31.6.1`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.6.1)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.6.0...v31.6.1)

#### What's Changed

- ci: adjust oldest supported installer for macos-15 by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;252](https://redirect.github.com/cachix/install-nix-action/pull/252)
- nix: 2.31.0 -> 2.31.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;253](https://redirect.github.com/cachix/install-nix-action/pull/253)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.6.1>

###
[`v31.6.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.6.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.5.2...v31.6.0)

#### What's Changed

- chore(deps): bump actions/checkout from 4 to 5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;249](https://redirect.github.com/cachix/install-nix-action/pull/249)
- docs: add example for `nix develop` by
[@&#8203;jennydaman](https://redirect.github.com/jennydaman) in
[#&#8203;248](https://redirect.github.com/cachix/install-nix-action/pull/248)
- nix: 2.30.2 -> 2.31.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;250](https://redirect.github.com/cachix/install-nix-action/pull/250)
Release notes: <https://discourse.nixos.org/t/nix-2-31-0-released/68465>

#### New Contributors

- [@&#8203;jennydaman](https://redirect.github.com/jennydaman) made
their first contribution in
[#&#8203;248](https://redirect.github.com/cachix/install-nix-action/pull/248)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.5.2...v31.6.0>

###
[`v31.5.2`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.5.2)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.5.1...v31.5.2)

#### What's Changed

- nix: 2.30.1 -> 2.30.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;246](https://redirect.github.com/cachix/install-nix-action/pull/246)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31...v31.5.2>

###
[`v31.5.1`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.5.1)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.5.0...v31.5.1)

#### What's Changed

- nix: 2.30.0 -> 2.30.1 by
[@&#8203;xokdvium](https://redirect.github.com/xokdvium) in
[#&#8203;245](https://redirect.github.com/cachix/install-nix-action/pull/245)
**\[SECURITY]** Builds with Nix 2.30.0 on macOS were executed with
elevated privileges (root), instead of the build users.
<https://github.com/NixOS/nix/security/advisories/GHSA-qc7j-jgf3-qmhg>

#### New Contributors

- [@&#8203;xokdvium](https://redirect.github.com/xokdvium) made their
first contribution in
[#&#8203;245](https://redirect.github.com/cachix/install-nix-action/pull/245)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.5.0...v31.5.1>

###
[`v31.5.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.5.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.4.1...v31.5.0)

#### What's Changed

- nix: 2.29.1 -> 2.30.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[#&#8203;244](https://redirect.github.com/cachix/install-nix-action/pull/244)
Release notes:
<https://nix.dev/manual/nix/2.30/release-notes/rl-2.30.html>

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.4.1...v31.5.0>

###
[`v31.4.1`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.4.1)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.4.0...v31.4.1)

#### What's Changed

- nix: 2.29.0 -> 2.29.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[#&#8203;243](https://redirect.github.com/cachix/install-nix-action/pull/243)
**\[SECURITY]**
<https://discourse.nixos.org/t/security-advisory-privilege-escalations-in-nix-lix-and-guix/66017>

#### New Contributors

- [@&#8203;github-actions](https://redirect.github.com/github-actions)
made their first contribution in
[#&#8203;243](https://redirect.github.com/cachix/install-nix-action/pull/243)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.4.0...v31.4.1>

###
[`v31.4.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.4.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.3.0...v31.4.0)

#### What's Changed

- nix: 2.28.3 -> 2.29.0 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;239](https://redirect.github.com/cachix/install-nix-action/pull/239)
  Release notes: <https://nix.dev/manual/nix/2.29/release-notes/rl-2.29>
- Automate nix updates in CI by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;241](https://redirect.github.com/cachix/install-nix-action/pull/241)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.3.0...v31.4.0>

###
[`v31.3.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.3.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.2.0...v31.3.0)

#### What's Changed

- feat: Pin actions to hashes by
[@&#8203;l0b0](https://redirect.github.com/l0b0) in
[#&#8203;201](https://redirect.github.com/cachix/install-nix-action/pull/201)
- chore(deps): bump actions/checkout from 4.1.1 to 4.2.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[#&#8203;234](https://redirect.github.com/cachix/install-nix-action/pull/234)
- docs: document how to provide AWS credentials to the nix-daemon by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;235](https://redirect.github.com/cachix/install-nix-action/pull/235)
- nix: 2.28.2 -> 2.28.3 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;236](https://redirect.github.com/cachix/install-nix-action/pull/236)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.2.0...v31.3.0>

###
[`v31.2.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.2.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31.1.0...v31.2.0)

#### What's Changed

- nix: 2.26.3 -> 2.28.2 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;232](https://redirect.github.com/cachix/install-nix-action/pull/232)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.1.0...v31.2.0>

###
[`v31.1.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.1.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31...v31.1.0)

#### What's Changed

- Remove deprecated `--darwin-use-unencrypted-nix-store-volume` flag by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;230](https://redirect.github.com/cachix/install-nix-action/pull/230)
- action: add option to configure updating trusted users by
[@&#8203;Enzime](https://redirect.github.com/Enzime) in
[#&#8203;231](https://redirect.github.com/cachix/install-nix-action/pull/231)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v31.0.0...v31.1.0>

###
[`v31.0.0`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31.0.0)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v31...v31)

#### What's Changed

- nix: 2.24.9 -> 2.25.2 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;218](https://redirect.github.com/cachix/install-nix-action/pull/218)
- ci: fix latest installer tests by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;220](https://redirect.github.com/cachix/install-nix-action/pull/220)
- GitHub test.yml: add ubuntu-24.04-arm to matrix by
[@&#8203;msgilligan](https://redirect.github.com/msgilligan) in
[#&#8203;221](https://redirect.github.com/cachix/install-nix-action/pull/221)
- nix: 2.25.2 -> 2.26.2 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;226](https://redirect.github.com/cachix/install-nix-action/pull/226)
- nix: 2.26.2 -> 2.26.3 by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;228](https://redirect.github.com/cachix/install-nix-action/pull/228)

#### New Contributors

- [@&#8203;msgilligan](https://redirect.github.com/msgilligan) made
their first contribution in
[#&#8203;221](https://redirect.github.com/cachix/install-nix-action/pull/221)

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v30...v31.0.0>

###
[`v31`](https://redirect.github.com/cachix/install-nix-action/releases/tag/v31)

[Compare
Source](https://redirect.github.com/cachix/install-nix-action/compare/v30...v31)

Starting with v31, this action will use semantic versioning for
releases.
Major tags, like v31, will be bumped to point to the latest minor/patch
release.
This is in line with how most GitHub actions manage releases.

#### What's Changed

- nix: 2.26.3 -> 2.28.2 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;232](https://redirect.github.com/cachix/install-nix-action/pull/232)

- nix: 2.24.9 -> 2.25.2 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;218](https://redirect.github.com/cachix/install-nix-action/pull/218)

- ci: fix latest installer tests by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;220](https://redirect.github.com/cachix/install-nix-action/pull/220)

- ci: add ubuntu-24.04-arm to matrix by
[@&#8203;msgilligan](https://redirect.github.com/msgilligan) in
[#&#8203;221](https://redirect.github.com/cachix/install-nix-action/pull/221)

- nix: 2.25.2 -> 2.26.2 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;226](https://redirect.github.com/cachix/install-nix-action/pull/226)

- nix: 2.26.2 -> 2.26.3 by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;228](https://redirect.github.com/cachix/install-nix-action/pull/228)

- feat: Pin actions to hashes by
[@&#8203;l0b0](https://redirect.github.com/l0b0) in
[#&#8203;201](https://redirect.github.com/cachix/install-nix-action/pull/201)

- chore(deps): bump actions/checkout from 4.1.1 to 4.2.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[#&#8203;234](https://redirect.github.com/cachix/install-nix-action/pull/234)

- docs: document how to provide AWS credentials to the nix-daemon by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;235](https://redirect.github.com/cachix/install-nix-action/pull/235)

- nix: 2.28.2 -> 2.28.3 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;236](https://redirect.github.com/cachix/install-nix-action/pull/236)

- nix: 2.28.3 -> 2.29.0 by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;239](https://redirect.github.com/cachix/install-nix-action/pull/239)
Release notes: <https://nix.dev/manual/nix/latest/release-notes/rl-2.29>

- Automate nix updates in CI by
[@&#8203;Mic92](https://redirect.github.com/Mic92) in
[#&#8203;241](https://redirect.github.com/cachix/install-nix-action/pull/241)

- nix: 2.29.0 -> 2.29.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[#&#8203;243](https://redirect.github.com/cachix/install-nix-action/pull/243)
**\[SECURITY]**
<https://discourse.nixos.org/t/security-advisory-privilege-escalations-in-nix-lix-and-guix/66017>

- nix: 2.29.1 -> 2.30.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[#&#8203;244](https://redirect.github.com/cachix/install-nix-action/pull/244)
Release notes:
<https://nix.dev/manual/nix/2.30/release-notes/rl-2.30.html>

- nix: 2.30.0 -> 2.30.1 by
[@&#8203;xokdvium](https://redirect.github.com/xokdvium) in
[#&#8203;245](https://redirect.github.com/cachix/install-nix-action/pull/245)
**\[SECURITY]** Builds with Nix 2.30.0 on macOS were executed with
elevated privileges (root), instead of the build users.
<https://github.com/NixOS/nix/security/advisories/GHSA-qc7j-jgf3-qmhg>

- docs: add example for `nix develop` by
[@&#8203;jennydaman](https://redirect.github.com/jennydaman) in
[#&#8203;248](https://redirect.github.com/cachix/install-nix-action/pull/248)

- nix: 2.30.2 -> 2.31.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;250](https://redirect.github.com/cachix/install-nix-action/pull/250)
Release notes: <https://discourse.nixos.org/t/nix-2-31-0-released/68465>

- nix: 2.31.0 -> 2.31.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;253](https://redirect.github.com/cachix/install-nix-action/pull/253)

- nix: 2.31.1 -> 2.31.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;256](https://redirect.github.com/cachix/install-nix-action/pull/256)

- feat: set up the environment based on the installer shell scripts by
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) in
[#&#8203;251](https://redirect.github.com/cachix/install-nix-action/pull/251)
  Adds the bin directory from the user's profile to `$PATH`.
  Configures the following environment variables:
  - `NIX_PROFILES`
  - `NIX_SSL_CERT_FILE` (if not set)

- nix: 2.31.2 -> 2.32.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;257](https://redirect.github.com/cachix/install-nix-action/pull/257)
Release notes: <https://discourse.nixos.org/t/nix-2-32-0-released/70528>

- nix: 2.32.0 -> 2.32.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;258](https://redirect.github.com/cachix/install-nix-action/pull/258)

- nix: 2.32.1 -> 2.32.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;259](https://redirect.github.com/cachix/install-nix-action/pull/259)

- nix: 2.32.2 -> 2.32.3 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;260](https://redirect.github.com/cachix/install-nix-action/pull/260)

- nix: 2.32.3 -> 2.32.4 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;261](https://redirect.github.com/cachix/install-nix-action/pull/261)

- nix: 2.32.4 -> 2.33.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;264](https://redirect.github.com/cachix/install-nix-action/pull/264)

- nix: 2.33.0 -> 2.33.3 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;266](https://redirect.github.com/cachix/install-nix-action/pull/266)

- ~~nix: 2.33.3 -> 2.34.0 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;267](https://redirect.github.com/cachix/install-nix-action/pull/267)
Release notes:
<https://discourse.nixos.org/t/nix-2-34-0-released/75818>~~ **Rolled
back due to reports of issues with cachix-action**

- nix: 2.34.0 -> 2.34.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;269](https://redirect.github.com/cachix/install-nix-action/pull/269)
Fixes a bug introduced in 2.34.0 that made the Nix daemon fail to load
authentication keys configured by `cachix-action`.

- nix: 2.34.1 -> 2.34.2 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;270](https://redirect.github.com/cachix/install-nix-action/pull/270)

- nix: 2.34.2 -> 2.34.4 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;271](https://redirect.github.com/cachix/install-nix-action/pull/271)

- nix: 2.34.4 -> 2.34.5 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;273](https://redirect.github.com/cachix/install-nix-action/pull/273)

**[CVE-2026-39860](https://redirect.github.com/NixOS/nix/security/advisories/GHSA-g3g9-5vj6-r3gj)**
Fixes a root privilege escalation vulnerability via sandbox escape.
**Severity: Critical.**

- nix: 2.34.5 -> 2.34.6 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;274](https://redirect.github.com/cachix/install-nix-action/pull/274)

- nix: 2.34.6 -> 2.34.7 by
[@&#8203;github-actions](https://redirect.github.com/github-actions)\[bot]
in
[#&#8203;275](https://redirect.github.com/cachix/install-nix-action/pull/275)

**[GHSA-vh5x-56v6-4368](https://redirect.github.com/NixOS/nix/security/advisories/GHSA-vh5x-56v6-4368)**:
Fixes a coroutine stack-to-heap overflow via unbounded recursion in the
NAR directory parser. **Severity: High.**

**[GHSA-gr92-w2r5-qw5p](https://redirect.github.com/NixOS/nix/security/advisories/GHSA-gr92-w2r5-qw5p)**:
Fixes an absolute path traversal vulnerability when unpacking archives
to disk. Severity: Moderate.

**Full Changelog**:
<https://github.com/cachix/install-nix-action/compare/v30...v31>

</details>

## Why?

Automated dependency update via Renovate.

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzcuNyIsInVwZGF0ZWRJblZlciI6IjQzLjE3Ny43IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

4dd8085 feat: nix support + new site URL (#1271)

Click to expand commit body
## What?

- **Goreleaser nix publisher** (`goreleaser.yml`): on each stable
release, goreleaser pushes a prebuilt `default.nix` to
`floatpane/nix-matcha` (`main` branch). Users can install via `nix
profile install github:floatpane/nix-matcha`.

- **Nightly nix tap** (`nightly.yml`): mirrors the existing brew tap
step — after each nightly build, computes sha256s for all four platform
tarballs, templates `default.nix` + `flake.nix`, pushes to
`floatpane/nix-matcha` (`nightly` branch).

- **Nixpkgs bump workflow** (`nixpkgs-bump.yml`): on stable release
publish, syncs `floatpane/nixpkgs` fork with upstream, bumps version +
hashes in `pkgs/by-name/ma/matcha/package.nix`, builds to verify, opens
a PR against `NixOS/nixpkgs`. Skips nightly/preview tags automatically.

- **Reference derivation** (`nix/nixpkgs-package.nix`): canonical
`buildGoModule` derivation for the manual nixpkgs init PR and as ground
truth for the bump workflow.

## Why?

Closes #1245 

NixOS/nixpkgs#518988 initial PR.

Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

dad02f3 fix(tui): surface fetchFolders errors (#1267)

Click to expand commit body
## What?

Per-account `fetcher.FetchFolders` errors are now collected into
`FoldersFetchedMsg.Errors` and surfaced as a transient overlay in the
TUI (4s, then auto-restore via the existing `PluginNotifyMsg` pattern).
Closes #1125.

## Why?

`fetchFoldersCmd` spawns one goroutine per account, each calling
`fetcher.FetchFolders`. The previous code returned immediately on err
and the goroutine vanished without leaving a trace. If an account's
IMAP login was broken, OAuth had expired, or the server was
unreachable, the affected account silently dropped out of the merged
folder list and the user got no signal -- their folder list quietly
missed entries. The reporter described this exactly: "user sees the
folder list silently miss those folders and never gets a notification."

Matt Van Horn created

f86d3a6 feat(plugin): per-plugin KV storage (#1187)

Click to expand commit body
## What?

- Add `matcha.store_set(key, value)`, `store_get(key)`,
`store_delete(key)`, `store_keys()` to the Lua plugin API
- Storage lives at `~/.config/matcha/plugins/<plugin_name>/data.json`
with mode `0o600`, JSON-encoded, atomic write via unique temp file +
`Rename`
- Per-plugin scoping: Manager tracks the active plugin during plugin
load, hook invocation, and keybinding callbacks; hooks/keybindings now
carry their plugin attribution (`registeredHook{fn, plugin}`)
- Plugin-name validation: only `^[a-zA-Z0-9_-]+$` is accepted as a path
component, blocking traversal
- Lua API surfaces real store-init errors (corrupt JSON, permission
denied) to plugin authors instead of swallowing them as "no plugin
context"
- Tests cover: round-trip set/get/delete/keys, persistence across
`Manager` instances, concurrent writes, file mode `0o600` (including
survives overwrite), invalid plugin name rejection, Lua-level error
propagation on corrupt JSON, hook/keybinding plugin attribution
- Demo helper: `screenshots/cmd/plugin_storage_demo/main.go` loads the
same plugin in two `Manager` instances against the same `HOME` to prove
cross-session persistence

## Why?

Closes #510.

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: drew <me@andrinoff.com>

Matt Van Horn and drew created

54bd72f docs: add github sponsors (#1282)

Click to expand commit body
## What?

Removes Open Collective and my website from funding.

Adds Open Collective to README, with GitHub sponsors

## Why?

We got approved for GitHub sponsors, and for most people, that is the
easiest way to contribute financially

Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

52e2592 fix: clean account caches on deletion (#1265)

FromSi created

318c320 fix(fetcher): nil-safe charset lookup (#1276)

Sai Asish Y created

353d9ef fix: mailbox channel send non-blocking (#1270)

Matt Van Horn created

b858d58 fix: UTF-8 filename truncation (#1272)

Click to expand commit body
## What?

- Add UTF-8-safe truncation for sanitized attachment filenames
- Preserve filename extensions while truncating the base name on valid
rune boundaries
- Add regression coverage for long CJK and emoji filenames

## Why?

The previous byte-slicing logic could cut through a multi-byte UTF-8
sequence when shortening long attachment filenames, producing invalid
UTF-8 for names containing CJK characters or emoji.

Fixes #1102.

Sean Corliss created

6852183 docs: FUNDING.yml (#1275)

Drew Smirnoff created

9288d3f docs: Open Collective funding option (#1275)

Click to expand commit body
## What?

Adds Opem Collective URL

## Why?

For sponsoring

Drew Smirnoff created

5e79726 ci: label PRs by diff size (#1273)

Click to expand commit body
## What?

adds diff size labeler for pull requests

## Why?

makes it easier to check prs for maintainers

Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

a9fc2f0 feat: plugin settings SDK (#1266)

Click to expand commit body
## What?

Adds user-configurable plugin settings. Plugins declare typed options
via a new `matcha.settings(spec)` Lua API supporting `boolean`,
`number`, and `string` types with defaults, labels, and descriptions.
The call returns a read-only proxy table whose fields reflect live
values, so hook callbacks read current settings through closure capture.
A second helper `matcha.get_setting(key [, plugin])` provides explicit
lookup. The plugin Manager tracks the loading plugin so schemas
attribute correctly, and gains methods for reading, writing, loading,
and exporting setting values with type coercion. Values persist in
`config.json` under a new `plugin_settings` field (both regular and
secure-mode disk formats).

## Why?

Plugins shipped hardcoded constants (keyword lists, thresholds,
toggles). Users had to edit Lua source to tweak them — fragile and lost
on plugin reinstall. Plugins now declare schemas; users edit values in
TUI; values persist across upgrades. Bool toggle avoids parser errors
from typing `true`/`false`/`1`/`0` inconsistently.

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: Lea <lea@floatpane.com>
Co-authored-by: Steve Evans <steve@floatpane.com>

Drew Smirnoff , Lea , and Steve Evans created

2aa2812 fix: protect providers map (#1268)

Click to expand commit body
## What?

Protected the `providers` map with a `sync.RWMutex` to fix a race
condition.

## Why?

`ensureProviders()` writes to the map on the Bubble Tea event loop while
`getProvider()` is called concurrently from goroutines spawned by batch
and search commands, causing unsafe concurrent map access.

Closes #766

Mohamed Mahmoud created

6848d43 feat: global email body cache eviction (#1257)

Click to expand commit body
## What?

Adds a configurable global size limit for cached email bodies.

- Defaults `body_cache_threshold_mb` to 100 MB.
- Applies the limit across the whole `~/.cache/matcha/email_bodies/`
directory, not per folder cache file.
- Evicts least recently accessed cached bodies until the total cache
size is back under the limit.
- Skips caching bodies larger than the configured limit.
- Adds tests for cross-folder LRU eviction, multi-entry eviction,
oversized replacements, and the default threshold.
- Updates the seed script to generate 10 KB email bodies for cache
testing.

## Why?

Email body cache files could grow without a global cap for active users
with large mailboxes. Existing pruning only removed bodies for emails no
longer present in a folder, so valid cached emails could accumulate
indefinitely. A global LRU limit keeps disk usage bounded while
preserving recently used cached messages.

Closes #521

FromSi created

d581aed feat: select composer attachments (#1259)

Click to expand commit body
## What?

Added selectable attachment navigation in the composer. Attachments are
now shown as a focused list with a cursor, and `backspace`, `delete`, or
`d` removes the selected attachment instead of always removing the last
one.

## Why?

Previously, when multiple files were attached, the composer only allowed
removing the most recently added attachment. This makes it possible to
choose and remove any specific attachment without deleting newer ones
first.

Closes #543

FromSi created

19149a6 fix(config): cache read no mutation (#1256)

Click to expand commit body
## What?

Closes #1251

`GetCachedEmailBody` is a read operation but it was stamping
`LastAccessedAt` on the matched entry and rewriting the body cache file
on every hit, violating the read/write boundary the issue calls out.
Drops the two flagged lines (`config/cache.go:505-506`) and adds a
one-line note above the function that `SaveEmailBody` is the access-time
owner.

## Why?

The issue's analysis is correct: every email view path in `main.go`
already chases `GetCachedEmailBody` with `SaveEmailBody`, which sets
`LastAccessedAt = time.Now()` on the entry it persists. That keeps the
LRU-style eviction in `evict` (sorted by `LastAccessedAt`) working
unchanged, with one fewer disk write per email view.

I traced both call sites to verify eviction recency is preserved on
cache hits:

- `main.go:707-744` (UpdatePreviewMsg): cache hit returns
`PreviewBodyFetchedMsg{Err: nil}`. The handler at `main.go:746-779` runs
`config.SaveEmailBody` whenever `msg.Err == nil`, which updates
`LastAccessedAt` (`config/cache.go:552`).
- `main.go:1247-1278` (ViewEmailMsg): cache hit returns
`EmailBodyFetchedMsg{Err: nil}`. The handler at `main.go:1282-1328` runs
`config.SaveEmailBody` whenever `msg.Err == nil`, same path.

So an email the user repeatedly opens still bumps to the front of the
eviction queue on every open; the work just happens in `SaveEmailBody`
(which already exists) instead of duplicating it inside
`GetCachedEmailBody`.

Matt Van Horn created

f6f120b chore: sync gomod2nix.toml (#1264)

Floatpane Bot created

67fdd91 chore: update flake.lock (#1263)

Floatpane Bot created

057c158 chore(deps): golang.org/x/term ^ v0.43.0 (#1260)

Floatpane Bot created

86cf8b0 chore(deps): golang.org/x/crypto ^ v0.51.0 (#1262)

Floatpane Bot created

5d29e3b chore(deps): golang.org/x/text ^ v0.37.0 (#1261)

Click to expand commit body
## What?

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) | [`v0.36.0`
→
`v0.37.0`](https://cs.opensource.google/go/x/text/+/refs/tags/v0.36.0...refs/tags/v0.37.0)
|
![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2ftext/v0.37.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2ftext/v0.36.0/v0.37.0?slim=true)
|

## Why?

Automated dependency update via Renovate.

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzAuNyIsInVwZGF0ZWRJblZlciI6IjQzLjE3MC43IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

8201361 chore(deps): golang.org/x/sys ^ v0.44.0 (#1258)

Click to expand commit body
## What?

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) | [`v0.43.0` →
`v0.44.0`](https://cs.opensource.google/go/x/sys/+/refs/tags/v0.43.0...refs/tags/v0.44.0)
|
![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fsys/v0.44.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fsys/v0.43.0/v0.44.0?slim=true)
|

## Why?

Automated dependency update via Renovate.

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzAuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3MC4zIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

dd34ac2 docs: update demo.gif (#1248)

Click to expand commit body
## What?

Replaces `public/assets/demo.gif` with a freshly recorded VHS run.

## Why?

Keeps the demo GIF aligned with the latest release so README and docs
reflect current behaviour. Generated automatically by the Update Demo
VHS workflow.

Co-authored-by: floatpanebot <278062430+floatpanebot@users.noreply.github.com>

Floatpane Bot and floatpanebot created

8418535 feat: show attachment file sizes (#1252)

Click to expand commit body
## What?

Display attachment file sizes in the composer attachment list, e.g.
`image.jpg (1.2 MB)`.

Also wired file size formatting through the existing i18n number
formatter:

- added `GetNumberFormatter()` to the i18n manager
- added a short TUI helper `tfs(...)`
- reused it in both composer and file picker
- removed the old file picker-local file size formatter
- added tests for attachment display

## Why?

Composer previously showed only attachment filenames, so users had no
quick way to check file size before sending.

The formatter was touched because there was already an unused
locale-aware `i18n.NumberFormatter.FormatFileSize`. Instead of keeping a
composer-specific helper or reusing a file picker-private function, this
change makes file size formatting a shared i18n-backed path. That keeps
formatting consistent across TUI components and supports locale-specific
number formatting, such as `1.2 MB` vs `1,2 MB`.

Closes #550

FromSi created

944af77 chore(deps): go ^ 1.26.3 (#1254)

Floatpane Bot created

f6343e9 chore(deps): go ^ 1.26.3 (#1253)

Floatpane Bot created

62f89db docs: update feature screenshots (#1247)

Click to expand commit body
## What?

Refreshes the feature screenshots in `docs/docs/assets/features/`.

### Screenshots included:
- `compose_email.png`
- `compose_empty.png`
- `drafts.png`
- `email_view.png`
- `inbox_view.png`
- `main_menu.png`
- `settings.png`
- `theme_settings.png`
- `threading_demo.png`

## Why?

Keeps documentation visuals aligned with the current TUI. Generated
automatically by the Generate Screenshots workflow on the latest
release.

Co-authored-by: floatpanebot <278062430+floatpanebot@users.noreply.github.com>

Floatpane Bot and floatpanebot created

05651d4 fix: split pane html conv and table fix (#1246)

Click to expand commit body
## What?

Fixes split pane HTML conversion, according to #1213 

Also changes in `view/html.go`:
- Extracted element loop into `renderHTMLToText` helper.
- `processBody` now: if `mimeType == text/html` and direct render is
whitespace-only, retry through `markdownToHTML` pre-pass

## Why?

Certain emails are not displayed correctly, as pointed by @EmilyxFox.
Also, split pane was displaying emails incorrectly not as per #1213 fix.

Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

726899a feat(threading): JWZ conversation view (#1188)

Click to expand commit body
## What?

- Add `internal/threading` package implementing the Jamie Zawinski
threading algorithm against `Message-ID` / `In-Reply-To` / `References`
headers, with subject-fallback grouping for orphans
- Carry `MessageID`, `InReplyTo`, and `References` through fetcher, the
IMAP/JMAP/POP3 backends, the on-disk email cache, the daemon RPC types,
and the inbox model so threading works against cached headers without
server round-trips
- Inbox renders threaded mode with one row per thread root, showing the
count and last-sender; `Enter` toggles expand/collapse; expanded
children render indented with `↪` markers
- `T` keybind toggles flat vs threaded for the current folder; the
per-folder mode persists via `folder_cache.go`
- Subject canonicalization handles `Re:`, `Fwd:`, `Fw:`, `AW:`, `WG:`,
`Tr:` (lowercased, stripped repeatedly so `Re: Re: Foo` -> `foo`)
- Tests cover: 3-message chains, forks, missing-parent placeholders,
subject-fallback grouping, empty References, deterministic ordering
across repeated `Build()` calls
- VHS demo (`screenshots/cmd/threading_demo` +
`screenshots/threading_demo.tape`): flat (5 emails) → threaded (3 rows
with `(3)` count on the root) → expanded (5 rows with `↪` on children) →
collapsed → flat

## Why?

This is the maintainer's spec from issue #509 and the more detailed
#1130:

> "Group emails into conversation threads using `In-Reply-To` and
`References` headers (RFC 5322). Display threads as collapsible groups
in the inbox, showing the latest message and a count of messages in the
thread."

> "Build threads with the Jamie Zawinski algorithm (the one Thunderbird
uses) so we don't have to rely on `X-GM-THRID`. Threading should be done
client-side from the cached header set so it works across providers."

The framing in #1130 is the user-visible argument: "Showing each reply
as a separate inbox row is how Mutt looked in 1999. Modern terminal
clients (aerc, himalaya) all thread."

The launch threads on r/coolgithubprojects + r/CLI + r/selfhosted
(cumulative 161 upvotes, 32 comments) consistently flagged conversation
grouping as the gap users notice first when comparing matcha to
gmail/superhuman/aerc.

## Notes

- Touches `main.go` (alongside in-flight #845 and #686). Conflicts
should be mechanical - the threading wiring in `main.go` is small
(cache-conversion paths to carry References/InReplyTo). Happy to rebase
or stack PRs.
- Ordering ties in JWZ are broken on `EmailID` so `Build()` is
deterministic across runs.
- The implementation deliberately avoids `X-GM-THRID` and IMAP THREAD
(RFC 5256) per the spec - threading is purely client-side over cached
envelope data.
- Out of scope: per-thread mark-as-read propagation rules (kept current
behavior); thread-aware archive/delete (uses single-message semantics
for now).

Closes #509. Addresses #1130.

This contribution was developed with AI assistance.

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Andriy Chernov <andriy@floatpane.com>
Co-authored-by: drew <me@andrinoff.com>

Matt Van Horn , Matt Van Horn , Andriy Chernov , and drew created

c94e714 fix(tui): wrap menu navigation (#1242)

Click to expand commit body
## What?

Adds wrap-around navigation to the remaining bounded TUI menus and
selection lists, including settings sections, file picker items, and
email attachments. Updates tests to cover the cyclic navigation
behavior.

## Why?

Some TUI areas still stopped at the first or last item while others
already used cyclic navigation. This makes menu movement consistent
across the app: pressing up on the first item selects the last item, and
pressing down on the last item selects the first.

Closes #1237

FromSi created

6bd53b1 fix(tui): stop attachment nav scroll (#1243)

Click to expand commit body
## What?

Prevents email body scrolling when navigating attachments in the email
view.

## Why?

When attachment focus is active, up/down should only move the attachment
selection. Previously, those key events also reached the email body
viewport, causing the message content to scroll at the same time.

FromSi created

6305a0f chore(deps): react ^ 19.2.6 (#1244)

Click to expand commit body
## What?

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [react](https://react.dev/)
([source](https://redirect.github.com/facebook/react/tree/HEAD/packages/react))
| [`19.2.5` →
`19.2.6`](https://renovatebot.com/diffs/npm/react/19.2.5/19.2.6) |
![age](https://developer.mend.io/api/mc/badges/age/npm/react/19.2.6?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react/19.2.5/19.2.6?slim=true)
|
| [react-dom](https://react.dev/)
([source](https://redirect.github.com/facebook/react/tree/HEAD/packages/react-dom))
| [`19.2.5` →
`19.2.6`](https://renovatebot.com/diffs/npm/react-dom/19.2.5/19.2.6) |
![age](https://developer.mend.io/api/mc/badges/age/npm/react-dom/19.2.6?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-dom/19.2.5/19.2.6?slim=true)
|

---

### Release Notes

<details>
<summary>facebook/react (react)</summary>

###
[`v19.2.6`](https://redirect.github.com/facebook/react/releases/tag/v19.2.6):
19.2.6 (May 6th, 2026)

[Compare
Source](https://redirect.github.com/facebook/react/compare/v19.2.5...v19.2.6)

##### React Server Components

- Type hardening and performance improvements
(by [@&#8203;eps1lon](https://redirect.github.com/eps1lon) and
[@&#8203;unstubbable](https://redirect.github.com/unstubbable))

</details>

## Why?

Automated dependency update via Renovate.

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjYuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE2Ni4zIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

c11de45 feat: markdown for html bodies (#1213)

Click to expand commit body
## What?

Threads MIME type detection from the fetch layer through to rendering.
FetchEmailBody and the IMAP/JMAP/POP3 providers now return BodyMIMEType.
The Backend interface, daemon RPC protocol, and local cache schema all
carry the MIME type through. view.ProcessBody takes the MIME type and
skips the markdownToHTML pre-pass when it's text/html. The TUI message
fetcher and view call sites are updated for the new field.

## Why?
Right now every email body gets run through md4c before we render it as
HTML. The assumption was that md4c would pass raw HTML through
untouched, but that falls apart on real HTML email — Datadog digests,
marketing stuff, anything with heavy attributes or indentation trips
md4c's html_block rules. When that happens, md4c either escapes the tags
or treats them as code blocks, and the TUI ends up showing literal
`<table>`, `<tr>`, `<td>` instead of the rendered content.
Detecting text/html and skipping the markdown pass fixes that, while
text/plain senders like GitHub notifications and mailing lists keep
their markdown formatting.

### Trade-offs & compatibility
If a text/html sender writes `**bold**` inside their HTML, it won't
render as bold anymore. That's spec-correct behavior, and it's worth
losing to get tables back. On the compat side, MIME type defaults to an
empty string in the wire format and cache, so old cache entries fall
back to the legacy markdown path. No migration needed.

---------

Co-authored-by: Drew Smirnoff <drew@floatpane.com>

Ryan Hartman and Drew Smirnoff created

efdebf1 fix(sender): fail closed on rand error (#1233)

Click to expand commit body
## What?

Treats `crypto/rand` failure as fatal in `sender.go` instead of falling
back to a `time.UnixNano()`-based outer boundary. Replaces both the
signed-only and signed+encrypted call sites with a
`smimeOuterBoundary()` helper that propagates the error, plus regression
tests using an injectable `randReader`.

## Why?

The previous fallback produced a predictable boundary that could be
collided by an attacker-controlled body part, breaking S/MIME envelope
integrity. Failing closed on rand errors removes the predictable path
entirely; tests pin the new behavior so the fallback can't silently
return.

Closes #1127.

Co-authored-by: SAY-5 <saiasish.cnp@gmail.com>

Sai Asish Y and SAY-5 created