Skip to content

Repository files navigation

PurifyMail

Sort your mail. Unsubscribe from the newsletters, clear out the rest, all on your own machine.

Français · Privacy · Connecting a mailbox · MIT

PurifyMail connects to your mailboxes over IMAP and puts every sender in one list, heaviest first. Each row offers the same three decisions:

  • Unsubscribe and delete, for the newsletters, when a link exists.
  • Delete, every message that sender ever sent you, for the volume no unsubscribe link can help with: the shop that mailed 300 order updates, the tool that notifies on every click, years of alerts from a service you left.
  • Keep, and never be asked again, until you change your mind: pressing Keep on a sender you already kept puts them back in the list.

One list, both jobs. A checkbox narrows it to the senders that can actually be unsubscribed when that is what you are there for. There is no PurifyMail account, no server, and no telemetry: your mail is read on your computer and stays there.

What it does

  • Connects to Gmail, Yahoo, Proton (via Bridge), Outlook, and any IMAP server. Several mailboxes at once, in one list, filterable per mailbox.
  • Sorts one sender at a time when you want. A card view with three full-size buttons and 1 2 3 on the keyboard, for working through hundreds of senders without aiming at anything.
  • Scans the whole mailbox. Every folder, including the ones your rules fill, and on Gmail the All Mail view so archived newsletters are found too. Sent, Drafts and Trash are skipped, and your own address is never treated as a sender: what you wrote never appears in the list and can never be deleted from it.
  • Rescans in seconds, not minutes. After the first pass, only messages the app has never seen are downloaded, and anything deleted elsewhere is noticed without re-reading the mailbox.
  • Finds newsletters properly. Standard headers (List-Unsubscribe, List-ID, Precedence), sending-platform fingerprints (Mailchimp, SendGrid, Brevo, Klaviyo, MailPoet, and a dozen more), address patterns, French and English wording, plus how often a sender writes to you. Missing a newsletter is treated as worse than flagging a sender you like, because one costs a click and the other stays invisible.
  • Reads the message when the headers say nothing. Plenty of small senders declare no List-Unsubscribe at all and bury the link in the footer: WordPress and MailPoet lists, self-hosted newsletters. PurifyMail opens a few recent messages and finds it, matching on the wording near the link rather than only inside it.
  • Unsubscribes properly. RFC 8058 one-click, then a plain request, then the confirmation page many senders answer with, whose form is filled in and submitted. When nothing works automatically, every link in the message is put in front of you, likeliest first, so no sender is ever a dead end.
  • Groups a sender across its addresses. bounce-9987@e.brand.com and news@mail.brand.com land on the same row.
  • Keeps some, deletes the rest. Click a sender's name to see their messages one by one, tick the few worth keeping, and send the others to Trash. For the shop that sent 300 order updates and four invoices.
  • Actually cleans up. Deleting a sender asks your server for every message from them, across every scanned folder, not just what the last scan cached. Unsubscribing deletes too, by default; switchable off.
  • Never destroys anything. Deleting moves messages to your mailbox's Trash. No EXPUNGE, ever.
  • Works in the background. Decisions are queued and carried out while you keep sorting; unsubscribes run six at a time so a dead endpoint never holds up the queue.
  • Asks for as little as possible. Your address picks your provider, the app password can be pasted with the spaces your provider printed, and a button opens the exact page that creates one. On a company server, Find it works the hostname out from your own domain.
  • Speaks French and English, both written rather than translated.

Install

Download the installer for your system from the Releases page.

System File
Windows PurifyMail_x.y.z_x64-setup.exe
macOS PurifyMail_x.y.z_universal.dmg
Linux purifymail_x.y.z_amd64.AppImage or .deb

"Unknown publisher" on first launch

The binaries are not code-signed. Signing is expensive, roughly €300 a year for a Windows certificate and $99 a year with Apple, and PurifyMail has no budget. Your system will therefore warn you the first time:

  • Windows: "Windows protected your PC". Click More info, then Run anyway.
  • macOS: "cannot be opened because the developer cannot be verified". Right-click the app, choose Open, then Open again in the dialog.
  • Linux: make the AppImage executable with chmod +x.

If that makes you uncomfortable, it should: build from source instead, the steps are just below.

Then open PurifyMail and follow Connecting a mailbox. The short version: Gmail, Yahoo, and Outlook need an app password, not your usual one, and Proton needs Proton Bridge running.

Using it

  1. Connect a mailbox. Pick your provider; the server settings fill in themselves. Press Test connection before saving: it tells you straight away whether the credentials work.
  2. Scan. The first scan reads every message header in the mailbox and then opens a few messages from the senders that declared no unsubscribe link, so a large account takes several minutes. It is done once: everything triage needs is kept locally, so sorting afterwards never waits on the network. You can stop it at any point; what was found is kept.
  3. Sort. Senders are listed by volume, heaviest first. Work through the list, or switch to the one-by-one view and use 1 2 3 on the keyboard. Tick several rows to act on them together. Decisions are carried out in the background, so you never wait on one to make the next.
  4. Check your Trash if you deleted something and changed your mind.

Building from source

You need Node.js 20+ and Rust, plus your platform's Tauri prerequisites.

git clone https://github.com/RDSV01/PurifyMail
cd purifymail
npm install
npm run app          # run in development
npm run app:build    # produce an installer in src-tauri/target/release/bundle

Working on the interface without a mailbox

Set VITE_DEMO=1 and the list fills with invented senders, so you can work on the UI without connecting a real account. The seed command is a no-op in release builds.

VITE_DEMO=1 npm run app                       # macOS / Linux
$env:VITE_DEMO="1"; npm run app               # Windows PowerShell

Cutting a release

Installers are not built by hand: GitHub Actions builds them for Windows, macOS, and Linux and attaches them to a release. A version tag starts it.

npm version 0.1.1 --no-git-tag-version
# put the same number in src-tauri/Cargo.toml and src-tauri/tauri.conf.json
git commit -am "release 0.1.1"
git tag v0.1.1
git push origin main --tags

The release is created as a draft so a broken build never reaches anyone: check the files, write the notes, press publish. To have it go out without that step, set releaseDraft: false in .github/workflows/release.yml. Expect about fifteen minutes for all three platforms.

.github/workflows/ci.yml runs on every commit and does the fast checks: frontend build (tsc is what stops fr.ts and en.ts drifting apart), cargo fmt, clippy with no warnings tolerated, and the tests.

How it is put together

src/                 React + TypeScript interface
  i18n/              fr.ts and en.ts, peers rather than translations
  state/store.ts     Zustand store; all backend events land here
  components/        List rows, the one-by-one card, bands, dialogs
  views/             Senders, Mailboxes, Settings
src-tauri/src/
  detect.rs          Newsletter scoring, sender grouping, link extraction
  mailbox.rs         IMAP: connect, scan every folder, search, move to Trash
  unsubscribe.rs     One-click, plain request, confirmation form, mailto:
  oauth.rs           Gmail OAuth2 with PKCE on a loopback redirect
  vault.rs           AES-256-GCM credential store, key in the OS keychain
  store.rs           SQLite metadata cache
  lib.rs             Tauri commands, the scan worker, the action queue

Run the backend tests with cd src-tauri && cargo test. They cover the parts worth getting right: sender grouping, unsubscribe-link extraction, header unfolding, RFC 2047 decoding, mailto: parsing, confirmation-form detection, and the detection threshold.

Contributing

Issues and pull requests are welcome. Two things to know before you start:

  • The detector is the product. If PurifyMail missed one of your newsletters, or could not unsubscribe you from one, that is a bug worth reporting: paste the message's headers and its footer HTML (with the addresses redacted) into an issue.
  • No new network calls. Anything that contacts a host not already listed in PRIVACY.md will not be merged.

License

MIT. See LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages