Skip to main content

MailPilot

English | 中文

纯 Python 命令行邮件客户端 —— 收、发、读、搜、标记 —— 内置邮件服务器,并提供完整的智能体(function-calling)API。

GPL-3.0-or-later 许可。零运行时依赖:SMTP、IMAP、POP3 客户端,asyncio 实现的 SMTP+POP3 服务器,SQLite 本地存储,MIME 解析,以及 NTLM 所需的 DES/MD4 等全部 SASL 认证,均基于 Python 标准库自行实现。

功能特性

  • 全部主流协议:SMTP(发送)、IMAP4(收取/搜索/标志/文件夹)、POP3(收取)——全面支持 SSL 与 STARTTLS。
  • 全部主流认证方式:SASL PLAIN、LOGIN、CRAM-MD5、XOAUTH2/OAUTHBEARER、NTLM(内置纯 Python DES + MD4),以及 POP3 的 APOP。auto 模式按服务器通告自动选择。
  • 服务商预设:gmail、outlook、qq、163、126、yahoo、icloud、zoho、aliyun、sina——一个参数填好全部服务器与端口。
  • 内置邮件服务器:没配服务器?mailpilot serve 即可启动本地 SMTP + POP3 服务器(asyncio、零系统依赖),支持按邮箱认证、CRAM-MD5/APOP,并带中继防护。
  • 本地 SQLite 存储:每封收取/发出的邮件都可离线搜索、标记、移动、删除。
  • MIME 处理完善:multipart/alternative、RFC 2047 中文头、附件(列出 + 保存)、HTML→纯文本兜底。
  • 智能体 API:每个操作都有对应的 OpenAI function-calling TOOLS schema + dispatch(),LLM 智能体能像人一样收发、搜索、标记邮件。

安装

要求 Python ≥ 3.10。运行时无任何第三方依赖,全部标准库。

# 推荐:直接装入现有 conda 环境(不需要 venv)
conda activate dev
pip install -e .[dev]        # [dev] 只额外装 pytest/ruff/mypy

只使用 CLI/API 的话,pip install -e . 即可。

数据与文件位置

所有运行时数据集中在一个目录:默认 ~/.mailpilot/。

文件 用途 权限
~/.mailpilot/config.json 账号凭据(邮箱、授权码/token、服务器地址、端口) 0600(保存时强制,仅属主可读写)
~/.mailpilot/mailpilot.db SQLite 存储:每封收取/发出的邮件——原始 RFC822 报文、解析后的头/正文、标志、附件 0600(首次运行后收紧)

目录解析优先级(从高到低):

  1. config.json 内的 data_dir 字段
  2. 环境变量 MAILPILOT_DATA_DIR
  3. 默认 ~/.mailpilot/

邮件数据库同时保存完整原始报文与解析后的字段(主题、发收件人、日期、标志、text/html 正文),因此可离线搜索,附件可随时重新提取。任何真实凭据或邮件内容都不会出现在代码、测试或文档中。

整体迁移(config + 邮件):

export MAILPILOT_DATA_DIR=/Volumes/SecureUSB/mailpilot

或在配置文件里设 "data_dir": "/path"。

配置账号(服务商预设)

mailpilot config add qq you@qq.com --password <SMTP授权码> --auth login --provider qq
mailpilot config test -a qq      # 探测 IMAP + POP3 + SMTP 认证

收取、列览、阅读、搜索、标记

mailpilot fetch -a qq -n 20      # 拉取新邮件进本地库
mailpilot list --unread          # 按时间倒序
mailpilot search "关键词"
mailpilot read 42                # 头部 + 正文
mailpilot read 42 --save-attachments ./att
mailpilot mark 42 --flags seen,flagged
mailpilot folders

发送

mailpilot send -t bob@example.com -s "你好" -m "正文" \
    --attach ./report.pdf:report-2026.pdf

运行内置服务器

# 无认证模式,localhost,存入 ~/.mailpilot/mailpilot.db
mailpilot serve --smtp-port 2525 --pop-port 1110 --domain localhost

# 带认证的邮箱(--user 可重复)
mailpilot serve --user alice@localhost:secret1 --user bob@localhost:secret2

随后任何 SMTP/POP3 客户端都可连 127.0.0.1:2525 / 127.0.0.1:1110。本地域投递无需认证;向其他域中继需要认证,否则拒绝(550)。

脚本化 JSON 输出

所有命令都接受 --json,统一返回 {"success", "data", "error", "metadata"}:

mailpilot list --json --unread | jq '.data[0].subject'

智能体集成(OpenAI Function Calling)

from mailpilot.agent.tools import TOOLS, dispatch

# 1. 把 TOOLS 加进模型的工具列表。
# 2. 模型发起工具调用时路由:
result = dispatch("mailpilot_send", {
    "to": ["bob@example.com"],
    "subject": "智能体发来的问候",
    "body": "通过 mailpilot 工具调用发送。",
})
print(result)  # {"success": True, "data": {...}, "error": None, "metadata": {...}}

可用工具:mailpilot_send、mailpilot_list、mailpilot_read、mailpilot_search、mailpilot_mark、mailpilot_delete、mailpilot_move、mailpilot_fetch、mailpilot_folders、mailpilot_account_add、mailpilot_account_list、mailpilot_account_test。

查看 schema:mailpilot api --schema。

Python API

from mailpilot import ToolResult, send_mail, list_messages, read_message, search_messages, mark_messages

result = send_mail(to=["bob@example.com"], subject="Hi", body="Hello")
if result.success:
    print(result.data["message_id"])

所有 API 函数返回 ToolResult dataclass(success、data、error、metadata、.to_dict()、__bool__ 真值判断)。

配置

账号存于 ~/.mailpilot/config.json(0600)。完整布局与迁移方法见上文数据与文件位置。运行期覆盖:

  • MAILPILOT_DATA_DIR — 数据目录
  • mailpilot serve --db <path> — 内置服务器的自定义数据库路径

项目结构

mailpilot/
├── core/            # config(账号/预设)、errors(ToolResult)、
│                    # auth(PLAIN/LOGIN/CRAM-MD5/XOAUTH2/NTLM/APOP)、
│                    # _des + _md4(NTLM 所需纯 Python 密码学原语)
├── mail/            # smtp_client、imap_client、pop_client、
│                    # parser(MIME 构建/解析/渲染)、store(SQLite)
├── serve/           # 内置 asyncio SMTP + POP3 服务器
├── agent/           # OpenAI function-calling TOOLS + dispatch
└── cli/             # argparse CLI(config/send/fetch/list/read/search/…)
tests/               # pytest 套件,含客户端↔内置服务器端到端回环

开发

conda activate dev      # 用现有环境,无需 venv
pip install -e .[dev]
pytest                  # 59 个测试
ruff check . && ruff format .
mypy mailpilot

备注

  • QQ/163/126 邮箱使用"授权码"而非登录密码——通过 --password 传入。凭据只存于 ~/.mailpilot/config.json(0600),绝不落入代码、测试或文档。
  • XOAUTH2 token 可用 mailpilot config test -a acct --oauth2-token <token> 或 Account.oauth2_token 提供(Gmail/Outlook OAuth 流程)。
  • 内置服务器把投递的邮件存进同一个 SQLite 库,因此 mailpilot fetch --protocol pop3 可以对它完整回环——测试智能体时不必碰真实邮箱。
  • 开发直接使用 conda 环境(如 conda activate dev && pip install -e .[dev])——无需 virtualenv。

许可

GPL-3.0-or-later(见 LICENSE)。


MailPilot

English | 中文

Pure-Python command-line mail client — send, fetch, read, search, mark — with a built-in mail server and a full agent (function-calling) API.

GPL-3.0-or-later licensed. Zero runtime dependencies: everything (SMTP, IMAP, POP3 clients, an asyncio SMTP+POP3 server, SQLite storage, MIME parsing, SASL auth incl. DES/MD4 for NTLM) is built on the Python standard library.

Features

  • All mainstream protocols: SMTP (send), IMAP4 (fetch/search/flags/folders), POP3 (fetch) — SSL and STARTTLS everywhere.
  • All mainstream auth methods: SASL PLAIN, LOGIN, CRAM-MD5, XOAUTH2/OAUTHBEARER, NTLM (with a pure-Python DES + MD4), and POP3 APOP. auto mode tries what the server advertises.
  • Provider presets: gmail, outlook, qq, 163, 126, yahoo, icloud, zoho, aliyun, sina — one flag fills all host/port settings.
  • Built-in mail server: no server configured? Run mailpilot serve to start a local SMTP + POP3 server (asyncio, zero system dependencies) with optional per-mailbox auth, CRAM-MD5/APOP support and relay protection.
  • Local SQLite store: every fetched/sent message is searchable, flaggable, movable, deletable — offline.
  • MIME done right: multipart/alternative, RFC 2047 CJK headers, attachments (list + save), HTML→text fallback.
  • Agent API: an OpenAI function-calling TOOLS schema + dispatch() for every operation, so an LLM agent can read/write/search/mark mail exactly like a human user.

Installation

Requires Python ≥ 3.10. No runtime dependencies — everything is standard library.

# Recommended: install into your existing conda env (no venv needed)
conda activate dev
pip install -e .[dev]        # [dev] adds pytest/ruff/mypy only

pip install -e . alone is enough for CLI/API usage.

Data & file locations

All runtime data lives in one directory: ~/.mailpilot/ by default.

File Purpose Permissions
~/.mailpilot/config.json Account credentials (email, auth code/token, server hosts, ports) 0600 (owner-only, enforced on save)
~/.mailpilot/mailpilot.db SQLite store: every fetched/sent message — raw RFC822 source, parsed headers/body, flags, attachments 0600 (tightened after first run)

Location resolution order (highest first):

  1. data_dir field inside config.json
  2. Environment variable MAILPILOT_DATA_DIR
  3. Default ~/.mailpilot/

The mail database stores the full raw message plus parsed fields (subject, from/to, date, flags, text/html bodies), so searches work offline and attachments can be re-extracted any time. No message content is kept anywhere else — no code, no tests, no README ever contain real credentials or message data.

To move everything (config + mail) elsewhere:

export MAILPILOT_DATA_DIR=/Volumes/SecureUSB/mailpilot

Or set "data_dir": "/path" in the config file.

Configure an account (provider preset)

Configure an account (provider preset)

mailpilot config add qq you@qq.com --password <SMTP-auth-code> --auth login --provider qq
mailpilot config test -a qq        # probes IMAP + POP3 + SMTP auth

Fetch, list, read, search, mark

mailpilot fetch -a qq -n 20   # same as before        # pull new mail into local store
mailpilot list --unread            # newest first
mailpilot search "Foxmail"
mailpilot read 42                  # headers + body
mailpilot read 42 --save-attachments ./att
mailpilot mark 42 --flags seen,flagged
mailpilot folders

Send

mailpilot send -t bob@example.com -s "Hello" -m "Body text" \
    --attach ./report.pdf:report-2026.pdf

Run the built-in server

# Open (no auth) on localhost, storing into ~/.mailpilot/mailpilot.db
mailpilot serve --smtp-port 2525 --pop-port 1110 --domain localhost

# Auth-protected mailboxes (repeat --user)
mailpilot serve --user alice@localhost:secret1 --user bob@localhost:secret2

Then point any SMTP/POP3 client at 127.0.0.1:2525 / 127.0.0.1:1110. Local-domain delivery is accepted without auth; relaying to other domains requires authentication and is otherwise denied (550).

JSON output for scripting

Every command accepts --json and returns {"success", "data", "error", "metadata"}:

mailpilot list --json --unread | jq '.data[0].subject'

Agent Integration (OpenAI Function Calling)

from mailpilot.agent.tools import TOOLS, dispatch

# 1. Pass TOOLS to your model's tool list.
# 2. When the model calls a tool, route it:
result = dispatch("mailpilot_send", {
    "to": ["bob@example.com"],
    "subject": "Hi from the agent",
    "body": "Sent via mailpilot tool call.",
})
print(result)  # {"success": True, "data": {...}, "error": None, "metadata": {...}}

Available tools: mailpilot_send, mailpilot_list, mailpilot_read, mailpilot_search, mailpilot_mark, mailpilot_delete, mailpilot_move, mailpilot_fetch, mailpilot_folders, mailpilot_account_add, mailpilot_account_list, mailpilot_account_test.

Inspect the schema yourself: mailpilot api --schema.

Python API

from mailpilot import ToolResult, send_mail, list_messages, read_message, search_messages, mark_messages

result = send_mail(to=["bob@example.com"], subject="Hi", body="Hello")
if result.success:
    print(result.data["message_id"])

All API functions return a ToolResult dataclass (success, data, error, metadata, .to_dict(), truthiness via __bool__).

Configuration

Accounts live in ~/.mailpilot/config.json (0600). See Data & file locations above for the full layout and how to relocate it. Per-run overrides:

  • MAILPILOT_DATA_DIR — data directory
  • mailpilot serve --db <path> — custom database path for the built-in server

Project structure

mailpilot/
├── core/            # config (accounts/presets), errors (ToolResult),
│                    # auth (SASL PLAIN/LOGIN/CRAM-MD5/XOAUTH2/NTLM/APOP),
│                    # _des + _md4 (pure-Python crypto primitives for NTLM)
├── mail/            # smtp_client, imap_client, pop_client,
│                    # parser (MIME build/parse/render), store (SQLite)
├── serve/           # built-in asyncio SMTP + POP3 server
├── agent/           # OpenAI function-calling TOOLS + dispatch
└── cli/             # argparse CLI (config/send/fetch/list/read/search/…)
tests/               # pytest suite incl. end-to-end client↔built-in-server loops

Development

conda activate dev      # your existing env; no venv needed
pip install -e .[dev]
pytest                  # 59 tests
ruff check . && ruff format .
mypy mailpilot

Notes

  • QQ/163/126 mailboxes use "authorization codes" (授权码) instead of the account password — pass it via --password. Credentials are stored only in ~/.mailpilot/config.json (0600); they never appear in code, tests, or docs.
  • XOAUTH2 tokens can be supplied with mailpilot config test -a acct --oauth2-token <token> or Account.oauth2_token for Gmail/Outlook OAuth flows.
  • The built-in server stores delivered mail in the same SQLite store, so mailpilot fetch --protocol pop3 round-trips against it — useful for testing agents without touching a real mailbox.
  • Development uses a conda env directly (e.g. conda activate dev && pip install -e .[dev]) — no virtualenv required.

License

GPL-3.0-or-later (see LICENSE).

Release files for cycleuser-mailpilot 0.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cycleuser-mailpilot 0.0.3
File Size Uploaded
cycleuser_mailpilot-0.0.3.tar.gz 64.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cycleuser-mailpilot 0.0.3
File Interpreter ABI Platform
cycleuser_mailpilot-0.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 126.9 kB

Release files / cycleuser_mailpilot-0.0.3.tar.gz

Download URL cycleuser_mailpilot-0.0.3.tar.gz
Size 64.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9ab456ff0a4270b57f4219b5a9b0951296f6f4a4f2af0a7896cfbe72f4b7fb50
BLAKE2b-256 checksum
How to use checksums
bb32d0409c8b204f1800b562d1bb2c7cd23a7d3607bc503dbdb6a6da752fe574
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release files / cycleuser_mailpilot-0.0.3-py3-none-any.whl

Download URL cycleuser_mailpilot-0.0.3-py3-none-any.whl
Size 62.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
be2aa2c3beff146f62982e119723d7bf2649f0e9a92ced533f6fc9d965718d7c
BLAKE2b-256 checksum
How to use checksums
b3853ee25c52c5e573e42713d9b51d5546a844347c334a39e734a040ae5215ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release history Release notifications | RSS feed

0.0.4

2 release files

This release

0.0.3 This release

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page