Inbox triage as a local app: log in to Gmail / Outlook / 163 and clear emails with 3-version LLM-drafted replies (DeepSeek-powered).
Project description
imail
Inbox triage as a local app. Log in once to Gmail, Outlook, or 163 — then clear your unread emails by picking from three LLM-drafted replies per message. Powered by DeepSeek.
You wake up to 30 emails. Each one needs a yes / no / "let me get back to you." imail fetches
your unread inbox, asks the model for three reply versions per email (positive · neutral · negative),
and saves your pick as a Gmail/IMAP draft. You stay in control of every Send button.
┌──────────────────────────────────────────────────────────────┐
│ From advisor@uni.edu │
│ Subject Can you join the panel on Thursday? │
│ … │
└──────────────────────────────────────────────────────────────┘
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1·POSITIVE │ │ 2·NEUTRAL │ │ 3·NEGATIVE │
│ Yes, I'll … │ │ Let me … │ │ Thanks for │
│ │ │ │ │ asking, but │
└─────────────┘ └─────────────┘ └─────────────┘
1 / 2 / 3 → save draft S → skip Q → end session
Features
- ✦ Multi-provider — Gmail (OAuth), and any IMAP mailbox: Outlook, 163, 126, QQ, Yahoo, iCloud, custom hosts.
- ✦ Local web app —
imailboots a FastAPI server and pops your browser tohttp://127.0.0.1:8765. - ✦ Drafts only — never sends mail on your behalf. You press Send yourself in your normal mail client.
- ✦ Secrets in OS keyring — IMAP app passwords go to macOS Keychain (or platform equivalent), not a plain text file.
- ✦ DeepSeek by default — cheap, fast, OpenAI-compatible. Point
IMAIL_BASE_URLat any other OpenAI-compatible endpoint (Together, Groq, Moonshot, 302.AI, an Anthropic-proxy, etc.) and it just works. - ✦ Three drafts per email in a single API call — fast, cheap, self-consistent. DeepSeek auto-caches the system prefix server-side.
- ✦ Keyboard-first —
1/2/3to save a draft,Sto skip,Qto end.
Install
The easy way (any platform — macOS / Linux / Windows; just needs Python ≥ 3.11):
# Recommended: uv (fastest, no extra setup if you already have it).
uv tool install imail-cli
# Or pipx (if you don't have uv).
pipx install imail-cli
Note: distribution name on PyPI is
imail-cli(the bareimailslot was taken). The command you run after install is stillimail.
Then export your DeepSeek API key and launch:
export DEEPSEEK_API_KEY=sk-... # get one at https://platform.deepseek.com/api_keys
imail # opens http://127.0.0.1:8765
First run shows an "Add account" screen. Pick Gmail / Outlook / 163 / etc., sign in, and you're triaging.
Try without installing (uv only):
uvx --from imail-cli imail
Releases are also attached as
.whland.tar.gzon GitHub Releases if you'd rather download the artefact yourself.
Quick Start (from source)
# 1. Install deps
uv sync
# 2. Set your DeepSeek key
cp .env.example .env
# → put your DEEPSEEK_API_KEY in .env (get one at https://platform.deepseek.com/api_keys)
# 3. Launch the app
uv run imail
# → opens http://127.0.0.1:8765 in your browser
First run will show an "Add account" screen. Pick a provider:
- Gmail — drop your
credentials.json(see docs/gmail-setup.md) and the first triage triggers the OAuth consent screen. - Microsoft 365 / Outlook / 163 / 126 / QQ / Yahoo / iCloud — sign in with your email + an app password / 授权码 (see docs/imap-setup.md).
- Custom — enter any IMAPS host + port.
After that, click your mailbox card → walk through unread emails → press 1/2/3 → drafts land in your Drafts folder.
Work or school account that blocks IMAP and won't let you register an Azure app? (CityU and many other universities.) See docs/forwarding-workflow.md for the validated forwarding-to-personal fallback — adds your work mail to imail in 5 minutes of server-side setup, no code needed.
Where this project is heading + what would unblock more mailboxes: docs/vision-and-paths.md — the project's big picture, current capability matrix, and a ranked list of compromise paths (browser extension, bookmarklet, menu-bar app, Outlook add-in, etc.) for when direct API access is blocked.
Configuration
All settings come from .env (see .env.example):
| Variable | Default | Notes |
|---|---|---|
DEEPSEEK_API_KEY |
(required) | DeepSeek API key. OPENAI_API_KEY is a fallback for non-DeepSeek endpoints. |
IMAIL_BASE_URL |
https://api.deepseek.com |
OpenAI-compatible endpoint |
IMAIL_MODEL |
deepseek-chat |
Or deepseek-reasoner for sharper, slower drafts |
USER_SIGNOFF |
Jie |
Name used in reply sign-offs |
IMAIL_PORT |
8765 |
Local server port |
IMAIL_HOST |
127.0.0.1 |
Bind address (only listens on loopback by default) |
IMAIL_CONFIG_DIR |
~/.config/imail |
Where accounts.json and OAuth tokens live |
Development
uv sync # install dev + runtime deps
uv run ruff check . # lint
uv run ruff format . # format
uv run mypy src # type check
uv run pytest # tests
Project Structure
src/imail/
cli.py Launcher — boots uvicorn + opens browser
config.py .env loader
server.py FastAPI app — status, accounts, triage session
accounts.py Account manifest + keyring-backed secrets
reply_generator.py DeepSeek (OpenAI-compatible) call + JSON parser
providers/
base.py EmailMsg + MailProvider Protocol
gmail.py Gmail API provider (OAuth)
imap.py Generic IMAP provider with presets
static/
index.html Single-page UI
app.js Alpine.js component
style.css Dark theme
docs/
gmail-setup.md One-time Google Cloud Console walk-through
imap-setup.md How to get app passwords on each provider
tests/ pytest suites
Security Notes
- No
gmail.sendscope is requested; the Gmail provider can only fetch, draft, mark-read, archive. - IMAP app passwords are stored in the OS keyring, not in
accounts.jsonor.env. - OAuth tokens are saved to
~/.config/imail/token-<account-id>.json(mode 0600). - Server listens on
127.0.0.1by default. Don't move it to0.0.0.0on a shared machine. - Email content reaches DeepSeek's servers. If you'd rather not share message bodies with any third party, point
IMAIL_BASE_URLat a self-hosted Ollama / vLLM endpoint running an instruction model.
License
MIT — see LICENSE.
Project details
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 imail_cli-1.3.0.tar.gz.
File metadata
- Download URL: imail_cli-1.3.0.tar.gz
- Upload date:
- Size: 178.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14f07149d381e9b53774a4215616fe91b694cd477a68abdbe46840da7201293f
|
|
| MD5 |
e497c94f302bbdf21dfe215bd260cd36
|
|
| BLAKE2b-256 |
857dd10e99ade9540958c59a36c85883f51684b19c436ff4272dba5f47ab1f2f
|
Provenance
The following attestation bundles were made for imail_cli-1.3.0.tar.gz:
Publisher:
release.yml on jessecu2024/imail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
imail_cli-1.3.0.tar.gz -
Subject digest:
14f07149d381e9b53774a4215616fe91b694cd477a68abdbe46840da7201293f - Sigstore transparency entry: 1565552183
- Sigstore integration time:
-
Permalink:
jessecu2024/imail@b7d593c85295cdc65e44614bf639ef29337f7d3d -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/jessecu2024
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b7d593c85295cdc65e44614bf639ef29337f7d3d -
Trigger Event:
push
-
Statement type:
File details
Details for the file imail_cli-1.3.0-py3-none-any.whl.
File metadata
- Download URL: imail_cli-1.3.0-py3-none-any.whl
- Upload date:
- Size: 60.7 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 |
766d71deadb14fe961594cb633042c2be14479b3091b66d8911a32be0005b0a4
|
|
| MD5 |
61eceea0b6820ee49b5dd935d278ebc1
|
|
| BLAKE2b-256 |
07cc4e10b3ff41c969aba2eddc3feab5a4440a446524176e839f798ae304b9a2
|
Provenance
The following attestation bundles were made for imail_cli-1.3.0-py3-none-any.whl:
Publisher:
release.yml on jessecu2024/imail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
imail_cli-1.3.0-py3-none-any.whl -
Subject digest:
766d71deadb14fe961594cb633042c2be14479b3091b66d8911a32be0005b0a4 - Sigstore transparency entry: 1565552217
- Sigstore integration time:
-
Permalink:
jessecu2024/imail@b7d593c85295cdc65e44614bf639ef29337f7d3d -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/jessecu2024
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b7d593c85295cdc65e44614bf639ef29337f7d3d -
Trigger Event:
push
-
Statement type: