Releases: peltonapp/Pelton
Release list
v2026.4.1
Changes
- chore: add codeowners -
@TRC-Loop in #363
- chore: change emails to @pelton.app addresses -
@TRC-Loop in #360
- chore: change emails to @pelton.app addresses -
@TRC-Loop in #361
- chore: point the flatpak manifest at the 2026.4 tarball -
@TRC-Loop in #350
- chore(deps): Bump the frontend-dependencies group across 1 directory with 10 updates -
@dependabot[bot] in #359
- chore(deps): Bump the go-dependencies group across 1 directory with 8 updates -
@dependabot[bot] in #396
- ci: build and test every pull request -
@TRC-Loop in #364
- docs: match the wails generator's blank lines in hand-written bindings -
@TRC-Loop in #393
- docs: overhauled docs -
@TRC-Loop in #394
- docs: say "Powered by Zensical" in the footer instead of "Made with" -
@TRC-Loop in #400
- feat: add Turkish (tr) locale -
@xdaxer in #379
- feat: bind message actions to their webmail letters -
@TRC-Loop in #390
- feat: choose the start menu and desktop shortcuts when installing -
@TRC-Loop in #413
- feat: deleting the open message opens the next one -
@TRC-Loop in #408
- feat: play embedded video and audio once remote content is allowed -
@TRC-Loop in #395
- feat: ship a portable windows exe alongside the installer -
@TRC-Loop in #412
- feat: show shortcut hints outside the message list -
@TRC-Loop in #389
- fix: a folder that fails to sync is reported as a clean sync -
@TRC-Loop in #373
- fix: a saved view that vanishes leaves the list showing it -
@TRC-Loop in #414
- fix: database is locked when writing during a sync -
@TRC-Loop in #392
- fix: deleting the open saved view leaves the list on it -
@TRC-Loop in #382
- fix: demo mode shows real mail before the first reload -
@TRC-Loop in #391
- fix: imported mailboxes never sync and never ask for a password -
@TRC-Loop in #372
- fix: keep the draft release tagged when updating its notes -
@TRC-Loop in #348
- fix: keep the release changelog under github's body limit -
@TRC-Loop in #346
- fix: mcp threat model comment still claims read-only tools -
@TRC-Loop in #362
- fix: moving a message into its own folder reports a silent success -
@TRC-Loop in #383
- fix: one line per pull request in the release changelog -
@TRC-Loop in #347
- fix: opening a folder or a crash report does nothing -
@TRC-Loop in #371
- fix: point sibling-repo links at their actual peltonapp names -
@TRC-Loop in #399
- fix: saving a keyword search as a view leaves the name blank -
@TRC-Loop in #374
- fix: search chips widen the bar over the reading pane -
@TRC-Loop in #411
- fix: search paging can repeat and skip messages -
@TRC-Loop in #365
- fix: select can be followed by no mailbox selected -
@TRC-Loop in #366
- fix: your own authenticated mail is no longer flagged as impersonation -
@TRC-Loop in #410
- ops: added nix flake for packaging -
@TildeEthDoUsPart in #355
- release: 2026.4.1 -
@TRC-Loop in #415
- test: add a frontend test runner and cover the logic modules -
@TRC-Loop in #409
- test: add an imap client seam to the desktop bindings -
@TRC-Loop in #405
- test: check the locale catalogs agree with english -
@TRC-Loop in #406
- test: cover autoconfig, credentials, configsync and oauth -
@TRC-Loop in #388
- test: wait for background goroutines before a test's store closes -
@TRC-Loop in #407
Full Changelog: v2026.4...v2026.4.1
Checksums
SHA-256 of every file on this release, also published as SHA256SUMS.txt, which sha256sum -c reads directly.
| File | SHA-256 |
|---|---|
Pelton-v2026.4.1-linux-amd64 |
b9256a60488b75db3e74d3bd6d6c4eeca1dc3fead02846ab1e81171bf3c3e3af |
Pelton-v2026.4.1-linux-amd64.deb |
4684176713e49c23a1dbf2a7d0bc60e38421e478c06038fd227a830345f4fc1f |
Pelton-v2026.4.1-linux-fedora-x86_64.rpm |
a01044e7d7ed694d3fb9341e2dc3c4d82278a4a027bc0cde045c2b32871d2174 |
Pelton-v2026.4.1-macos-applesilicon-app.zip |
83fcc017e00ea3d4c62e7743b2600a9cc18d33d638eab233589594da639cbc65 |
| `Pelton-v2026.4.1-macos-applesilicon... |
Nightly nightly-2026.09.15 (untested, not a release)
Caution
This is not a release. Do not use it with your real inbox.
This is an automated nightly build of Pelton, made from the dev
branch. It has not been reviewed, tested or released, and it is
expected to break.
It can lose or damage email. It may fail to send, send the wrong
thing, delete messages on your server, or corrupt its local cache of
your mail. Deletions on an email server can be permanent and cannot
be undone by us.
Use a test account whose contents you can afford to lose entirely.
There is no warranty of any kind and no support. You download
and use this build entirely at your own risk. To the fullest extent
permitted by law, the authors and distributors of Pelton accept no
liability for any loss of or damage to data, for lost or misdirected
email, or for any other loss or damage arising from its use. The full
warranty and liability terms are at https://pelton.app/terms and in
DISCLAIMER.md.
If you want a working email client, download a
real release
instead.
Installing alongside a normal Pelton
A nightly is deliberately kept separate from a real install and the two
can sit side by side:
- it installs as Pelton Nightly with its own icon,
- it keeps its own accounts, mail and settings in a separate data
directory, so it cannot touch or corrupt your normal install's mail, - on Linux it is the
pelton-nightlypackage with apelton-nightly
binary, and it does not register itself as yourmailto:handler.
Nightlies older than 14 days are deleted automatically.
Built from dev at f0a27e2.
v2026.4
Pelton 2026.4
Changes
- chore: drop the minimize-to-tray option -
@TRC-Loop in #189
- chore: Enable blank issues in issue template configuration -
@TRC-Loop in #338
- chore: point dependabot at dev from the branch it reads -
@TRC-Loop in #260
- chore: put PGPKeyDTO in the order the wails generator writes -
@TRC-Loop in #224
- chore: stamp 2026.4 in the appstream release history -
@TRC-Loop in #345
- chore: untrack frontend/package.json.md5 -
@TRC-Loop in #221
- chore(deps): bump echo to 4.15.3 for the static route bypass fix -
@TRC-Loop in #343
- chore(deps): Bump github.com/labstack/echo/v4 from 4.13.3 to 4.15.3 in the go_modules group across 1 directory -
@dependabot[bot] in #339
- chore(deps): Bump the frontend-dependencies group across 1 directory with 9 updates -
@dependabot[bot] in #295
- chore(deps): Bump the go-dependencies group across 1 directory with 7 updates -
@dependabot[bot] in #319
- chore(deps): bump wails, sqlite and five frontend packages -
@TRC-Loop in #258
- chore(deps): go and frontend dependency bumps, and target dependabot at dev -
@TRC-Loop in #182
- ci: rebuild the docs when the theme overrides change -
@TRC-Loop in #233
- Delete on backspace, and shortcut hints in the right-click menu -
@TRC-Loop in #331
- Detect tracking pixels and keep them blocked -
@TRC-Loop in #263
- docs: document the menu bar access keys -
@TRC-Loop in #289
- docs: link the discord invite directly and add it to the docs site -
@TRC-Loop in #230
- feat: alt key access to the in-app menu bar -
@TRC-Loop in #274
- feat: close the window with cmd+w without quitting -
@TRC-Loop in #243
- feat: command palette with fuzzy search for actions, mail and settings -
@TRC-Loop in #212
- feat: create, rename and delete imap folders -
@TRC-Loop in #190
- feat: decrypt and verify received pgp mail -
@TRC-Loop in #227
- feat: delete moves mail to the trash -
@TRC-Loop in #284
- feat: developer overlays for activity, process and frame timing -
@TRC-Loop in #296
- feat: dismissible password prompt with a mailbox warning marker -
@TRC-Loop in #294
- feat: empty trash from the folder context menu -
@TRC-Loop in #209
- feat: flags in the language picker -
@TRC-Loop in #305
- feat: flatpak packaging for flathub -
@TRC-Loop in #210
- feat: label mail handed to mcp agents as untrusted -
@TRC-Loop in #283
- feat: mark folders that are not syncing -
@TRC-Loop in #287
- feat: mcp write actions with per-tool permissions -
@TRC-Loop in #307
- feat: more view icons for everyday categories -
@TRC-Loop in #208
- feat: native window frame, cursors and calmer setup flow -
@TRC-Loop in #241
- feat: nightly builds from dev with their own identity and warnings -
@TRC-Loop in #177
- feat: opt-in revocation checking for s/mime certificates -
@TRC-Loop in #306
- feat: option to minimize to the notification area on Windows -
@TRC-Loop in #180
- feat: pgp key storage, import and passphrase handling -
@TRC-Loop in #213
- feat: profiles -
@TRC-Loop in #299
- feat: reading-pane tabs -
@TRC-Loop in #297
- feat: remember the window size and position across launches -
@TRC-Loop in #249
- feat: reorder and pin sidebar folders, and pick a startup selection -
@TRC-Loop in #198
- feat: save an eml copy when archiving -
@TRC-Loop in #275
- feat: scan links and attachments with VirusTotal -
@TRC-Loop in #207
- feat: setting for whether the close button quits or keeps running -
@TRC-Loop in #172
- feat: settings editors open as modals -
@TRC-Loop in #301
- **feat: sign and encrypt fr...
v2026.3.4
Changes
ci: build before publishing so releases and nightlies ship complete -
@TRC-Loop in #200
Both workflows built their release after announcing it, which is backwards in two different ways.
Releases: build on the tag, not on publish
release.yml only ran on release: published, so publishing a draft started a 15-minute wait during which the release was live and empty. Anyone arriving in that window found a version with nothing to download.
Builds now run on the tag push instead. Pushing v1.2.3 has draft-release.yml write the changelog into a draft while this workflow fills that same draft with installers. By the time you look at it, everything is attached, and publishing is an instant manual click that rebuilds nothing.
A draft job waits for the release to appear before the builds finish (the two workflows react to the same push, and the changelog job is normally done in seconds). If it never shows up, it creates an empty draft itself rather than losing a whole build to a missing upload target.
Copr still waits for publish. It pushes to a live dnf repo that real users install from, so it must not fire while the release is an unpublished draft. It is the only job left on the release: published trigger.
workflow_dispatch gained an optional tag: with one it builds and uploads into that tag's existing release, which repairs a draft whose build failed or one tagged before this change. Without one it behaves as before and uploads nothing.
Nightlies: publish only what actually built
The prerelease was created first so three jobs could upload into it in parallel. A failed build therefore left a nightly on the releases page that was empty or half-filled, and looked downloadable.
The three platform jobs now stage their installers as artifacts, and a new publish job creates the prerelease with all of them attached in one go. It only runs when every platform succeeded, so a broken build publishes nothing at all and yesterday's nightly stays the newest thing on the page. prune follows publish rather than the build jobs.
The warning body, the same-day replace behaviour and the retention pruning are unchanged.
Notes
- Verified with
actionlint(clean) and a YAML parse of all three workflows. - This is on
mainbecause that is where releases are cut and where the scheduled nightly runs from. It will reachdevwith the back-merge.
fix: imported mailboxes could never be given a password -
@TRC-Loop in #214
A mailbox imported from another mail client could never sync, never explained why, and offered no way to fix it.
What was wrong
The Thunderbird/mbox importer creates the account row from the other client's server settings, but it cannot take that client's stored password with it, so no keyring secret is ever written. resolveIMAP then falls through to the environment-credential path meant for the legacy cli account, which does not match, and the connection fails with errNoCredentials.
There was no way out of that state from inside the app. UpdateAccountRequest carried display name, username and the four server fields, and no password at all, so editing the mailbox could not supply one either. The account just sat there failing.
The fix
You can now enter a password when editing a mailbox. UpdateAccountRequest gains an optional Password; empty leaves the stored secret alone, so an edit that only moves a port does not force you to retype it. The field is placeheld differently depending on whether a password exists, and a mailbox with none shows a short explanation of why.
Sync prompts for what is missing. AccountsNeedingPassword reports accounts with nothing in the keyring, and runSync asks about each one before syncing, one dialog at a time.
Cancelling is a real answer. Skip leaves that account alone and syncs the rest rather than blocking everything, and the skip is remembered for the session so an automatic sync every few minutes does not turn into a prompt every few minutes. It comes back next launch, because the account genuinely is still broken.
Details worth noting
- Storing a password over an OAuth account is refused. Gmail and Outlook accounts sign in with a token; quietly replacing that with a password would produce a login the provider rejects, so
SetAccountPasswordreturns an error instead. - Only a definite "nothing stored" prompts. A keyring that is locked or unreadable returns a different error, and treating that as "no password" would ask the user to retype one they already gave.
needsPasswordchecks forErrNotFoundspecifically. - The legacy cli account is excluded, since its password comes from the environment and it is not actually missing one.
Testing note
credentials.Load reads the real OS keyring, so a test that calls AccountsNeedingPassword against a fresh database still collides with whatever the developer running it has installed under account id 1. The decision is therefore factored into needsPassword, which takes the lookup error as an argument and is tested directly. Worth remembering for anything else that touches credentials.
Verification
go build, go vet and the desktop tests pass, including new coverage for the missing/present/unreadable keyring cases and the env-backed account. pnpm run check is 0 errors and 0 warnings; the frontend build succeeds. Six locales.
fix: nightly publish and prune failing without repo context -
@TRC-Loop in #204
Both of last night's nightly runs failed. All three platforms built and staged
their installers correctly; the new publish job is what died:
failed to run git: fatal: not a git repository (or any of the parent directories): .git
publish only downloads artifacts and calls gh, so it has no
actions/checkout. Without a checkout there is no git remote for gh to infer
the repository from, and gh release create exits 1 before creating anything.
The draft job in release.yml passes --repo "$GITHUB_REPOSITORY" for the
same reason; that was not carried over to nightly.yml in #200.
This also caused the double run: the first failure never created the tag that
tells the next run there is nothing left to build.
prune had the same bug, silently
prune reports success but has never worked. From the last nightly that
actually ran (2026-08-07):
prune 2026-08-07T13:47:20 failed to run git: fatal: not a git repository
prune conclusion: success
Same missing repo context. It is reported as a success because
gh release list | while read takes the exit status of the while, not of
gh, so the failure is swallowed. Nightlies have therefore never been pruned,
despite the release body promising it. Nothing is currently overdue, so this
deletes nothing on the next run.
Change
Four gh calls gained --repo "$GITHUB_REPOSITORY". The three
gh release upload calls in release.yml are left alone: those jobs do check
the repository out.
The pipeline that masks prune's errors is deliberately left as-is.
Verified with actionlint (clean) on both workflows.
Summary
- Added
--repo "$GITHUB_REPOSITORY"to fourghcommands in the nightly publish and prune jobs. - Fixed release creation and release listing when jobs do not check out the repository.
- Prevented nightly publish failures and repeated builds caused by missing repository context.
- Kept the existing prune error-masking pipeline unchanged.
- Left the three
gh release uploadcommands inrelease.ymlunchanged. - Verified both workflows with
actionlint.
AI use
Probably AI-assisted. The change appears to use AI for summarization or review support, but there is no clear evidence of 100% agentic implementation.
Full Changelog: v2026.3.3...v2026.3.4
Pelton is free software under the GPL-3.0, provided without warranty and used at your own risk. It connects to your real mailboxes, deletions can be permanent, and Pelton is not a backup tool. Keep your own backup of anything you cannot afford to lose.
Warranty and liability: DISCLAIMER.md - pelton.app/terms
v2026.3.3
Pelton can now read your mail out of the client you are leaving.
This release contains that one feature and nothing else.
Import from another mail client
Switching used to mean starting from nothing: every account retyped by hand, and any local-only mail left behind. Both halves are covered now.
Your accounts. Pelton reads Thunderbird's configuration and offers to recreate the mailboxes, so you do not retype six servers and ports. It looks where Thunderbird actually installs:
- Linux the distro package, the Flatpak and the Snap, all three
- macOS
~/Library/Thunderbirdand~/Library/Application Support - Windows
%APPDATA%\Thunderbird
If your profile lives somewhere else, you can point at the folder yourself. Passwords cannot come across, so each mailbox asks for its password once.
Your mail. Single messages (.eml), whole archives (.mbox), and Thunderbird's own local folders, including nested ones. Read and flagged state comes with them. Importing the same file twice does not duplicate anything.
Large archives import in the background with a progress bar, so a multi-gigabyte mbox does not freeze the window.
Where to find it
Adding a mailbox now starts by asking whether you are setting one up or coming from another client. That choice appears wherever you add a mailbox: first run, the sidebar, the Mailbox menu, and Settings. There is also a direct entry under Settings, External.
Imported mail stays local
It lands in a new Local Folders section that has no server behind it. It is never synced, never uploaded, and never folded into the unified inbox, so importing a decade of old mail does not bury what is actually new. The section only appears once you have imported something.
Your old client is not touched
Pelton only reads. It never writes, renames or deletes anything in another program's mail store, and it leaves no cache or marker behind. That includes modification times, so the client you are migrating from cannot tell the difference. It is safe to point at a profile you are still using, and safe to run twice.
Nothing about the import touches the network.
Full Changelog: v2026.3.2...v2026.3.3
v2026.3.2
Changes
This release is about one thing: making clear, in every place Pelton is handed to you, that it comes without warranty and what that means for your mail.
Terms
DISCLAIMER.mdships with Pelton: warranty and liability as an additional term under GPLv3 section 7(a), German authoritative with an English translation, also published at pelton.app/terms.- The Windows installer shows a liability page after the GPL page.
- The
.deb, the.rpmand the macOS app bundle carryLICENSEandDISCLAIMER.md. SECURITY.mddocuments the private reporting path for vulnerabilities.
In the app
- Onboarding asks you to acknowledge the notice before setup continues. Installs that predate this are asked once on next start.
- Settings, About Pelton has a new "Warranty and liability" entry next to the license links.
Fewer ways to lose data by accident
- Importing a configuration now lists which categories it is about to overwrite and asks before writing. It used to replace settings, mailboxes, the remote-image whitelist and signatures on a single click, with no way back.
- Removing an address book contact asks first.
- The mailbox deletion prompt now names what is removed from this device (downloaded mail, attachments, the saved password) and says that mail on the server is not touched.
All new wording is available in English, German, French, Dutch, Spanish and Polish.
Full Changelog: v2026.3.1...v2026.3.2
Pelton is free software under the GPL-3.0, provided without warranty and used at your own risk. It connects to your real mailboxes, deletions can be permanent, and Pelton is not a backup tool. Keep your own backup of anything you cannot afford to lose.
Warranty and liability: DISCLAIMER.md - pelton.app/terms
v2026.3.1
Highlights
- Views can now match on multiple sender and recipient addresses, and support regular expressions for text, from, to and subject.
- Settings are reorganized into clearer groups with a search box that finds individual settings, not just categories.
- New offline indicator in the status bar. When there is no connection, sync and the raw-source viewer say "No internet connection" instead of confusing credential or host errors.
- Unified Inbox and the built-in view names (Inbox, Flagged, Drafts, Sent, and more) are now fully localized.
- Optional fullscreen empty-state background image for the reading pane, off by default.
- New "This email" action to load remote content for a single message, remembered across syncs.
- Polish language support.
Changes
feat: add Polish (pl) locale -
@TRC-Loop in #153
Closes #140.
Adds a Polish (pl) locale.
Changes
- New
frontend/src/lib/locales/pl.tstranslating every key fromen.ts. Key set is at exact parity with en.ts (verified by diff); placeholder tokens ({count}, {who}, {when}, {version}, {n}, {field}, {folder}, {size}, {mailbox}, {author}, {detail}) are preserved verbatim, and technical terms (IMAP, SMTP, OAuth, Gravatar, BIMI, PGP, SPF/DKIM/DMARC, MCP, TLS/SSL/STARTTLS, Markdown, HTML, Vim, proxy) are left untranslated. - Registered
plin the i18n loader/selector (Localetype,localesarray,localeNames-> "Polski", dynamic import map), so it is selectable in Settings. - Extended the Go-side locale tables so Polish users also get native strings: built-in locales set (
bind_locales.go), new-mail notifications (notify.go), and the native menu bar (menu_i18n.go). - No em-dashes in any string.
Verification
- pl.ts key set diffs clean against en.ts.
- go build, go test (internal/desktop), svelte-check and pnpm build all pass.
Note: this is a complete first-pass translation; a native-speaker review pass is welcome as a follow-up.
feat: fullscreen empty-state background toggle -
@TRC-Loop in #152
Closes #148.
Adds an option to show the empty-state image as a full-screen background of the reading pane, instead of the small centered mark.
Changes
- New
emptyStateFullscreenboolean preference, off by default. - When on (and an empty-state image is set), the reading pane renders that image as a full-bleed
coverbackground when no message is open. Otherwise the existing small, faded, centered mark is unchanged. - Toggle added in Settings next to the empty-state image picker; it is disabled until an image is chosen.
- Wired through backend setting (
empty_state_fullscreen), UIPrefsDTO, prefs store + setter, api key, types, and generated bindings. - i18n keys added to all five locales (en/de/fr/es/nl).
Verification
- go build, svelte-check, and pnpm build all clean.
feat: group and rebalance settings categories with per-setting search -
@TRC-Loop in #151
Closes #130.
The settings panel had ~20 flat categories with a badly overloaded Appearance section and several near-empty ones. This groups and rebalances them and adds real per-setting search. Every existing setting is preserved, only relocated.
Categories: 24 → 16, grouped under 6 headings
- Appearance now holds theming only: theme/schedule, accent, density, corners, interface scale, reduce motion, empty-state image.
- Menu bar (new): the whole macOS menu-bar cluster pulled out of Appearance.
- Reading & display = Display + Panes + all three font pickers (body/UI/mono moved out of Appearance).
- Message list = List + Sidebar + Avatars.
- Composing & sending = Composing + Sending.
- Privacy & network = Privacy + Network.
- Accounts = Mailboxes + Contacts.
- Backup & integrations = External + Import/Export.
- Sync & power = Power + Offline/download.
- Unchanged: Themes, Language, Signatures, Notifications, Gestures, Shortcuts, About.
Nav groups: Appearance / Mail / Privacy / Accounts / Advanced / About. Merged sub-groups get a labeled divider so nothing reads as a jumble.
Per-setting search
Typing filters the nav and shows a flat results list of individual settings by their own label (e.g. proxy, gravatar, vim, undo send, swipe, backup), each tagged with the category it lives in; clicking jumps straight there.
Spacing and space
- Hints now hug the control they describe with a clear gap below, so they read as part of that setting instead of floating between two.
- Content column widened 560 to 720px.
i18n / verification
- New keys (groups, per-category keywords, new category labels, Menu bar) added to all five locales (en/de/fr/es/nl), files at parity.
- Every category key maps 1:1 to a render block; no setting removed.
- svelte-check clean, pnpm build clean.
feat: multi-address chips and regex matching in views -
@TRC-Loop in #150
Closes #149.
Saved views can now filter with multiple sender/recipient addresses and match content with regular expressions.
Changes
- Multi-address chips for From / To. The single-line
fromandtoinputs are now chip inputs: type an address, press Enter/comma/semicolon (or blur) to add it, remove with backspace or the x. A message matches the field when it matches any chip (OR within the field); fields still AND with each other. - Regex toggle. A per-view "Use regular expressions" option treats the text/from/to/subject criteria as regular expressions instead of plain substrings. Invalid patterns are rejected on save; a view whose regex fails to compile at run time matches nothing rather than breaking the sidebar.
Implementation
- Plain single-address views keep the existing full-text index path (unchanged behavior/perf). Regex or multi-address views take a scan-and-filter path: read the newest messages in scope (capped by
maxViewScan), then match in Go. Matches stay capped atmaxViewMatches. - Storage: new
use_regexcolumn (migration 0012);query_from/query_tonow hold a newline-separated address list. Existing single-address views load as one-item lists, so nothing breaks on upgrade. - Plain matching is case-insensitive substring; regex is matched as written (use
(?i)for case-insensitive). - i18n keys added to all five locales. Generated Wails bindings updated for the new DTO shape.
Tests
internal/desktop/bind_views_test.go: multi-address OR, case-insensitive plain match, regex alternation, invalid-regex rejection, and field ANDing.- Full
go test ./internal/...,svelte-check, andpnpm buildpass.
feat: persistent per-message remote content allow -
@TRC-Loop in #154
Closes #136.
Adds a persistent per-message remote-content allow, so a newsletter or receipt you reopen often can render remote images every time without trusting the whole sender or domain.
Approach
Chose option 1 from the issue: a fourth banner action, This email, alongside "Load once" / "This sender" / "This domain". It is non-modal and does not change what "Load once" does (which stays ephemeral).
Changes
- Backend
AllowRemoteForMessage(messageID)records the message in a newremote_allow_messagessetting. It is keyed by the RFC Message-ID header (lowercased/trimmed) so the allow survives re-sync, expunge and a changed local row id; when a message has no Message-ID it falls back tolocal:<row id>. GetMessagenow renders remote content when the message is individually allowed:remoteAutoAllow(from) || remoteMessageAllowed(m). The existing global / sender / domain paths are untouched, so privacy defaults (blocked by default) are unchanged and this stays an explicit per-message opt-in.- Frontend: new banner button wired to
allowRemoteForMessage; on click it persists and renders remote content immediately. New i18n keys added to all five locales (en/de/fr/es/nl). No em-dashes. - Generated Wails bindings + api wrapper updated for the new method.
Tests / verification
internal/desktop/bind_images_test.go: Message-ID keying and local fallback.- go build, go test (internal/desktop), svelte-check and pnpm build all pass.
Full Changelog: v2026.3...v2026.3.1
v2026.3
Changes
chore(deps): Bump the frontend-dependencies group across 1 directory with 11 updates -
@dependabot[bot] in #118
Bumps the frontend-dependencies group with 11 updates in the /frontend directory:
| Package | From | To |
|---|---|---|
| @fontsource/familjen-grotesk | 5.2.8 |
5.3.0 |
| @fontsource/spline-sans-mono | 5.2.8 |
5.3.0 |
| @tabler/icons-svelte | 3.44.0 |
3.45.0 |
| @tiptap/core | 3.27.3 |
3.28.0 |
| @tiptap/extension-link | 3.27.3 |
3.28.0 |
| @tiptap/pm | 3.27.3 |
3.28.0 |
| @tiptap/starter-kit | 3.27.3 |
3.28.0 |
| marked | 18.0.6 |
18.0.7 |
| svelte | 5.56.4 |
5.56.7 |
| svelte-check | 4.7.2 |
4.7.3 |
| vite | 8.1.4 |
8.1.5 |
Updates @fontsource/familjen-grotesk from 5.2.8 to 5.3.0
Commits
- See full diff in compare view
Updates @fontsource/spline-sans-mono from 5.2.8 to 5.3.0
Commits
- See full diff in compare view
Updates @tabler/icons-svelte from 3.44.0 to 3.45.0
Release notes
Sourced from @tabler/icons-svelte's releases.
Release 3.45.0
20 new icons:
filled/brand-signaloutline/app-window-bottom-leftoutline/app-window-bottom-rightoutline/app-window-bottomoutline/app-window-centeroutline/arrow-fork-tripleoutline/brand-signaloutline/device-vision-pro-wifioutline/device-workstationoutline/dragonoutline/italic-offoutline/tab-closeoutline/text-outlineoutline/text-regex-asteriskoutline/text-regex-endoutline/text-regex-plusoutline/text-regex-questionoutline/text-regex-startoutline/underline-offoutline/virtual-spaceNew features
- New package:
@tabler/icons-astro— Astro support- Added
sideEffects: falsefor better tree-shaking in Vue package- Spelling fixes: corrected misspelled icon names
Fixed icons:
outline/flip-horizontal,outline/flip-verticalRenamed icons:
filled/mood-confuzedrenamed tofilled/mood-confusedoutline/brand-adobe-after-effectrenamed tooutline/brand-adobe-after-effectsoutline/brand-kako-talkrenamed tooutline/brand-kakao-talkoutline/currency-rubelrenamed tooutline/currency-rubleoutline/foodstepsrenamed tooutline/footstepsoutline/gender-trasvestirenamed tooutline/gender-travestioutline/ikosaedrrenamed tooutline/icosahedronoutline/mood-confuzedrenamed tooutline/mood-confusedoutline/physotherapistrenamed tooutline/physiotherapistoutline/sport-billardrenamed tooutline/sport-billiard
Commits
975920fRelease 3.45.04a4b287Add Astro support for Tabler Icons (#1559)- See full diff in compare view
Updates @tiptap/core from 3.27.3 to 3.28.0
Release notes
Sourced from @tiptap/core's releases.
v3.28.0
@tiptap/extension-detailsPatch Changes
- 8614730: Fix the cursor moving to the details summary after typing in content at the start of a document.
@tiptap/core@3.28.0
@tiptap/extension-listPatch Changes
- 8614730: Fix markdown parsing a line like
(216) 555-1234as an ordered list. A number followed by)mid-line is no longer treated as a list marker.@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/reactPatch Changes
- 8614730: Batch React node view portal store notifications that happen in the same microtask to avoid nested update depth warnings when many node views mount together.
- 8614730: Bind onMount and onUnmount event handlers when initializing an Editor with useEditor hook.
@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaboration-caretPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaborationPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-drag-handlePatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version- Updated dependencies [8614730]
@tiptap/extension-collaboration@3.28.0
... (truncated)
Changelog
Sourced from @tiptap/core's changelog.
3.28.0
Patch Changes
@tiptap/pm@3.28.03.27.4
Patch Changes
@tiptap/pm@3.27.4
Commits
c5f4b57chore(release): release new stable release (#8038)24263ecchore(release): publish a new stable version- See full diff in compare view
Updates @tiptap/extension-link from 3.27.3 to 3.28.0
v1.0.9
Pelton 1.0.9.
Highlights
- IMAP/SMTP username auth — accounts whose login name differs from the email address can now be added and edited, plus an explicit SMTP security (SSL/TLS vs STARTTLS) selector. (#108)
- Outbound proxy — new Preferences → Network section routing all connections (IMAP, SMTP, and web calls) through a SOCKS5 or HTTP proxy, or the system proxy environment, with keyring-stored auth. (#110)
- Linux
.deb+ raw binary now published alongside the Fedora.rpm.
Important
1.0.9 is the last release to use semantic versioning. From the next release Pelton moves to Calendar Versioning (YYYY.Q.INCR — year, calendar quarter, per-quarter counter). The next version will be 2026.4.0, written as 2026.4 for the flagship (first) release of the quarter. See the README "Versioning" section for details.
Changes
ci: publish linux amd64 binary and .deb alongside the .rpm -
@TRC-Loop in #112
Adds two Linux release artifacts next to the existing Fedora .rpm:
- Raw amd64 binary
Pelton-<version>-linux-amd64for users who just want to run it directly. - Debian/Ubuntu
.debPelton-<version>-linux-amd64.debbuilt with the same nfpm config.
How
- The
linux-fedorajob is renamedlinuxsince it now produces the binary, the.deband the.rpmfrom one build. - nfpm's
dependsmoved into per-packageroverrides, because the gtk3/webkit2gtk runtime has different package names on Debian vs Fedora. The.debdepends onlibgtk-3-0 | libgtk-3-0t64(the second covers Ubuntu 24.04's t64 rename) andlibwebkit2gtk-4.1-0; the.rpmkeepsgtk3/webkit2gtk4.1. - The same post-install hook that refreshes the desktop/icon caches runs on both (
.rpmposttrans,.debpostinstall). - The version step strips a leading
vfor both package formats (pkg_version).
Targets dev for the 1.0.9 release.
feat: outbound proxy settings for mail and web connections -
@TRC-Loop in #111
Closes #110.
Adds an outbound proxy option in Preferences -> Network that routes every Pelton connection through a proxy.
What
- Modes: Off, System, Manual.
- System follows the standard proxy env vars (HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY), honouring NO_PROXY per target.
- Manual supports SOCKS5 and HTTP proxies, with optional username/password.
- Covers everything: IMAP, SMTP, and the app's own web calls (autodiscovery, update check, one-click unsubscribe).
- Auth in the keyring: the proxy password is stored in the OS keyring like account secrets, never in the settings db. The UI is write-only for the password (it receives only
hasPassword, shows a placeholder, and keeps the stored secret unless you type a new one). - Test button dials a well-known endpoint through the proxy so you can confirm it works before saving.
How
- New
internal/proxypackage:Config-> a TCPDialContext(SOCKS5 viagolang.org/x/net/proxy, HTTP via a CONNECT tunnel inconnect.go, system viahttpproxy.FromEnvironment) and an*http.Clientfactory. - The IMAP/SMTP configs gain an optional
Dialhook. When no proxy is set the hook is nil and the existing direct-dial path is used unchanged - so non-proxy users are byte-for-byte unaffected. Only proxied connections take the new path (which builds the client from a pre-dialed conn, since go-imap'sDial*only accepts a concrete*net.Dialer). - Proxy preference persisted as JSON under the
proxysetting; password in the keyring. Loaded once at startup and cached onApp, refreshed bySetProxyConfig. - The three web call sites now take an
*http.Clientfrom the proxy-aware factory.
Testing
- New
internal/proxyunit tests: config validation, credential-carrying URL, dialer selection, and a stub HTTP proxy verifying the CONNECT tunnel andProxy-Authorization. go test ./internal/...,go vet,gofmtclean;svelte-checkclean.
Note
DNS resolution and the MX-probe step of autodiscovery are not tunnelled (they are not HTTP); the mail and web transports are. Full OS GUI proxy settings (macOS SystemConfiguration / Windows WinHTTP) are out of scope; System mode uses the environment variables, which is the cross-platform, GDPR-safe common denominator.
Targets dev for the 1.0.9 release.
feat: separate login username and explicit SMTP security in account setup -
@TRC-Loop in #109
Fixes #108, reported by @ahornero (Alberto). Thanks for the clear report and the offer to test.
What
Two gaps in the manual IMAP/SMTP account setup:
- Separate login username. Some servers authenticate on a username that is not the email address. The setup form assumed username == email, so those accounts could not be added. There is now an optional Username field (add wizard and mailbox editor); leave it blank to keep logging in with the email address.
- Explicit SMTP security. The advanced section only exposed IMAP security (SSL/TLS vs STARTTLS). SMTP now has the same toggle. The security choice sets the conventional port as the default; the port field stays fully editable for non-standard setups.
How
- New migration
0010_account_username.sqladds ausernamecolumn (default empty = log in with email), so every existing account keeps working unchanged. Usernamethreaded throughstorage.Account, add/update/test-connection requests, the credential resolvers (loginNamehelper: username when set, else email), backup export/import, and the DTO.- SMTP TLS mode is derived from the port (465 implicit, 587 STARTTLS), matching the existing IMAP behaviour; the new toggle just flips the conventional port.
- Wizard + mailbox editor UI, generated Wails bindings (hand-edited), and en/de/fr/es strings.
Testing
go test ./internal/...andgo vetpass.svelte-checkclean.
Targets dev for the 1.0.9 release.
fix: correct nfpm scripts placement so the .deb builds -
@TRC-Loop in #115
The 1.0.9 linux release job failed with Yaml: unmarshal errors: field posttrans not found in type nfpm.Scripts: posttrans is rpm-specific and only valid under the top-level rpm: block, not under overrides.<packager>.scripts.
Fix: keep posttrans under rpm.scripts, keep the Fedora depends at top level (used by the .rpm), and override only the .deb with its Debian dependency names plus a postinstall hook.
Validated locally with nfpm: both --packager deb and --packager rpm now build, and the .deb control lists Depends: libgtk-3-0 | libgtk-3-0t64, libwebkit2gtk-4.1-0.
macOS/Windows/Copr artifacts on 1.0.9 were unaffected; this re-cuts the linux artifacts.
Full Changelog: v1.0.8...v1.0.9
v1.0.8
Changes
chore: derive wails CLI version from go.mod in release builds -
@TRC-Loop in #86
Fixes #70.
The release workflow pinned WAILS_VERSION: v2.12.0 while go.mod moved to v2.13.0, so every release since the bump was built by the older CLI (the known class of problem where a mismatched wails CLI rewrites go.mod and the runtime bindings to its own version).
Instead of bumping the pin and hoping it stays in lockstep, the env var is gone entirely: all four install steps now derive the CLI version from the module pin itself (go list -m -f '{{.Version}}' github.com/wailsapp/wails/v2), so the CLI can never drift from go.mod again.
docs: fix icon rendering, macos steps, annotation, footer -
@TRC-Loop in #79
Docs site fixes after the first deploy:
- Icons rendered filled instead of stroked (the globe was a solid blob): the theme CSS sets
fill: currentColor, which beats SVG presentation attributes. The vendored tabler icons now carry their stroke styling as an inlinestyleattribute, which wins. - macOS install steps now describe the real first-launch flow: Done in the blocked dialog, System Settings, Privacy & Security, Open Anyway, authenticate. The
xattrone-liner stays as the shortcut. FAQ entry matches. - The container tree in the theme format spec uses a clickable code annotation for manifest.json instead of an inline comment.
- Footer privacy link reads "Privacy / Datenschutz", matching the bilingual imprint label.
Verified locally: build clean, no-CDN check passes, annotation markup and inline icon styles present in the output.
Summary
- Updated macOS installation and FAQ guidance to reflect the actual Privacy & Security → Open Anyway flow, while retaining
xattras a shortcut. - Replaced the inline
manifest.jsoncomment with a clickable theme-format annotation. - Renamed the footer link to Privacy / Datenschutz.
- Applied inline stroke styling to vendored Tabler icons.
- Confirmed a clean build, no-CDN compliance, and expected annotation/icon markup.
AI usage
Not Likely — no explicit AI, agent, co-author, or generated-content indicators were identified. There is insufficient evidence to conclude that AI was used.
docs: zensical site for docs.pelton.app -
@TRC-Loop in #78
Sets up docs.pelton.app as a Zensical site (the successor to Material for MkDocs, by the same team), styled like Pelton itself.
Structure:
zensical.tomlat the repo root, content indocs/, vendored tabler icons inoverrides/.icons/tabler/(generated from the same @tabler package the app uses).- Pages: landing (card grid), Install (macOS/Windows/Copr dnf/raw rpm/source, in content tabs), Getting started (mailboxes, app passwords, sync, data locations, privacy defaults), Themes (overview + full .peltontheme spec + create-a-theme walkthrough), Shortcuts (keys markup), FAQ.
docs/AGENTS.mdis the machine-readable documentation;docs/llms.txtjust points to https://docs.pelton.app/AGENTS.md. The deploy copies the raw markdown to /AGENTS.md next to the rendered /AGENTS/ page.
Style: Pelton's tokens mapped onto the theme variables (light and dark, toggle defaults to the system scheme), bundled Familjen Grotesk and Spline Sans Mono, flat header with hairline border, 5px radii, tabler icons only (header repo badge, palette toggles, footer socials).
No CDNs, by design and by enforcement:
font = false(Google Fonts off), no emoji shortcodes, no math extension, all fonts/icons/scripts served from the site itself.- The deploy workflow fails if the built html/css contains any external src/link/url()/@import load. Plain text links (imprint, Apple/Google help pages) are allowed.
- Remaining "fontawesome.com" strings are license comments inside Zensical's own bundled stylesheet (inline data-URI glyphs); nothing is fetched.
Footer: copyright, pelton.app, Imprint / Impressum, Privacy, and a "For AI Agents" link to /AGENTS.md. Socials: GitHub and pelton.app with tabler icons.
Deploy: .github/workflows/docs.yml builds on pushes to main touching docs/**, zensical.toml or the workflow, runs the no-CDN check, and deploys to GitHub Pages (zensical pinned to 0.0.50). One-time setup after merge: repo Settings > Pages > Source: GitHub Actions, and a DNS CNAME for docs.pelton.app (docs/CNAME is already in the artifact).
Not included: social preview cards (Zensical 0.0.50 has no generator for them yet, revisit when it lands).
Verification: local zensical build --clean is clean, the external-load scan reports nothing, no em-dashes or slop vocabulary in the content.
Summary
- Added a Pelton-styled Zensical documentation site for
docs.pelton.app. - Documented installation, setup, themes, shortcuts, privacy, and FAQs.
- Added self-hosted fonts, icons, logos, custom CSS, light/dark themes, and custom-domain configuration.
- Added machine-readable
AGENTS.mdandllms.txt. - Added GitHub Pages deployment with a guard against external asset loads.
- Added local
site/build-output exclusion.
AI involvement
AI use is 100% — Very Likely, with strong signs of agentic assistance, including AI-generated change summaries, the AGENTS.md file, and highly structured documentation.
feat: 12/24-hour time format setting -
@TRC-Loop in #87
Fixes #62.
Adds a clock preference under Settings > Display: Auto (follows the system locale, the previous behavior and the default), 12-hour, or 24-hour.
All time rendering now goes through shared helpers in lib/format.ts that take the preference, so it applies consistently everywhere times show: message list dates, the reading-pane header, message info modal, backup file info, send-later presets, snooze presets, outbox scheduled rows, and the date picker summary. The scattered per-component toLocaleString calls were converted to the shared helpers along the way, so future call sites inherit the setting for free.
Backed by a time_format setting (stored like every other pref), default auto.
feat: auto dark mode by time of day -
@TRC-Loop in #89
Fixes #61.
Adds a fourth theme mode, Scheduled, next to System/Light/Dark in appearance settings. It switches to the dark theme inside a configurable window (default 19:00 to 07:00, two native time inputs shown while the mode is selected) and back to light outside it.
resolveThemeintheme.tslearned theschedulepreference; the window may cross midnight, and a half-typed or malformed time keeps the previous bound instead of flipping the theme.- Re-evaluated once a minute plus whenever the window regains focus, so waking from OS sleep (where a timer fires late) picks the right side of the boundary promptly.
- Follows all the existing theme plumbing: native window chrome syncs on every flip, and an active custom
.peltonthemestill pins its own base like it does for the other modes. - Times persist as
theme_dark_start/theme_dark_end("HH:MM").
feat: corner style setting -
@TRC-Loop in #102
Fixes #60
Adds the missing cosmetic from the #60 grab-bag: a corner style setting under Settings > Appearance with Square / Default / Rounded, applied live like theme and density.
The issue's other examples already landed elsewhere: accent color has its own picker, and list row styling shipped as the row template settings. Corner radius was the remaining gap. Square zeroes the radius tokens, Rounded softens them (10px controls, 12px cards); the implementation is a data-corners attribute on the root that swaps only the --radius-control/--radius-card tokens, so every component stays corner-agnostic, custom themes keep working (their radius tokens win while a theme is active with its own values), and the setting persists and exports/imports with the settings category like the other appearance options.
Note for merging: same trivial adjacent-line conflicts with the other settings-plumbing PRs (#87-#90) as they have among themselves; merge oldest-first and say the word if any need a rebase.
Verified: go build/vet/gofmt, desktop tests, svelte-check 0 errors. Labels in all five languages.
feat: default font dropdown for email bodies -
@TRC-Loop in #90
Fixes #66.
Adds a Mail body font dropdown under Settings > Display, next to the message font size. It only changes the base font-family the reader iframe's srcdoc styles set, so emails that declare their own fonts keep them; the setting is pur...