Smart enough to say no.
Project description
nothx
nothx (no thanks) separates legitimate subscriptions from spam and phishing, then takes the safe action: unsubscribe from authenticated lists or suppress dangerous mail in Junk without contacting its sender. Mailbox access and body inspection stay on your machine. If you enable a cloud AI provider, only a bounded summary of locally selected marketing/spam headers is sent for preference classification—never message bodies or unrelated personal mail.
Your inbox, uncrowded.
Quick Start
pipx install nothx
nothx init
That's it. The wizard handles everything else.
Don't have pipx?
brew install pipx(macOS) orsudo apt install pipx(Linux).Run
nothxanytime for the interactive menu.
Why nothx?
| The Problem | How nothx fixes it |
|---|---|
| Mailbox-cleanup services require inbox access | IMAP scanning and state remain on your machine |
| Most tools treat all unwanted mail alike | Safe subscriptions are unsubscribed; spam/phishing is never contacted |
| Manual unsubscribing is tedious | AI classifies hundreds of senders in seconds |
| One-size-fits-all rules | Learns your preferences over time |
| Yet another app to run | Uses native OS scheduling (launchd/systemd) |
| What if AI gets it wrong? | Correct future local policy and teach the classifier |
Features
Core
- AI-Powered — Claude, GPT, Gemini, or local models via Ollama
- Authenticated Unsubscribe — strict RFC 8058 one-click, vetted HTTPS GET, or constrained mailto
- Real Spam Suppression — consumes provider Junk/phishing verdicts and safely moves exact IMAP UIDs to the discovered Junk mailbox
- Privacy First — header-only by default; the optional footer scanner is local, bounded, and never sends footer content to AI
Smart
- Learns From You — Gets smarter every time you disagree with a decision
- 5-Layer Classification — Rules → Patterns → AI → Heuristics → Manual review
- Guarded Automation — unknown authentication, conflicting verdicts, and protected identities go to review
Practical
- Multi-Account — Scan Gmail + Outlook simultaneously
- Native Scheduling — No daemon needed. Uses launchd (macOS) or systemd (Linux).
- Future Policy Corrections —
nothx undo domain.comchanges nothx's future decision; it cannot externally resubscribe you
Beautiful
- Rich CLI — Animated banner, progress bars, colored output
- Interactive Mode — Just run
nothxfor menu-driven operation
The Learning System
nothx gets smarter the more you use it. Every decision trains your personal preference model.
What it learns:
- Keywords — Keep emails with "receipt"? Future receipt-related senders score safer.
- Open rates — If you keep emails you never open, it stops penalizing low engagement.
- Volume tolerance — Keep high-volume senders? It raises the threshold before flagging.
Corrections teach it too. When you run nothx undo, it doesn't just restore — it learns that this type of email matters to you.
nothx status --learning # See your learned preferences
How It Works
Email arrives in Inbox or Junk
↓
┌─────────────────┐
│ PROVIDER POLICY │ Junk, phishing, authentication, mailbox flags
└────────┬────────┘
↓
┌─────────────────┐
│ USER RULES │ Your exact keep, unsubscribe, and block choices
└────────┬────────┘
↓
┌─────────────────┐
│ LOCAL CANDIDATE │ List/bulk, engagement, and cold-outreach evidence
└────────┬────────┘
↓
┌─────────────────┐
│ AI / HEURISTICS │ Preference classification for selected candidates
└────────┬────────┘
↓
┌─────────────────┐
│ SAFE DISPOSITION│ Keep, review, unsubscribe, or move to Junk
└─────────────────┘
Provider threat evidence and explicit block rules are resolved before AI. Bulk mail is not automatically spam, and an unsubscribe link is not automatically safe.
Commands
Essentials
| Command | What it does |
|---|---|
nothx |
Interactive menu |
nothx init |
Setup wizard — accounts, API key, first scan |
nothx run |
Scan and process emails |
nothx status |
Stats, accounts, schedule at a glance |
nothx review |
Decide on uncertain senders |
Day-to-Day
| Command | What it does |
|---|---|
nothx senders |
List all tracked senders |
nothx search <pattern> |
Find a specific sender |
nothx undo [domain] |
Change future local policy (does not resubscribe) |
nothx history |
View grouped, redacted operation history |
nothx export |
Export data to CSV |
Configuration
| Command | What it does |
|---|---|
nothx rule "pattern" keep/unsub/block |
Add a classification rule |
nothx rules |
List all classification rules |
nothx schedule --daily |
Set the recommended automatic run frequency |
nothx account add/remove |
Manage email accounts |
nothx config --show |
View current config |
nothx consent |
Explicitly grant or revoke versioned network/mailbox automation consent |
nothx run --full-history |
Explicitly scan all UIDs instead of the incremental cursor |
nothx run --rescan |
Repeat the configured lookback without rewinding the cursor |
nothx update |
Check for and install updates |
nothx completion |
Generate shell completion |
Aliases: r (run), s (status), rv (review), h (history)
Setup
Requirements
- Python 3.11+
- Gmail, Outlook, Yahoo, or iCloud account
- AI provider (optional — works without AI too)
Installation
pipx is the recommended way to install nothx. It handles virtual environments automatically.
# Base install (heuristics only, or Ollama)
pipx install nothx
# With your preferred AI provider
pipx install "nothx[anthropic]" # Claude (recommended)
pipx install "nothx[openai]" # GPT-4
pipx install "nothx[gemini]" # Google Gemini
pipx install "nothx[all-ai]" # All providers
Don't have pipx?
macOS:
brew install pipx
Linux:
# Ubuntu/Debian
sudo apt install pipx
# Fedora
sudo dnf install pipx
pipx requires Python 3.11+. After installing, verify with python3 --version.
Using pip instead
If you prefer pip, use a virtual environment to avoid system conflicts:
python3 -m venv ~/.nothx-venv
source ~/.nothx-venv/bin/activate
pip install nothx
Gmail App Password
- Go to myaccount.google.com/apppasswords
- Generate a new password for "nothx"
- Copy the 16-character code
Requires 2FA enabled on your account.
Outlook / Live / Hotmail OAuth
Microsoft personal accounts no longer accept basic authentication or app passwords for IMAP. nothx uses OAuth2 device sign-in instead; it never needs your Microsoft password.
- In Azure App registrations, create a public-client app that supports Personal Microsoft accounts only.
- Under Authentication, enable Allow public client flows. No client secret or redirect URI is needed.
- Copy the Application (client) ID and provide it when
nothx initornothx account addasks for it. - Open the displayed Microsoft device-login URL, enter its short code, and approve IMAP and SMTP access.
The access and refresh tokens are stored separately in
~/.nothx/tokens.json with owner-only permissions. If an older token granted
IMAP but not SMTP, nothx asks you to sign in once more before it sends an
unsubscribe email.
AI Provider Setup
Anthropic (Claude) — Best for email classification. Get API key
OpenAI (GPT) — GPT-4o models. Get API key
Google (Gemini) — Free tier available. Get API key
Ollama (Local) — Run models locally. No API key needed. Install Ollama
Without AI, nothx uses heuristic scoring. Still works, just less smart.
Safety and privacy defaults
- Inbox and the unambiguously advertised IMAP
\Junkmailbox are scanned. nothx does not guess localized Junk folder names; configure an override if your server advertises none or several. - Initial runs use the configured lookback. Later runs use
(account, mailbox, UIDVALIDITY, UID)cursors. Full history is always explicit. - Body fetching is disabled by default. The optional footer scanner examines at most two inline text tails (64 KiB each, 128 KiB total) for authenticated list/bulk candidates. It skips attachments, nested messages, images, scripts, and forms.
- One-click POST requires compliant headers plus
$canunsubscribeor a correlated passing DKIM signature that covers both unsubscribe headers. All outbound unsubscribe contact—including an explicitly opened browser page—and mailbox actions require separate, versioned consent. - HTTP requests are HTTPS-only, proxy/cookie/auth/referrer-free, redirect constrained, SSRF checked, and connected to an already validated public IP while preserving TLS hostname verification.
- Stored targets are fingerprints and hashed destination labels. Complete hosts, paths, queries, mailto recipients/bodies, and HTTP response bodies are excluded from normal history and exports.
What an outcome means
requested: the endpoint accepted a one-click/GET request, or SMTP accepted the mail for delivery. It does not guarantee mail will stop.needs_user: safe automation reached a login, form, JavaScript flow, preference center, CAPTCHA, or another manual boundary.verified_quiet: a complete post-grace scan found no later matching delivery.ineffective: matching mail arrived after the 48-hour grace period. One fresh-token or alternate-method retry is allowed; another post-grace delivery is blocked.blocked: nothx sent no unsubscribe traffic and applied its local spam path. Portable IMAP Junk movement is best effort; provider-side spam training is not guaranteed.
Troubleshooting
Connection failed
- Verify your App Password (not your regular password)
- Ensure IMAP is enabled in your email settings
- For Gmail: Check that 2FA is enabled (required for App Passwords)
- For Outlook/Live/Hotmail: re-add the account to renew OAuth consent; app passwords do not work
- Run
nothx testto diagnose
AI classification not working
- Check your API key:
nothx config --show - Verify you have credits/quota with your chosen provider (Anthropic, OpenAI, or Google)
- nothx falls back to heuristics if AI fails — it still works
Still getting emails after unsubscribe
- Some senders ignore unsubscribe requests (bad actors)
- Daily runs verify accepted requests after 48 hours and escalate repeat offenders to Junk
- Add manually:
nothx rule "domain.com" block
Start fresh
nothx reset # Delete everything
nothx reset --keep-config # Keep accounts, clear history
Comparison
| Feature | Unroll.me | SaneBox | Leave Me Alone | nothx |
|---|---|---|---|---|
| Price | Free | $84-432/yr | $48/yr | Free |
| Mailbox processing | Cloud | Cloud | Cloud | Local |
| Actually unsubscribes | No | Yes | Yes | Yes |
| AI classification | No | Yes | Basic | Yes (multi-provider) |
| Learns your preferences | No | Limited | No | Yes |
| Local AI option | No | No | No | Yes (Ollama) |
| Open source | No | No | No | Yes |
Philosophy
We built nothx because:
- Your email is yours. Not a product to sell.
- AI should adapt to you. Not the other way around.
- Automation should be invisible. Set once, forget forever.
- Words matter. A request is not verified cessation, and changing local policy cannot externally resubscribe an address.
Contributing
git clone https://github.com/sainihas/nothx.git
cd nothx
pip install -e ".[dev]"
pytest
License
MIT — see LICENSE
nothx — Because your inbox should work for you, not against you.
Made with mass frustration at marketing emails.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nothx-0.1.8.tar.gz.
File metadata
- Download URL: nothx-0.1.8.tar.gz
- Upload date:
- Size: 233.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0dc0626efa135fce3656d6a5834ee36df6bfede32fa4556edafd83097dba5de6
|
|
| MD5 |
6ebcddd52675baeb70926c38c8db6816
|
|
| BLAKE2b-256 |
d16c420a933439348c24305ace3a9298de5b364961b833f6d2a3b7e24e00977a
|
Provenance
The following attestation bundles were made for nothx-0.1.8.tar.gz:
Publisher:
publish.yml on sainihas/nothx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nothx-0.1.8.tar.gz -
Subject digest:
0dc0626efa135fce3656d6a5834ee36df6bfede32fa4556edafd83097dba5de6 - Sigstore transparency entry: 2137884929
- Sigstore integration time:
-
Permalink:
sainihas/nothx@e254d999efb3f97567c5758c2156bec6efe279cf -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/sainihas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e254d999efb3f97567c5758c2156bec6efe279cf -
Trigger Event:
release
-
Statement type:
File details
Details for the file nothx-0.1.8-py3-none-any.whl.
File metadata
- Download URL: nothx-0.1.8-py3-none-any.whl
- Upload date:
- Size: 177.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42455ba7462d15c4b4329c7cafff62c22a406f98b2299cdb755cafbb0220207c
|
|
| MD5 |
f02910347c77a9e84bb73342b174250f
|
|
| BLAKE2b-256 |
a8fc8bbd0285d187b41861c3af32b1f25ac4ff796361ce5550cbedaa556f1ec1
|
Provenance
The following attestation bundles were made for nothx-0.1.8-py3-none-any.whl:
Publisher:
publish.yml on sainihas/nothx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nothx-0.1.8-py3-none-any.whl -
Subject digest:
42455ba7462d15c4b4329c7cafff62c22a406f98b2299cdb755cafbb0220207c - Sigstore transparency entry: 2137884949
- Sigstore integration time:
-
Permalink:
sainihas/nothx@e254d999efb3f97567c5758c2156bec6efe279cf -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/sainihas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e254d999efb3f97567c5758c2156bec6efe279cf -
Trigger Event:
release
-
Statement type: