邮箱助手实战:以网易 163 邮箱为例 如果你只是想让脚本定时读取网易 163 邮箱,最短路径其实很清楚: 在网页端开启 生成并保存授权码 用 跑通第一版 Python 脚本 这篇文章写给第一次做邮箱自动化的人。看完之后,你应该能直接拿走三样东西: 什么时候该优先用 ,而不是 163 邮箱从网页端到授权码的完整开启路径 一段够用的 Python 验证脚本 其他邮箱这次只做迁移提示,不展开逐步截图。
如果你只是想让脚本定时读取网易 163 邮箱,最短路径其实很清楚:
IMAP/SMTPimap.163.com:993 跑通第一版 Python 脚本这篇文章写给第一次做邮箱自动化的人。看完之后,你应该能直接拿走三样东西:
IMAP,而不是 POP3其他邮箱这次只做迁移提示,不展开逐步截图。
还有一个环境边界先提前说清楚:
IMAP 脚本读取,是在 WSL Ubuntu 里实跑验证的WSL,只要你的 Python 运行环境能连到 imap.163.com:993,在 Windows、macOS、Linux 都可以跑WSL 这次主要影响的是 OpenClaw cron / gateway 这一层的运行细节,不是邮件协议本身很多人第一次做邮箱自动化,会先去找网页接口、Cookie,或者所谓的“邮箱 token”。
对 163 邮箱这类个人邮箱来说,真正更稳的入口还是标准邮件协议。
IMAP:适合读取邮件、同步状态POP3:也能收邮件,但更接近“下载收件箱”SMTP:负责发信,不负责读信凭证这件事也一样。
脚本侧真正该优先准备的,通常不是网页登录密码,而是网页邮箱设置页里生成的授权码。
所以这篇文章的主线非常简单:
IMAP如果你的目标只是把邮件下载到本地,POP3 也能完成任务。
但如果你想做一个后续还能继续扩展的“邮箱助手”,IMAP 更合适。
原因不复杂。IMAP 更接近“远程操作服务器上的邮箱”,而不只是把邮件拽下来:
网易帮助中心对这一点有明确说明:开启 IMAP 后,客户端上的删除、已读等操作会反馈到服务器,因此网页端和客户端里看到的状态通常是一致的。
下面这张对照图能更直观看出差异:

如果只记一句话,可以先这么理解:
POP3 更像下载器IMAP 更像同步协议先打开网易邮箱入口:https://email.163.com/

登录完成后,你会进入 163 邮箱主页。

到这里为止,你还只是完成了“网页邮箱登录”。
这一步离脚本可读邮件还差关键一步:开启邮件协议服务并生成授权码。
在顶部导航里点击“设置”,再进入 POP3/SMTP/IMAP。

这也是网易帮助中心给出的官方开启路径:
设置 -> POP3/SMTP/IMAP对这篇文章来说,重点只放在 IMAP/SMTP。
如果你的目标是“让脚本读取 163 邮箱”,优先开启 IMAP/SMTP 这一组。
点击“开启”后,页面会先弹出继续开启的确认提示:

完成页面要求的验证后,会看到开启成功的提示:

如果你后面还要兼容某些历史设备、旧系统,或者沿用既有的 POP3 收信流程,也可以额外开启 POP3/SMTP。
对应的成功提示长这样:

但对 Python 自动化读取来说,第一优先级仍然是先把 IMAP/SMTP 跑通。
IMAP/SMTP 开启完成后,页面下方会出现授权码管理区域。这里要重点看两件事:

如果你这里已经有旧授权码记录,先处理掉不再使用的旧记录,再重新生成新的授权码会更稳。
如果你点击新增或重新生成,页面会弹出授权码窗口。这里展示的这串字符,就是后面第三方客户端或 Python 脚本要使用的登录凭证。

一个很重要的细节是:授权码不会像网页密码那样一直摆在那里。
复制之后,就消失了,所以注意复制好之后保管好。
所以这里最稳的做法是:
如果你要读取网易 163 邮箱,第一版最小配置通常就是这几个:
MAIL_HOST=imap.163.com MAIL_PORT=993 MAIL_USER=your_name@163.com MAIL_PASSWORD=replace_with_authorization_code MAIL_FOLDER=INBOX MAIL_FETCH_LIMIT=10
这里最容易填错的是两项:
MAIL_HOST 不要写成网页地址 email.163.comMAIL_PASSWORD 不要优先填网页登录密码,应先尝试授权码要把这两个地址分开看:
https://email.163.com/ 是给人用的网页入口imap.163.com:993 是脚本连接邮件协议时更常用的服务端点163 邮箱设置页里也能看到这组协议服务器地址:

这点也能和华为官方支持页里的第三方邮箱配置说明对上。
如果你现在就想先跑通,不想自己拼步骤,直接照着下面做。
这一节对应的现成文件都在同目录 examples/ 里:
examples/imap_connect_test.pyexamples/yesterday_mail_report.pyexamples/.env.exampleexamples/requirements.txtexamples/README.mdexamples/openclaw_setup_prompt.md.env.example在 examples/ 目录里,把 .env.example 复制成 .env,然后填入你自己的邮箱地址和授权码。
MAIL_HOST=imap.163.com MAIL_PORT=993 MAIL_USER=your_name@163.com MAIL_PASSWORD=replace_with_authorization_code MAIL_FOLDER=INBOX MAIL_FETCH_LIMIT=5
如果你本地已经有可用的 python:
pip install -r requirements.txt python imap_connect_test.py
如果你更适合直接用 uv,可以一步跑完:
uv run --with python-dotenv imap_connect_test.py
至少出现下面这些信号,就说明链路已经打通:
tcp_tls = successlogin_status = OKid_status = OKresult = success如果还能看到最近几封邮件的 subject / from / date / preview,说明脚本已经不只是连通,而是真的把邮件读出来了。
第一版脚本的目标不需要太大。
先验证你的 163 邮箱能不能通过 IMAP 被 Python 读到,就已经足够。
下面这版脚本只依赖 Python 标准库,适合做第一次联通性验证:
import email import imaplib import os from email.header import decode_header def decode_mime_words(value: str) -> str: if not value: return "" parts = decode_header(value) decoded = [] for text, encoding in parts: if isinstance(text, bytes): decoded.append(text.decode(encoding or "utf-8", errors="replace")) else: decoded.append(text) return "".join(decoded) def fetch_recent_emails(): host = os.environ["MAIL_HOST"] port = int(os.environ.get("MAIL_PORT", "993")) user = os.environ["MAIL_USER"] password = os.environ["MAIL_PASSWORD"] folder = os.environ.get("MAIL_FOLDER", "INBOX") limit = int(os.environ.get("MAIL_FETCH_LIMIT", "10")) mail = imaplib.IMAP4_SSL(host, port) mail.login(user, password) mail.select(folder) status, data = mail.search(None, "ALL") if status != "OK": raise RuntimeError("failed to search mailbox") mail_ids = data[0].split() target_ids = mail_ids[-limit:] results = [] for mail_id in reversed(target_ids): status, msg_data = mail.fetch(mail_id, "(RFC822)") if status != "OK": continue raw_message = msg_data[0][1] message = email.message_from_bytes(raw_message) results.append( { "id": mail_id.decode(), "subject": decode_mime_words(message.get("Subject", "")), "from": decode_mime_words(message.get("From", "")), "date": message.get("Date", ""), } ) mail.close() mail.logout() return results if __name__ == "__main__": emails = fetch_recent_emails() for item in emails: print("=" * 60) print("ID:", item["id"]) print("From:", item["from"]) print("Date:", item["date"]) print("Subject:", item["subject"])
这段脚本只做三件事:
只要这一版能跑通,后面再加未读筛选、正文提取、附件下载、定时任务,都是增量扩展。
不过如果你要直接拿去连 163 邮箱,建议优先用同目录 examples/ 里的实跑版本。
原因很简单:163 这边在真实联通测试里,实跑版脚本已经把连接细节补完整了,更适合直接复用。
如果你想直接照着做,优先看:
examples/README.mdexamples/imap_connect_test.pyexamples/.env.exampleexamples/requirements.txt这次我已经在当前环境里实跑过一次,成功链路可以直接收成下面几点:
TCP/TLS 连接成功LOGIN 成功SELECT INBOX 成功脱敏后的实际输出如下。为了节省篇幅,下面只保留其中一条邮件记录作为示例:
{ "host": "imap.163.com", "port": 993, "user": "191***67@163.com", "tcp_tls": "success", "login_status": "OK", "connection": "login_success", "imap_id": { "capability_status": "OK", "capabilities": [ "IMAP4rev1 XLIST SPECIAL-USE ID LITERAL+ STARTTLS APPENDLIMIT=71680000 XAPPLEPUSHSERVICE UIDPLUS X-CM-EXT-1 SASL-IR AUTH=XOAUTH2" ], "id_supported": true, "id_sent": true, "id_status": "OK" }, "mailbox": { "folder": "INBOX", "total_messages": 5, "fetched_items": [ { "message_id": "5", "subject": "新设备登录提醒", "from": "网易邮箱账号安全 <safe@service.netease.com>", "date": "Sat, 14 Mar 2026 11:59:43 +0800 (CST)", "preview": "@media screen and (min-width:750px)..." } ] }, "result": "success" }
这个结果已经足够说明:你的 163 邮箱 IMAP 地址、授权码和脚本读取链路,在当前环境里是跑通的。
这里也顺手把验证边界说清楚:
WSL Ubuntu + Python + 163 IMAP + 授权码 这条链路OpenClaw cron,不同宿主环境的 gateway 启动方式可能会不一样如果你接下来的目标不是“手动跑脚本”,而是让龙虾每天早上自动汇报昨天的邮件,建议把这件事拆成四层:
第一版最省事的做法,不是先封成 Skill,而是先把脚本放进龙虾当前工作目录。
一个够用的目录结构可以是:
your-openclaw-workspace/ .env scripts/ yesterday_mail_report.py
这里直接复用同目录 examples/ 里的脚本即可:
examples/yesterday_mail_report.py如果你不想手动创建 scripts/ 和复制文件,也可以直接把这个脚本文件上传给龙虾,再用现成提示词让它自己落盘:
examples/openclaw_setup_prompt.md本仓库关于 OpenClaw 环境变量的说明很清楚:
加载优先级依次是:
.env~/.openclaw/.env所以最短路径就是把邮箱配置写进当前工作目录 .env:
MAIL_HOST=imap.163.com MAIL_PORT=993 MAIL_USER=your_name@163.com MAIL_PASSWORD=replace_with_authorization_code MAIL_FOLDER=INBOX
这里建议把职责分开:
yesterday_mail_report.py 只输出 JSON你可以直接给龙虾这段提示词:
请运行当前工作目录下的 scripts/yesterday_mail_report.py。 读取脚本输出的 JSON,只汇报昨天 00:00-23:59 的邮件内容。 输出时按四类整理: 1. 需要我处理 2. 安全提醒 3. 系统通知 4. 可忽略邮件 每封邮件只保留: - 主题 - 发件人 - 时间 - 一句话摘要 最后再给一个「今天需要优先处理的事项」小节。 如果 total_messages = 0,就直接告诉我:昨天没有需要汇报的新邮件。
如果你希望龙虾连“保存脚本到工作目录”这一步也一起做,而不是先手动复制文件,直接用:
examples/openclaw_setup_prompt.md里面已经给了三种可直接复制的提示词:
.env.exampleOpenClaw 支持 cron 调度。
如果你要每天早上 9 点汇报昨天的邮件,可以这样加:
openclaw cron add \ --name "163 昨日邮件摘要" \ --cron "0 9 * * *" \ --session isolated \ --message "请运行当前工作目录下的 scripts/yesterday_mail_report.py。读取脚本输出的 JSON,只汇报昨天 00:00-23:59 的邮件内容,按需要我处理、安全提醒、系统通知、可忽略四类整理;如果 total_messages = 0,就直接告诉我昨天没有需要汇报的新邮件。" \ --announce
创建之后,可以用下面这个命令确认:
openclaw cron list --json
本仓库关于 cron 的文档还提醒了一点:整点任务可能会自动分散到 0-5 分钟内执行。
所以这里更准确的理解是“以 9:00 为目标的晨间任务”。
这篇文章不是强制要求 WSL。
如果你的 OpenClaw 本来就在 macOS、Linux 或 Windows 本机环境里跑,直接按你自己的安装方式执行即可。
但如果你和这次实测环境一样,是 Windows 宿主机 + WSL Ubuntu,有两个细节值得提前写清楚:
cron 相关命令依赖 gateway 先启动cron list --json 做检查更稳这次实测里,WSL 中需要先执行:
systemctl --user start openclaw-gateway.service
然后再去跑 cron status、cron add、cron rm 之类的命令。
这次补测时还确认了一点:
如果 gateway 刚重启就立刻执行 cron,有机会碰到:
gateway closed (1006 abnormal closure)
更稳的做法是:先启动或重启 gateway,再等 2-3 秒,再去执行 cron list、cron add、cron rm。
还有一个这次实测出的现象:
在当前 WSL 环境里,优先把 cron list --json 当成检查命令更稳。
一方面它更适合程序化判断;另一方面,gateway 如果还没 ready,文本版和 JSON 版都可能一起报错,这时候先补一次等待再重试,比直接把结果理解成“没有任务”更可靠。
所以如果你是 WSL 路线,建议把下面这条当成检查任务的默认命令:
openclaw cron list --json
如果你发现 openclaw 命令本身不在当前 shell 的 PATH 里,也不要急着判断成“没有安装”。
先检查:
nvm 之类的方式安装在其他路径也就是说,WSL 在这里更像是一个已验证过可行、但要注意启动顺序和 PATH 的运行环境,而不是“必须路线”。
这件事不需要只押一种方式。
openclaw cron add,属于命令式部署这两种方式都成立。
如果你想先确保细节不走偏,命令式更可控;如果你想把这件事彻底交给龙虾接管,提示词式更省手。
如果你只是自己先跑通,这一版已经够用。
如果后面你要长期复用,或者想让多个工作空间都能直接调起这个邮箱助手,再把它封装成工作空间技能更合适。
本仓库文档给出的工作空间技能目录是:
~/.openclaw/workspace/skills/
第一次写邮箱助手时,一个很常见的问题是:IMAP 能不能像消息推送一样实时来信?
工程上更准确的理解是:
IMAP 协议本身也支持 IDLE,更接近“等服务器通知”最简单的轮询思路就是:
import time while True: fetch_recent_emails() time.sleep(60)
这样做的原因很现实:
如果后面你真的需要更强的实时性,再去研究 IMAP IDLE 和长连接重连策略会更稳。
这两个地址的角色不同:
email.163.com 是网页邮箱入口imap.163.com 才是脚本读取邮件时更常用的协议服务地址如果你已经开启了 IMAP/SMTP,脚本却还是报认证失败,优先检查这一点。
很多问题不是 Python 写错了,而是凭证填错了。
网易帮助中心明确提到,开启相关服务时要按页面提示完成验证。
流程没走完,脚本侧依然可能无法登录。
更稳的顺序应该是:
这样排错成本会低很多。
这篇主要以 163 为例,其他邮箱只给迁移思路。
和 163 基本是同一类处理方式:
IMAP/POP3/SMTP 相关服务思路也接近:
IMAP 或 POP3自建邮箱的关键不在“是不是自建”,而在于:
IMAP如果服务端允许 IMAP + 密码认证,脚本通常就能直接读取。
如果基础认证被关闭,只开放 OAuth 或其他认证方式,那就不能照搬 163 这一套。
先做哪一步最划算?
先在网页端开启 IMAP/SMTP,保存授权码,然后用 imap.163.com:993 跑通第一版 Python 脚本。只要这一步成功,后面的邮箱助手就有了一个可靠起点。