Commit log

5840b30 chore(deps): go ^ 1.26.4 (#1430)

Click to expand commit body
## What?

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [go](https://redirect.github.com/actions/go-versions) | uses-with |
patch | `1.26.3` β†’ `1.26.4` |

---

### Release Notes

<details>
<summary>actions/go-versions (go)</summary>

###
[`v1.26.4`](https://redirect.github.com/actions/go-versions/releases/tag/1.26.4-26891772857):
1.26.4

[Compare
Source](https://redirect.github.com/actions/go-versions/compare/1.26.3-25533533231...1.26.4-26891772857)

Go 1.26.4

</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 is behind base branch, 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:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDkuNCIsInVwZGF0ZWRJblZlciI6IjQzLjIwOS40IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

e9adba8 docs: remove gitads (#1428)

Click to expand commit body
Signed-off-by: drew <me@andrinoff.com>

Drew Smirnoff created

ced3444 docs: add a mention of v1 in README (#1409)

Click to expand commit body
## What?

Adds a mention about v1 release in the README (master branch

## Why?

So that people know, that, even, if there are no commits on master, we
still are developing

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

Drew Smirnoff created

617e1aa chore: sync gomod2nix.toml (#1407)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

4ee8a9b chore(deps): react ^ 19.2.7 (#1406)

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.6` β†’
`19.2.7`](https://renovatebot.com/diffs/npm/react/19.2.6/19.2.7) |
![age](https://developer.mend.io/api/mc/badges/age/npm/react/19.2.7?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react/19.2.6/19.2.7?slim=true)
|
| [react-dom](https://react.dev/)
([source](https://redirect.github.com/facebook/react/tree/HEAD/packages/react-dom))
| [`19.2.6` β†’
`19.2.7`](https://renovatebot.com/diffs/npm/react-dom/19.2.6/19.2.7) |
![age](https://developer.mend.io/api/mc/badges/age/npm/react-dom/19.2.7?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-dom/19.2.6/19.2.7?slim=true)
|

---

### Release Notes

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

###
[`v19.2.7`](https://redirect.github.com/facebook/react/releases/tag/v19.2.7):
19.2.7 (June 1st, 2026)

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

##### React Server Components

- Fixed missing `FormData` entries in Server Actions which regressed in
19.2.6
([#&#8203;36566](https://redirect.github.com/facebook/react/pull/36566)
by [@&#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 is behind base branch, 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:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDcuNCIsInVwZGF0ZWRJblZlciI6IjQzLjIwNy40IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

daab110 chore(deps): charm.land/bubbletea/v2 ^ v2.0.7 (#1405)

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/) |
|---|---|---|---|
|
[charm.land/bubbletea/v2](https://redirect.github.com/charmbracelet/bubbletea)
| `v2.0.6` β†’ `v2.0.7` |
![age](https://developer.mend.io/api/mc/badges/age/go/charm.land%2fbubbletea%2fv2/v2.0.7?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/charm.land%2fbubbletea%2fv2/v2.0.6/v2.0.7?slim=true)
|

---

### Release Notes

<details>
<summary>charmbracelet/bubbletea (charm.land/bubbletea/v2)</summary>

###
[`v2.0.7`](https://redirect.github.com/charmbracelet/bubbletea/releases/tag/v2.0.7)

[Compare
Source](https://redirect.github.com/charmbracelet/bubbletea/compare/v2.0.6...v2.0.7)

### A few lil’ stability patches

Hi! This is a patch release with a few solid improvements around
stability and correctness.

- [@&#8203;lrstanley](https://redirect.github.com/lrstanley), one of our
faves, fixed a race condition around mice in the Cursed Renderer
- [@&#8203;lawrence3699](https://redirect.github.com/lawrence3699) fixed
a panic that could happen when input's not available
- We fixed a correctness issue with regard to mouse releases when Kitty
Keyboard was active (thanks,
[@&#8203;mitchellh](https://redirect.github.com/mitchellh))

Thanks for using Bubble Tea, and if you see anything awry please do let
us know!

β€”Charm πŸ‘‹

#### Changelog

##### Fixed

-
[`c60f0c5`](https://redirect.github.com/charmbracelet/bubbletea/commit/c60f0c53042238305ec13b486326588f12aea0ec):
fix: prevent data race with cursedRenderer.onMouse
([#&#8203;1691](https://redirect.github.com/charmbracelet/bubbletea/issues/1691))
([@&#8203;lrstanley](https://redirect.github.com/lrstanley))
-
[`074596e`](https://redirect.github.com/charmbracelet/bubbletea/commit/074596e14e2f5ca5e3986ee72e7c08f1569c4178):
fix: skip input reader restore when input is disabled
([#&#8203;1680](https://redirect.github.com/charmbracelet/bubbletea/issues/1680))
([@&#8203;lawrence3699](https://redirect.github.com/lawrence3699))
-
[`878d7df`](https://redirect.github.com/charmbracelet/bubbletea/commit/878d7df2f2b02f3ca8db177fa8553834bc35ea7c):
fix(deps): bump ultraviolet for kitty keyboard fix
([@&#8203;meowgorithm](https://redirect.github.com/meowgorithm))

***

<a href="https://charm.land/"><img alt="The Charm logo"
src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a>

Thoughts? Questions? We love hearing from you. Feel free to reach out on
[X](https://x.com/charmcli), [Discord](https://charm.land/discord),
[Slack](https://charm.land/slack), [The
Fediverse](https://mastodon.social/@&#8203;charmcli),
[Bluesky](https://bsky.app/profile/charm.land).

</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 is behind base branch, 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:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDcuNCIsInVwZGF0ZWRJblZlciI6IjQzLjIwNy40IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

f97aca4 chore: sync gomod2nix.toml (#1402)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

1295b58 chore: update flake.lock (#1401)

Click to expand commit body
## What?

Updates `flake.lock` to the latest revisions of all flake inputs
(`nixpkgs`, `flake-utils`, etc.).

## Why?

Keeps Nix inputs current so contributors and CI build against fresh
`nixpkgs`. Picks up upstream security and toolchain fixes. Generated
automatically by the flake-lock update workflow on changes to `go.sum`.

Floatpane Bot created

cbd1137 fix(badge): dedupe unread count (#1398)

Click to expand commit body
## What?

Deduplicate unread badge counting across `emailsByAcct` and
`folderEmails` by tracking seen emails with `AccountID + UID`.

Added a regression test for the case where the same unread email exists
in both stores.

<img width="595" height="652" alt="image"
src="https://github.com/user-attachments/assets/8c837fb8-017c-4c7c-aa2c-052f244288b2"
/>

## Why?

Closes #1107

`syncUnreadBadge` counted unread emails from both stores independently,
but the stores can contain the same fetched messages. This could make
the macOS unread badge show roughly double the real unread count.

<img width="598" height="647" alt="image"
src="https://github.com/user-attachments/assets/f2b1c267-29bc-4d4c-a116-4c91af789722"
/>

FromSi created

e4987f3 test: implement encryption tests (#1399)

Click to expand commit body
## What?

Implements a complete test suite for the `encryption.go`.

## Why?

The previous implementation had no test coverage for the
`encryption.go`.

Closes #886

Mohamed Mahmoud created

1890665 chore: use go-keybind (#1397)

Click to expand commit body
## What?

Uses [`go-keybind`](https://github.com/floatpane/go-keybind).

## Why?

Easier to maintain/expand

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

Drew Smirnoff created

dad48a0 ci: prepare release v1 workflows (#1400)

Click to expand commit body
## What?

Adds a v1 release backporting, merge queue behaivor, e.t.c.

## Why?

We are ready to start working on v1 of matcha. v0 will still be
maintained and supplied security updates, bug fixes, QoL features

---------

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

Drew Smirnoff created

c1940a6 chore: sync gomod2nix.toml (#1396)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

16d519b chore: use floatpane/go-icalendar (#1395)

Click to expand commit body
## What?

Replaces `calendar.go` with a new library
[`go-icalendar`](https://github.com/floatpane/go-icalendar)

## Why?

Makes the code easier to expand and improve apart. Also, could be
re-used by other people

---------

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

Drew Smirnoff created

f072a04 chore: sync gomod2nix.toml (#1394)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

f2bdf25 chore: use secretbox (#1393)

Click to expand commit body
## What?

Switches to [`go-secretbox`](https://github.com/floatpane/go-secretbox).

## Why?

Makes the code reusable and easier to maintain.

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

Drew Smirnoff created

54017d8 fix: move email actions to daemon (#1378)

Click to expand commit body
## What?

Delegates email operations (delete, archive, move) to the daemon instead
of blocking the UI with loading spinners.

## Why?

Email operations can take time, especially for batch actions or slower
IMAP connections. By delegating them to the daemon, the UI remains
responsive, operations continue in the background, and users can safely
close the TUI without interrupting the work.

Closes #1255

Mohamed Mahmoud created

df18854 ci: remove release event (#1392)

Click to expand commit body
## What?

Removes a release event trigger on nix-pkgs-bump workflow

## Why?

We need to rely on r-ryantm, because it will get merged sooner that way.

Drew Smirnoff created

0d9848d docs: update feature screenshots (#1391)

Floatpane Bot created

8e40179 docs: update demo.gif (#1390)

Floatpane Bot created

de73bbd chore: sync gomod2nix.toml (#1389)

Floatpane Bot created

9df4bae chore: use new library cardhl (#1387)

Click to expand commit body
## What?

Replaces a lot of code with a new library
[`go-openpgp-card-hl`](https://github.com/floatpane/go-openpgp-card-hl)

## Why?

Could be reused by other project and easier to maintain separately

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

Drew Smirnoff created

9cf49ca fix: inaccessible settings fields (#1388)

Click to expand commit body
## What?

Fixes crypto settings field not taking input.

## Why?

A critical bug, you could not set up crypto

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

Drew Smirnoff created

ada70fa chore: sync gomod2nix.toml (#1386)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

6f76180 chore: add jwz-go and bubble-overlay (#1379)

Click to expand commit body
## What?

Replaces the `internal/threading` with our library
[`jwz-go`](https://github.com/floatpane/jwz-go).

Replaces helper `overlay.go` with a library
[`bubble-overlay`](https://github.com/floatpane/bubble-overlay)

## Why?

These libraries may be used by others, and it will make it easier to
maintain them separate from our project.

---------

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

Drew Smirnoff created

06cdbd9 chore: sync gomod2nix.toml (#1385)

Floatpane Bot created

ece0fec chore(deps): github.com/floatpane/termimage ^ v0.2.1 (#1380)

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/) |
|---|---|---|---|
|
[github.com/floatpane/termimage](https://redirect.github.com/floatpane/termimage)
| `v0.2.0` β†’ `v0.2.1` |
![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2ffloatpane%2ftermimage/v0.2.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2ffloatpane%2ftermimage/v0.2.0/v0.2.1?slim=true)
|

---

### Release Notes

<details>
<summary>floatpane/termimage (github.com/floatpane/termimage)</summary>

###
[`v0.2.1`](https://redirect.github.com/floatpane/termimage/releases/tag/v0.2.1)

[Compare
Source](https://redirect.github.com/floatpane/termimage/compare/v0.2.0...v0.2.1)

<!-- Release notes generated using configuration in .github/release.yml
at v0.2.1 -->

#### What's Changed

##### Dependencies

- chore(deps):
[@&#8203;types/react](https://redirect.github.com/types/react) ^ 19.2.15
by [@&#8203;floatpanebot](https://redirect.github.com/floatpanebot) in
[#&#8203;8](https://redirect.github.com/floatpane/termimage/pull/8)
- chore(deps): golang.org/x/image ^ v0.41.0 by
[@&#8203;floatpanebot](https://redirect.github.com/floatpanebot) in
[#&#8203;12](https://redirect.github.com/floatpane/termimage/pull/12)

#### New Contributors

- [@&#8203;floatpanebot](https://redirect.github.com/floatpanebot) made
their first contribution in
[#&#8203;8](https://redirect.github.com/floatpane/termimage/pull/8)

**Full Changelog**:
<https://github.com/floatpane/termimage/compare/v0.2.0...v0.2.1>

***

**Install:**

```bash
go get github.com/floatpane/termimage@v0.2.1
```

See the [Go
reference](https://pkg.go.dev/github.com/floatpane/termimage) for full
API documentation.

</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 is behind base branch, 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:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDUuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIwNS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Floatpane Bot created

576414c chore: sync gomod2nix.toml (#1384)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

4654520 chore: update flake.lock (#1383)

Click to expand commit body
## What?

Updates `flake.lock` to the latest revisions of all flake inputs
(`nixpkgs`, `flake-utils`, etc.).

## Why?

Keeps Nix inputs current so contributors and CI build against fresh
`nixpkgs`. Picks up upstream security and toolchain fixes. Generated
automatically by the flake-lock update workflow on changes to `go.sum`.

Floatpane Bot created

d4fd1fa chore: use udsrpc for daemon (#1382)

Click to expand commit body
## What?

Replaced a lot of code with a new library
[`go-uds-jsonrpc`](https://github.com/floatpane/go-uds-jsonrpc)

## Why?

A lot of code is reusable, and this may bring a lot of users into
floatpane ecosystem.

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

Drew Smirnoff created

1d7c81a fix(tui): settings focus nav (#1367)

Click to expand commit body
## What?

Improves Settings pane focus navigation in the TUI.

- Adds `left` navigation back from the content pane to the settings
menu.
- Allows `left` to leave Settings from the menu, like `esc`.
- Hides right-pane cursor/highlight when the content pane is not
focused.
- Keeps bold styling only on the currently focused pane.
- Updates English Settings help text.
- Adds tests for horizontal pane focus and App Encryption input
behavior.

<img width="1400" height="800" alt="view"
src="https://github.com/user-attachments/assets/b35a6c89-0efa-4bb6-aad6-91fda01fb274"
/>

## Why?

Closes #1231

Fixes confusing Settings focus behavior where both panes could appear
selected at the same time.

This makes keyboard navigation clearer: `>` and bold styling now
indicate the active focus, while `left` provides a consistent way to
move back or exit.

---------

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

FromSi and drew created

2ba041f fix: maildir fetch errors (#1375)

Click to expand commit body
## What?

Routes all per-account fetch sites in main.go through
`m.providers[acct.ID]`.

## Why?

Fixes #1309

---------

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

Drew Smirnoff created

18062bf fix: centralize cache file registry (#1370)

Click to expand commit body
## What?

Replaces the hardcoded file list inside `MigrateCacheFiles()` with two
package-level registries: `cacheFiles` for JSON cache files and
`cacheDirectories` for cache subdirectories.

## Why?

Previously, adding a new cache file to the project required finding and
updating the hardcoded list inside `MigrateCacheFiles()`. This was easy
to forget and caused files to be silently left behind in the old
`~/.config/matcha/` location after migration. Now there is a single
obvious place to register new cache paths.

Closes #564

Mohamed Mahmoud created

9e4f238 docs: support TIP CAUTION and other (#1376)

Click to expand commit body
## What?

Adds support for `[!TIP]` and other github's admonitions. 

## Why?

So it looks better, and can be read from GitHub and our [docs
website](https://docs.matcha.email)

---------

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

Drew Smirnoff created

9386351 fix: prevent a fork bomb (#1374)

Click to expand commit body
## What?

Add `view/main_test.go` with `TestMain` calling
`termimage.MaybeRunWorker()` before `m.Run()`.

## Why?

termimage.DisplayWithSize` (called by `view.prerenderImage`) sandboxes
image decode by spawning `os.Executable()` as subprocess with
`TERMIMAGE_WORKER=1`. Worker subprocess MUST call
`termimage.MaybeRunWorker()` first to intercept, decode, exit.

`main.go` does this for the real binary. Test binary did not. When
`TestProcessBodyWithImageProtocol` ran Kitty/iTerm cases,
`prerenderImage` spawned the test binary as worker. Child re-ran full
test suite β†’ triggered more `prerenderImage` calls β†’ spawned more
children β†’ fork bomb. RAM exhausted, machine froze.

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

Drew Smirnoff created

072de66 docs: update feature screenshots (#1372)

Floatpane Bot created

ff078ff docs: update demo.gif (#1371)

Floatpane Bot created

c276224 docs: add commit message length rule (#1373)

Click to expand commit body
## What?

Adds a contribution guideline that commit messages should be 40
characters or fewer.

## Why?

Keeps commit history concise and easier to scan across logs, changelogs,
and review workflows.

FromSi created

15f1730 chore: sync gomod2nix.toml (#1369)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

4bd4513 chore: update flake.lock (#1368)

Click to expand commit body
## What?

Updates `flake.lock` to the latest revisions of all flake inputs
(`nixpkgs`, `flake-utils`, etc.).

## Why?

Keeps Nix inputs current so contributors and CI build against fresh
`nixpkgs`. Picks up upstream security and toolchain fixes. Generated
automatically by the flake-lock update workflow on changes to `go.sum`.

Floatpane Bot created

c0cc0a6 feat: add termimage (#1366)

Click to expand commit body
## What?

Replaces our image rendering with
[floatpane/termimage](https://github.com/floatpane/termimage)

## Why?

termimage was built to be a more secure way to show an image without the
worry of harming your computer.

---------

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

Drew Smirnoff created

db06d38 chore: sync gomod2nix.toml (#1364)

Click to expand commit body
## What?

Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`.

## Why?

Keeps the Nix build in sync with Go module changes. Without this, `nix
build` fails when new or upgraded Go deps are missing from
`gomod2nix.toml`. Generated automatically by the gomod2nix sync
workflow.

Floatpane Bot created

37f0a64 chore: update flake.lock (#1363)

Click to expand commit body
## What?

Updates `flake.lock` to the latest revisions of all flake inputs
(`nixpkgs`, `flake-utils`, etc.).

## Why?

Keeps Nix inputs current so contributors and CI build against fresh
`nixpkgs`. Picks up upstream security and toolchain fixes. Generated
automatically by the flake-lock update workflow on changes to `go.sum`.

Floatpane Bot created

116847b test: refactor body cache tests (#1359)

Click to expand commit body
## What?

Refactors the test suite for email body cache.

## Why?

The previous implementation only covered a few narrow scenarios and
failed to test the system under most practical edge cases.

Closes #887

Mohamed Mahmoud created

ebea5a3 fix(view): sanitize HTML rendering (#1361)

Click to expand commit body
## What?

HTML email rendering now sanitizes untrusted content before converting
it to terminal text.

Available after sanitization:
- safe text/layout tags such as paragraphs, lists, tables, headings,
blockquotes, and inline formatting
- safe links using `http`, `https`, `mailto`, and `tel`
- image sources using `http`, `https`, safe `cid`, and valid
`data:image` payloads

Not available after sanitization:
- `javascript:`, `vbscript:`, `file:`, relative, and protocol-relative
links
- `data:` or `cid:` links in `<a href>`
- scripts, styles, event handlers like `onclick`, and unsafe attributes
- OSC 8 clickable image fallbacks for `cid:` and `data:image` sources

## Why?

Closes #653

HTML emails could include unsafe links or attributes such as
`javascript:` URLs and `on*` event handlers. In terminals with OSC 8
hyperlink support, these could become risky clickable terminal links.

This hardens HTML rendering for untrusted email content and addresses.

FromSi created

83b3fd9 fix(fetcher): wait for IDLE goroutines (#1342)

Click to expand commit body
## What?

Track every IDLE watcher goroutine on the `IdleWatcher` via
`sync.WaitGroup` so `StopAllAndWait` catches lingering goroutines whose
map entry was already replaced. Add `StopAllAndWaitTimeout` for shutdown
paths that need a bounded wait, and switch the daemon shutdown from the
fire-and-forget `StopAll()` to the bounded variant so one stuck IMAP
connection cannot block the daemon.

## Why?

Closes #731 (filed by @andrinoff). The existing pattern in
`fetcher/idle.go:48-60` and `:72-75` does `close(existing.stop);
delete(w.watchers, account.ID)` and leaves the goroutine to tear down in
the background. If the IMAP connection is stuck (server stops responding
mid-IDLE, network hangs without RST), the goroutine never exits, the map
no longer holds the `done` channel, and `StopAllAndWait()` has no way to
see it. The original report's suggested fix was "use WaitGroup or ensure
goroutines terminate within timeout" - this PR does both.

The daemon side surfaces the problem: `daemon/daemon.go:129` previously
called `idleWatcher.StopAll()` and immediately continued to
`closeAllClients()`. If any underlying connection hung, the lingering
IDLE goroutines outlived the daemon's shutdown path with no log entry.
The new bounded-wait shutdown logs `idle watcher: stop timed out` when
goroutines don't exit within 5s, so operators see leaks instead of
silently losing them.

Two new tests cover both behaviors: replaced-goroutine tracking via
WaitGroup, and timeout-on-slow-exit returning `ErrStopTimeout`.

Fixes #731

Matt Van Horn created

e0cb01c feat: spellcheck and suggestions (#1362)

Click to expand commit body
## What?

Adds spellcheck library, `dict` CLI command, suggestions, and more

## Why?

Closes #1160

---------

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

Drew Smirnoff , Lea , Andriy Chernov , and Steve Evans created

5a83030 fix(fetcher): close debug files (#1337)

Click to expand commit body
## What?

Adds cleanup for the shared `DEBUG_IMAP` debug file handle.

The shutdown path now closes debug files before exiting, including code
paths that call `os.Exit`, and logs any close error through
`loglevel.Debugf`.

## Why?

Closes #715.

A deferred cleanup in `main()` is skipped when the process exits via
`os.Exit`, which could leave the `DEBUG_IMAP` file descriptor open for
the lifetime of the process. Closing it through the shared exit path
makes cleanup reliable across CLI and daemon exits.

---------

Co-authored-by: FromSi <fromsi665@gmail.com>

Md Mushfiqur Rahim and FromSi created

5fee465 chore: migrate goreleaser config (#1360)

Click to expand commit body
## What?

Migrates `brews` to `homebrew_casks`.

THIS WILL LOSE SUPPORT FOR LINUX HOMEBREW

## Why?

Since [goreleaser
v2.1.6](https://github.com/goreleaser/goreleaser/releases/tag/v2.16.0)
`brews` was fully depreciated

---------

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

Drew Smirnoff created

6c7f04b fix(editor): check temp close (#1339)

Click to expand commit body
## What?

Checks `tmpFile.Close()` when preparing the temporary file for the
external editor.

If closing the temp file fails, the temp file is removed and an
`EditorFinishedMsg` with a contextual error is returned.

## Why?

Closes #728.

Ignoring `tmpFile.Close()` could hide failures that happen while
flushing the written email body before opening the external editor.
Returning the close error makes editor startup failures explicit and
prevents continuing with an unreliable temp file.

---------

Co-authored-by: FromSi <fromsi665@gmail.com>

Md Mushfiqur Rahim and FromSi created