Skip to main content

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

imail

PyPI Python License CI

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 appimail boots a FastAPI server and pops your browser to http://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_URL at 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-first1 / 2 / 3 to save a draft, S to skip, Q to 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 bare imail slot was taken). The command you run after install is still imail.

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 .whl and .tar.gz on 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.send scope is requested; the Gmail provider can only fetch, draft, mark-read, archive.
  • IMAP app passwords are stored in the OS keyring, not in accounts.json or .env.
  • OAuth tokens are saved to ~/.config/imail/token-<account-id>.json (mode 0600).
  • Server listens on 127.0.0.1 by default. Don't move it to 0.0.0.0 on a shared machine.
  • Email content reaches DeepSeek's servers. If you'd rather not share message bodies with any third party, point IMAIL_BASE_URL at 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

imail_cli-1.3.0.tar.gz (178.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

imail_cli-1.3.0-py3-none-any.whl (60.7 kB view details)

Uploaded Python 3

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

Hashes for imail_cli-1.3.0.tar.gz
Algorithm Hash digest
SHA256 14f07149d381e9b53774a4215616fe91b694cd477a68abdbe46840da7201293f
MD5 e497c94f302bbdf21dfe215bd260cd36
BLAKE2b-256 857dd10e99ade9540958c59a36c85883f51684b19c436ff4272dba5f47ab1f2f

See more details on using hashes here.

Provenance

The following attestation bundles were made for imail_cli-1.3.0.tar.gz:

Publisher: release.yml on jessecu2024/imail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for imail_cli-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 766d71deadb14fe961594cb633042c2be14479b3091b66d8911a32be0005b0a4
MD5 61eceea0b6820ee49b5dd935d278ebc1
BLAKE2b-256 07cc4e10b3ff41c969aba2eddc3feab5a4440a446524176e839f798ae304b9a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for imail_cli-1.3.0-py3-none-any.whl:

Publisher: release.yml on jessecu2024/imail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page