mcp-email
mcp-email — IMAP / SMTP 信箱 MCP server(本機 stdio + 遠端 HTTP / OAuth)
純 Python 實作(mcp_email.py),把任意支援 IMAP / SMTP 的標準信箱(Gmail / Outlook / Yahoo / iCloud / Zoho / 公司 Exchange / 自架 mail server …)包成 MCP tools 給 Claude / Claude Code / Cowork / 任何 MCP host 用。
三種啟動模式(參考 m2k-calendar-tools 的部署架構):
模式 | 指令 | 適用場景 | 認證 |
stdio(預設) |
| 本機單人(Claude Desktop / Code) | 環境變數 / |
HTTP |
| 內網多人共用(Claude Code / Desktop 遠端連線) | 每請求 |
OAuth |
| claude.ai Connectors(手機 app / 網頁版) | OAuth 2.1 + 無狀態加密 token,伺服器不存帳密 |
能做什麼(16 個 tools)
Tool | 用途 |
| Runtime 動態切換 SMTP / IMAP 帳密、port、TLS、附件上限、收件人白名單 |
| 一鍵測 SMTP + IMAP 是否能登入 |
| 寄信:HTML + 純文字、to/cc/bcc、檔案/Base64 附件、Reply-To、自訂 headers、retry |
| 回覆某封信:自動帶 |
| 轉寄某封信: |
| IMAP 列出所有 mailbox 名稱(中文名稱自動解碼) |
| 列出 folder 內訊息 header(支援 IMAP search syntax;含 |
| 抓單封信完整內容(body text/html、附件 metadata 含 index、 |
| 下載單封信裡某個附件的實際內容(base64),以 filename 或 index 指定;有大小上限保護 |
| 加/移除 IMAP flag( |
| 標記 |
| 建立 folder(支援中文,自動 modified UTF-7;已存在不報錯) |
| 搬信:UID MOVE,server 不支援則 COPY + UID EXPUNGE fallback |
| 規則整理:掃描後依條件 move/mark/delete, |
| 把一封信存成草稿(IMAP APPEND 到草稿匣, |
| 把草稿匣裡的某封草稿寄出,成功後從草稿匣刪除 |
Prompts(在支援的 client 顯示成 slash command)
Prompt | 用途 |
| 分流信箱:列未讀 → 摘要 → 建議動作(參數:folder、limit) |
| 每週整理:引導 |
| 讀取指定信件並草擬回覆、確認後才寄(參數:uid、folder、tone) |
對應使用者需求:
📤 寄信 HTML + 純文字 ✅(multipart/alternative,純文字 fallback 自動)
👥 多收件人 to / cc / bcc ✅(bcc 不會 出現在 header)
📎 附件 — 本機檔案路徑 + Base64 ✅(text/* 自動 charset=utf-8)
🔧 Runtime 動態設定 ✅(
email_configuretool,任一欄位可單獨更新)🔍 連線測試 ✅(SMTP
NOOP+ IMAPNOOP各別測)⚡ 高效能 ✅(timeout 可調、SMTP send 失敗 exponential backoff 重試)
安裝
最快:uvx / pip(從 PyPI)
⚠️ 尚未發佈到 PyPI(首次發佈流程見文末〈發佈到 PyPI〉)。發佈後即可用 下列方式安裝;在那之前請用下一節「從原始碼」。
發佈後,用 uv 免手動建環境,首次執行自動抓套件:
uvx mcp-email # 直接跑(uv 會自動安裝到隔離環境)
# 或
pipx install mcp-email
pip install mcp-email # 裝進現有環境,提供 `mcp-email` 指令MCP host 設定(Claude Desktop / Code / Cursor / Cline … 通用),帳密走 env:
{
"mcpServers": {
"email": {
"command": "uvx",
"args": ["mcp-email"],
"env": {
"IMAP_SERVER": "imap.gmail.com", "IMAP_PORT": "993",
"SMTP_SERVER": "smtp.gmail.com", "SMTP_PORT": "465", "SMTP_USE_SSL": "true",
"EMAIL_USER": "you@gmail.com", "EMAIL_PASS": "<app password>"
}
}
}
}Claude Code 使用者:repo 內附
.mcp.json,用claude開這個資料夾會自動提示啟用。
從原始碼(開發 / 自己改)
建議用獨立的 virtualenv,避免污染系統 Python(也不要把 .venv/ 提交到 git):
cd ~/Documents/workspace/mcp-email
# 建立並啟用虛擬環境(請用你實際的 Python,例如 Homebrew 的 python3)
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 執行時依賴
pip install -r requirements.txt
# 開發 / 測試依賴(含 aiosmtpd 假 SMTP)
pip install -r requirements-dev.txt
# 跑端到端測試(in-process 假 SMTP + 假 IMAP)
python test_e2e.py
# 預期:=== 49/49 passed ===
# 遠端(--http/--oauth)模式測試
python -m pytest test_remote.py -q⚠️ macOS 注意:別用
/usr/bin/python3(CommandLineTools 內建的 stub)建 venv, 它可能跳出xcode-select安裝提示。請改用 Homebrew 的python3(/opt/homebrew/bin/python3)或 pyenv。.venv/已列入.gitignore, 不會、也不該進版控;clone 後請各自重建。
註冊到 Claude Desktop / Cowork / Code
打開 Claude 的 MCP 設定檔(通常在 ~/Library/Application Support/Claude/claude_desktop_config.json 或對應路徑),加上:
{
"mcpServers": {
"email": {
"command": "python3",
"args": ["/Users/weiting/Documents/workspace/mcp-email/mcp_email.py"],
"env": {
"SMTP_HOST": "smtp.gmail.com",
"SMTP_PORT": "587",
"SMTP_USER": "you@gmail.com",
"SMTP_PASS": "<gmail app password>",
"SMTP_USE_TLS": "true",
"IMAP_HOST": "imap.gmail.com",
"IMAP_PORT": "993",
"IMAP_USER": "you@gmail.com",
"IMAP_PASS": "<gmail app password>",
"IMAP_USE_SSL": "true",
"EMAIL_FROM": "Your Name <you@gmail.com>",
"EMAIL_TIMEOUT_SEC": "30",
"EMAIL_RETRY_MAX": "3"
}
}
}
}重啟 Claude 後就會看到 email_* 系列 tool 出現。
不設環境變數也可以,啟動後第一次用之前先呼叫 email_configure 設定帳密(runtime 設定不會落地,重啟會清空)。
用環境變數 + wrapper(推薦:設定檔零密碼)
如果你的帳密放在 ~/.secrets(會被 shell source 的機密檔),可以用附帶的 run_server.sh:
它會先 source ~/.secrets 再啟動 server,所以連 GUI 啟動的 Claude Desktop 也吃得到 env、
而設定檔裡完全不用寫密碼。設定改成:
{
"mcpServers": {
"email": { "command": "/絕對路徑/mcp-email/run_server.sh" }
}
}環境變數別名:server 同時接受兩種命名,~/.secrets 不必改名 —
標準名 | 也接受的別名 |
|
|
|
|
|
|
帳密只需設一組:SMTP 與 IMAP 通常是同一個信箱帳號,所以帳密不必重複設 —
用共用的
EMAIL_USER/EMAIL_PASS(或MAIL_*),SMTP / IMAP 兩邊都吃;或只設一邊(例如只有
IMAP_USERNAME/IMAP_PASSWORD),另一邊會自動沿用同一組帳密。只有
host/port因協定不同需各自設(如smtp.x.com:587vsimap.x.com:993;自架常是同 host 不同 port)。
只設一個協定也可以:IMAP 與 SMTP 功能完全獨立 —— 只設 IMAP 就能用全部讀信工具
(list_folders / list_messages / get_message / mark / delete);
只設 SMTP 就能用 email_send。要兩種都用才需要兩邊的 host 都設。
遠端使用(本地以外)
以下兩種模式讓同一份 server 部署在內網主機 / NAS / 雲端 VM,多人共用。
共同原則:伺服器只設定主機資訊(IMAP_HOST / SMTP_HOST / port / TLS),
不設定任何人的帳密;每位使用者的帳密隨請求帶入、原樣 pass-through 給
IMAP/SMTP 登入,撤銷 = 使用者自己改密碼或撤掉應用程式專用密碼。
兩種模式都是明文帳密等級的傳輸,正式部署必須放在 HTTPS 反向代理後面
(nginx / Caddy / Synology 反向代理皆可)。放在反向代理後面時,記得設
EMAIL_ALLOWED_HOSTS=你的對外網域,否則 SDK 的 DNS-rebinding 防護會把
請求擋成 421 Invalid Host header。
遠端模式與 stdio 的行為差異(多人共用的安全考量):
email_configure停用並自 tool 列表隱藏(全域設定不容任一使用者改動)path附件預設停用(那是「伺服器」的檔案系統);請改用content_base64, 或由管理員設EMAIL_ATTACHMENT_DIRS白名單開放預設
From= 該請求登入的帳號(不吃伺服器端EMAIL_FROM)
HTTP 模式(Basic pass-through,適合內網共用)
# 已安裝(pip / pipx)或直接 uvx,一行起服務:
IMAP_HOST=mail.example.com SMTP_HOST=mail.example.com \
uvx mcp-email --http --host 0.0.0.0 --port 8765
# 從原始碼跑也一樣:python3 mcp_email.py --http --host 0.0.0.0 --port 8765主機設定也可以放在工作目錄的 .env 檔(KEY=VALUE 每行一組,環境變數優先),
不必每次打在指令前。
每位使用者在自己的 Claude Code 註冊(帳密只存在自己機器上):
claude mcp add --transport http email https://主機/mcp \
--header "Authorization: Basic $(printf '%s' '帳號:密碼' | base64)"伺服器不保存任何帳密、也絕不回退到環境變數憑證:沒帶 Authorization
標頭的工具呼叫一律被拒絕。
OAuth 模式(claude.ai Connectors:手機 app / 網頁版)
注意:OAuth 模式為單行程設計(進行中的授權交易存在記憶體), 不支援多副本負載平衡;token 本身無狀態,重啟不影響已發 token。
claude.ai 的連線來自 Anthropic 雲端,issuer 必須是公網可達的 HTTPS 網址:
# uvx(自動帶上 OAuth 模式的額外依賴 cryptography):
IMAP_HOST=mail.example.com SMTP_HOST=mail.example.com \
uvx --with cryptography mcp-email --oauth --issuer https://mail-mcp.example.com \
--host 0.0.0.0 --port 8765
# 或既有環境:pip install "mcp-email[oauth]"(= pip install cryptography)流程:標準 OAuth 2.1(動態註冊 + PKCE)。使用者第一次連接會被導到
/login 輸入信箱帳密(建議應用程式專用密碼),bridge 先以 IMAP 登入驗證,
通過後把憑證用伺服器金鑰 AES-GCM 加密封進 token —— 無狀態設計,
伺服器沒有憑證資料庫。access token 1 小時、refresh token 30 天自動輪替。
claude.ai 端:設定 → 連接器(Connectors)→ 新增自訂連接器 → 貼上
https://mail-mcp.example.com/mcp。
相關環境變數(皆選配):
變數 | 用途 |
| token 加密金鑰(urlsafe base64 的 32 bytes);沒設就自動產生 |
| 金鑰檔 / DCR client 註冊檔路徑(Docker 部署指向 |
| 設了之後,登入帳號沒打 |
| 登入失敗日誌(固定格式,供 fail2ban 監看封鎖來源) |
| 反向代理後的對外網域白名單(逗號分隔) |
⚠️ 金鑰是整個 OAuth 模式的單點要害:拿到 bridge 金鑰的人可以解開所有
已發 token 內的使用者憑證。金鑰檔 / EMAIL_BRIDGE_KEY 務必限縮讀取權限、
不進版控(repo 的 .gitignore 已排除 .bridge-key),有疑慮就換金鑰
(代價只是所有人重新授權一次)。
內建防護:登入頁同意畫面(顯示發起授權的應用程式名稱+授權碼送達的 網域,讓使用者辨識並攔截釣魚連結)、登入失敗節流(同 IP / 全域滑動視窗, 避免上游信箱服務封鎖 bridge 的 IP)、同授權交易密碼錯誤 5 次作廢、 登入頁安全標頭、auth log 自我輪替。搭配 fail2ban 的 filter 範例:
# /etc/fail2ban/filter.d/mcp-email.conf
[Definition]
failregex = mcp-email-login-fail ip=<HOST>
# jail:logpath 指向 EMAIL_AUTH_LOG 的路徑,maxretry/bantime 視需求Docker 部署
現成多架構 image(linux/amd64 + linux/arm64,打 v* tag 由 GitHub Actions 自動發佈):
# GHCR(免登入即可 pull)
docker pull ghcr.io/weiting-tw/mcp-email:latest
# Docker Hub(維護者設定 DOCKERHUB_* secret 後才會發佈)
docker pull weiting-tw/mcp-email:latest或自己建:
docker build -t mcp-email .
# HTTP 模式(把 mcp-email 換成上面的 image 名稱亦可)
docker run -d -p 8765:8765 \
-e IMAP_HOST=mail.example.com -e SMTP_HOST=mail.example.com \
mcp-email
# OAuth 模式(掛 /data volume 保留金鑰與 client 註冊)
docker run -d -p 8765:8765 -v mcp-email-data:/data \
-e IMAP_HOST=mail.example.com -e SMTP_HOST=mail.example.com \
mcp-email --oauth --issuer https://對外網址 --host 0.0.0.0 --port 8765容器以非 root(uid 10001)執行。OAuth 模式為單行程設計(授權交易存在 記憶體),不支援多副本負載平衡。
HTTPS 反向代理範例(Caddy,兩行搞定自動憑證)
mail-mcp.example.com {
reverse_proxy 127.0.0.1:8765
}nginx 使用者:proxy_pass http://127.0.0.1:8765; 並保留
proxy_set_header Host $host;;SSE 緩衝不用另外關(server 回應已帶
X-Accel-Buffering: no)。設好代理後記得配 EMAIL_ALLOWED_HOSTS=mail-mcp.example.com。
遠端部署上線前檢查清單
上線 --http / --oauth 前逐項確認,尤其打 ✅ 的三項是實務上最常害人踩雷的:
HTTPS 反向代理:帳密/token 是明文等級傳輸,一定要放在 TLS 後面,絕不裸跑對外。
EMAIL_ALLOWED_HOSTS:設成你的對外網域,否則 SDK 的 DNS-rebinding 防護會回421 Invalid Host header。✅ OAuth 金鑰要持久化:
--oauth一定要掛-v mcp-email-data:/data(或設固定的EMAIL_BRIDGE_KEY)。沒掛 volume→容器每次重啟都重新產生金鑰→所有人 token 全失效、要重新授權,這是最常見的災情。✅ 金鑰檔權限:
.bridge-key(或/data)只給執行帳號讀;拿到金鑰的人可解開所有已發 token 內的使用者憑證。已在.gitignore排除,切勿進版控。✅ 用應用程式專用密碼:宣導使用者在登入頁輸入 App Password,不要用信箱主密碼——外洩時只波及收發信、可單獨撤銷。
同意畫面:登入頁會顯示「哪個應用程式要連你的信箱」+「授權碼送達的網域」;提醒使用者只在認得目的地時才繼續(防釣魚)。
失敗節流 / fail2ban:設
EMAIL_AUTH_LOG並掛 fail2ban(filter 範例見上),擋帳密暴力猜測。path附件:遠端模式預設停用;若確有需求才用EMAIL_ATTACHMENT_DIRS白名單開放,範圍越小越好。token 生命週期已知:access 1 小時(自動續)、refresh 30 天(活躍使用者滾動不過期);使用者改密碼=所有舊 token 失效(需重新授權),這是刻意的撤銷機制。
常見信箱設定
服務 | SMTP host | port | TLS | IMAP host | port | SSL | 備註 |
Gmail |
| 587 | TLS |
| 993 | SSL | |
Outlook / Microsoft 365 |
| 587 | TLS |
| 993 | SSL | 帳號需開 SMTP / IMAP 開關 |
Outlook.com / Hotmail |
| 587 | TLS |
| 993 | SSL | 同上 |
Yahoo Mail |
| 587 | TLS |
| 993 | SSL | 需開 App Password |
iCloud Mail |
| 587 | TLS |
| 993 | SSL | 需開 App-specific Password |
Zoho Mail |
| 587 | TLS |
| 993 | SSL | |
自架(Postfix + Dovecot) | 視設定 | 587/465 | TLS / SSL | 視設定 | 143/993 | STARTTLS / SSL |
安全提醒:別把純密碼塞進 config 檔案明文。建議:
Gmail / Yahoo / iCloud / Outlook:用 App Password(兩階段驗證 → 應用程式密碼)
公司 Exchange:問 IT 拿 SMTP/IMAP credential,或用 OAuth(這個版本暫未支援 OAuth flow)
密碼存 macOS Keychain 並用
security find-generic-password -w動態注入
TLS / SSL 憑證驗證:預設兩邊都 驗 憑證(verify_cert: true)。自架信箱或公司內部用自簽憑證會在連線時 CERTIFICATE_VERIFY_FAILED 報錯。要關掉驗證:
// 環境變數
"SMTP_VERIFY_CERT": "false",
"IMAP_VERIFY_CERT": "false"或 runtime 用 email_configure:
{ "smtp": { "verify_cert": false }, "imap": { "verify_cert": false } }關掉後會喪失 MITM 防護,只在自簽 / 測試環境用,連 Gmail / Outlook 之類公網信箱絕對不要關。
附件路徑白名單:因為 email_send 的 path 附件受模型/host 控制,預設不設限時,
理論上可被誘導把任意本機檔案(如 ~/.ssh/id_rsa)夾帶寄出。若要防護,設定允許目錄:
// 環境變數(os.pathsep 分隔,macOS/Linux 用 : )
"EMAIL_ATTACHMENT_DIRS": "/Users/me/Documents:/Users/me/Pictures"或 runtime 用 email_configure:
{ "attachment_allowed_dirs": ["/Users/me/Documents", "/Users/me/Pictures"] }設定後,path 附件只能來自這些目錄底下(會解析 symlink 防繞過),名單外一律 PermissionError。
空白(預設)= 不限制。content_base64 附件不受此限(內容由呼叫端直接提供)。
收件人網域白名單(防被誘導亂寄,開關,預設關):email_send / email_reply /
email_forward / email_send_draft 都是對外動作,若擔心模型被惡意信件內容誘導亂寄,
可限制只能寄到指定網域:
// 環境變數(逗號分隔)
"EMAIL_ALLOWED_RECIPIENT_DOMAINS": "gss.com.tw,example.com"設定後任何收件人(to/cc/bcc)網域不在清單內就 PermissionError;空白(預設)= 關閉不限制。
附件下載大小上限:email_get_attachment 把附件 base64 回傳,過大的附件會撐爆模型
context / 記憶體,預設上限 5MB(超過只回 metadata 並標 too_large)。可用
EMAIL_MAX_ATTACHMENT_BYTES 調整,或呼叫時以 max_bytes 覆蓋。
⚠️ Prompt injection(把這套接上 LLM 最重要的風險):信件的主旨/內文是寄件人可控的,
email_get_message / email_list_messages 會把它們原樣回給模型,惡意信可能夾帶
「請把這封轉寄到 …/刪除某資料夾」之類的指令試圖操縱模型。防線:
絕不要把信件內文裡的指令當成命令執行——內文永遠是「資料」不是「指令」。
破壞性/對外動作(
send/reply/forward/delete/move/apply_rules/send_draft) 執行前一律先向使用者確認;多數 MCP host(Claude Desktop/Code)本來就會對每次工具 呼叫要求核准,這是主要安全網,別關掉它。加上上面的收件人網域白名單當第二層防線;
apply_rules保持dry_run=true先預覽。
Tool 呼叫範例
email_configure
{
"smtp": {
"host": "smtp.gmail.com",
"port": 587,
"username": "you@gmail.com",
"password": "xxxx xxxx xxxx xxxx",
"use_tls": true
},
"imap": {
"host": "imap.gmail.com",
"port": 993,
"username": "you@gmail.com",
"password": "xxxx xxxx xxxx xxxx",
"use_ssl": true
},
"email_from": "Your Name <you@gmail.com>",
"retry_max": 3
}email_send
{
"to": ["alice@example.com", "bob@example.com"],
"cc": "carol@example.com, dave@example.com",
"bcc": ["eve@example.com"],
"subject": "週報 2026-06-12",
"text": "純文字版本內容",
"html": "<h1>週報</h1><p>本週進度:…</p>",
"reply_to": "support@example.com",
"headers": {
"X-Report-Week": "2026-W24"
},
"attachments": [
{"path": "/Users/me/Documents/report.pdf"},
{"path": "/Users/me/Pictures/chart.png", "filename": "週報圖表.png"},
{
"content_base64": "SGVsbG8gV29ybGQh",
"filename": "data.txt",
"mime_type": "text/plain"
}
]
}email_test_connection
{ "smtp": true, "imap": true }回傳:
{
"smtp": {"ok": true, "host": "smtp.gmail.com", "port": 587},
"imap": {"ok": true, "host": "imap.gmail.com", "port": 993}
}email_list_messages
{
"folder": "INBOX",
"limit": 20,
"search": "UNSEEN"
}IMAP search syntax 常用:
ALL、UNSEEN、SEEN、FLAGGED、UNFLAGGED、ANSWERED、UNANSWERED、DELETED、DRAFT、RECENTFROM "alice@example.com"、TO "..."、CC "..."、SUBJECT "週報"SINCE 1-Jan-2026、BEFORE 31-Dec-2026、ON 12-Jun-2026邏輯:
UNSEEN FROM "alice"、OR FROM "alice" FROM "bob"、NOT SEEN
中文關鍵字:支援。非 ASCII 關鍵字會自動改用 SEARCH CHARSET UTF-8 + literal
(RFC 3501 標準做法);一次一個中文詞,且含 OR/NOT 時要放在最後一個條件。
若伺服器接受語法但比對不到(實測 Mail2000 不解 RFC2047 編碼的中文標頭),會自動
fallback 成「以剩餘 ASCII 條件縮小範圍 → 抓 header 在客戶端比對」(掃描上限 200 封,
回傳會附 note 說明)。email_apply_rules 的規則比對本來就在客戶端做,中文不受限。
email_get_message
{ "folder": "INBOX", "uid": "12345", "mark_read": false }email_mark / email_delete
{"folder": "INBOX", "uids": ["12345", "12346"], "flag": "\\Seen", "add": true}
{"folder": "INBOX", "uids": ["12345"]}驗證測試結果
=== 49/49 passed ===另有 test_mcp_stdio.py:用真正的 MCP client 把 mcp_email.py 以 stdio 子行程啟動,
跑完整 initialize → list_tools → 呼叫 tool 的 handshake,驗證能被任何 MCP host 載入。
以及 test_remote.py(40 tests):遠端模式的 Basic 標頭解析、每請求憑證覆蓋、
遠端限制(email_configure / path 附件停用、白名單 symlink 繞過)、
OAuth token 加解密與 provider 流程(含失敗節流、狀態清理、DCR 上限淘汰)、
in-process uvicorn 起真正 streamable-http server 的端對端測試——包括
「HTTP Basic 帳密穿透到 IMAP/SMTP 登入」與「DCR→PKCE→/login→token→Bearer
呼叫工具」的完整 OAuth 授權流程。
每次 push / PR 會由 GitHub Actions 在 Python 3.10–3.13 上自動跑兩支測試(見 .github/workflows/test.yml)。
涵蓋三類情境:
SMTP 寄信(in-process aiosmtpd 假 SMTP,真的把信送過去比對)
header(From / To / Cc / Reply-To / Subject)
bcc 不外漏(rcpt_tos 有 bcc 但 header 沒)
multipart:純文字 + HTML 兩個 part 都存在
附件:檔案 + base64 兩種來源,filename 含中文(
備註.txt)也對retry:port 沒人 listen 時 SMTP 會 raise
ConnectionRefusedError密碼不會出現在
email_configure回傳
錯誤路徑 / 安全
沒寄件人、沒收件人、附件不存在、壞 base64 各自 raise 對應 error
html-only 自動補純文字 fallback
附件白名單:名單外檔案被
PermissionError擋下、名單內正常附加
IMAP 讀信(FakeIMAP 取代真連線)
list_folders/list_messages(UID 正確解析)/get_message(text+html+附件 metadata)mark(flag 真的寫入)/delete(UID EXPUNGE,及不支援 UIDPLUS 時 fallback)/test_connection(IMAP NOOP)parser 健壯性:FLAGS/UID 出現在 BODY literal「之後」的回應排序也能正確解析
設計選擇 / 已知限制
無 OAuth flow:目前只支援帳密。Gmail / 365 OAuth2 比較複雜,要看後續是否真實需要再加。
不維護長連線:每次 IMAP 呼叫都重開連線。簡單可靠,效能上對「偶爾讀信」場景夠用;如果你要做「常駐 polling」可能要改長連線。
IMAP search 直接傳給伺服器:自由度高但要懂 RFC 3501 syntax;含空格的字串記得加雙引號(如
FROM "alice@x.com")。刪信用 UID EXPUNGE:
email_delete在 server 支援 UIDPLUS(RFC 4315)時只清掉你指定的 uid,不會誤刪資料夾內其他已標\Deleted的信;不支援時才 fallback 到一般EXPUNGE(回傳的method欄位會標明用了哪種)。附件大小:受 SMTP 伺服器限制(Gmail 25MB、Outlook 20MB、Exchange 視設定)。本工具不設上限,超過會直接 SMTP error。
遠端模式的多帳號:
--http/--oauth天生多人(每請求帶各自憑證、彼此隔離);stdio 模式仍是一個 instance 一個帳號,多帳號要靠 host 多開幾個 instance(每個給不同 env)。OAuth 模式單行程:授權交易存在記憶體,不支援多副本負載平衡;token 本身無狀態,重啟不影響已發 token(金鑰不變的前提下)。
發佈到 PyPI(維護者用)
推 v* tag 會由 GitHub Actions 自動 build + 發佈(.github/workflows/publish.yml,
走 PyPI Trusted Publishing,不需要 API token):
# 1. bump pyproject.toml 的 version 並 commit
# 2. 上 tag 並推出去,Actions 就會發佈
git tag v0.3.0 && git push origin v0.3.0一次性設定:PyPI 的 mcp-email 專案 → Settings → Publishing → 新增 GitHub publisher
(owner weiting-tw、repository mcp-email、workflow publish.yml、environment pypi),
並在 GitHub repo 的 Settings → Environments 建立名為 pypi 的 environment。
License
MIT。隨便用。