Skip to content

Repository files navigation

163mail-mcp

一个最小可用的 163 邮箱 MCP 服务,使用 Go + Rod 通过真实浏览器自动化访问 https://mail.163.com

当前实现了 4 个核心工具:

  • login
  • check_login_status
  • send_mail
  • send_mail_with_big_attachment

功能概览

login

打开 163 邮箱登录页,并优先尝试使用环境变量自动登录。

  • 如果配置了环境变量 MAIL163_USERNAMEMAIL163_PASSWORD,会优先自动登录
  • 如果自动登录失败,会回退到手动登录
  • 如果没有配置环境变量,会直接等待用户手动登录

check_login_status

检查当前浏览器页面中是否存在 #dvNavContainer

  • 存在:表示已登录
  • 不存在:表示未登录

send_mail

发送邮件,参数要求:

  • to:收件人,不能为空
  • subject:主题,不能为空
  • content:正文,不能为空
  • 支持多个收件人,多个邮箱用分号 ; 分隔
  • 会校验邮箱格式

发送流程:

  1. 打开 163 邮箱页面
  2. 检查是否已登录
  3. 如果未登录,优先尝试环境变量自动登录
  4. 点击“写信”
  5. 填写收件人、主题、正文
  6. 点击“发送”
  7. 等待 #sucAnimIcon.suc-anim-icon.had-finish-anim
  8. 返回发送成功信息

send_mail_with_big_attachment

发送带本地大附件的邮件,参数要求:

  • to:收件人,不能为空
  • subject:主题,不能为空
  • content:正文,不能为空
  • attachment_paths:本地附件路径数组,不能为空
  • 最多支持 5 个附件
  • 单个附件大小不能超过 500MB

发送流程:

  1. 打开 163 邮箱页面
  2. 检查是否已登录
  3. 如果未登录,优先尝试环境变量自动登录
  4. 点击“写信”
  5. 填写收件人、主题、正文
  6. 向页面中的 input[type="file"] 注入本地附件路径
  7. 持续等待附件上传和扫描完成
  8. 点击“发送”
  9. 返回发送成功信息

说明:

  • attachment_paths 建议传绝对路径
  • 大附件上传和网易侧扫描可能持续较长时间,服务端会在上传阶段持续轮询等待
  • 服务内部会为附件创建 ASCII 临时上传文件名,以避免中文文件名或特殊字符影响浏览器上传
  • 收件人看到的附件名会是服务内部生成的安全临时名,而不是原始中文文件名
  • 如果任一附件不存在、不可访问、或路径是目录,会在打开浏览器前直接报错,不再继续尝试发送

登录策略

当前登录策略分为两层:

1. 自动登录

如果设置了以下环境变量:

  • MAIL163_USERNAME
  • MAIL163_PASSWORD

服务会优先尝试自动登录。

其中 MAIL163_USERNAME 支持以下规则:

  • 如果值是 xxx@163.com,登录时会自动裁剪成 xxx
  • 如果不是 @163.com 结尾,则原样使用

自动登录时会尝试勾选“30天免登录”复选框:

  • input#un-login[name="un-login"]

2. 手动登录

如果自动登录失败,或者没有配置环境变量,用户可以直接在浏览器中手动登录。

服务会复用固定浏览器 profile,因此手动登录成功后,后续重启 MCP server 时通常仍然可以保留登录状态。

浏览器与 Profile

默认浏览器

在 macOS 下,默认优先使用:

/Applications/Google Chrome.app/Contents/MacOS/Google Chrome

如果没有找到这个路径,则回退到 Rod 默认浏览器。

固定 Profile

默认浏览器 profile 目录:

~/.163mail-mcp/browser-profile

这意味着:

  • 手动登录成功后,登录态通常会被保存在这个目录里
  • 重启 MCP server 后,大概率不需要重新登录

你也可以通过参数自定义 profile:

-user-data-dir=/path/to/profile

运行环境

  • macOS
  • Windows
  • Linux / Docker

安装

1. 安装依赖

go mod tidy

2. 启动服务

go run . -addr :16161

启动参数说明

参数 含义 是否必填 默认值
-addr HTTP 监听地址 :16161
-headless 是否以无头模式运行浏览器 false
-browser-bin 自定义浏览器可执行文件路径 macOS 下优先尝试系统 Chrome,否则回退到 Rod 默认浏览器
-user-data-dir 浏览器 profile 目录 ~/.163mail-mcp/browser-profile

环境变量说明

环境变量 含义 是否必填 默认值
MAIL163_USERNAME 163 邮箱账号,用于自动登录和默认调试回执收件人 自动登录场景下必填
MAIL163_PASSWORD 163 邮箱密码,用于自动登录 自动登录场景下必填
MAIL163_DEBUG_REPORT_ENABLED 是否开启“发送成功后自动回寄调试回执” false
MAIL163_DEBUG_REPORT_RECIPIENT 调试回执收件人邮箱 默认使用 MAIL163_USERNAME

说明:

  • 如果未设置 MAIL163_USERNAMEMAIL163_PASSWORD,服务仍可启动,但需要手动登录
  • 如果 MAIL163_DEBUG_REPORT_ENABLED=false,则不会发送调试回执
  • MAIL163_DEBUG_REPORT_RECIPIENT 仅在开启调试回执时生效

Docker 支持

项目现在可以直接构建为 Docker image,并在容器里运行。

Docker 部署步骤

  1. 构建镜像
  2. 准备宿主机挂载目录
  3. 启动容器
  4. 使用 /healthz 检查服务状态

1. 构建镜像

docker build -t 163mail-mcp:latest .

如果你准备把镜像部署到 Windows 宿主机上的 Linux 容器环境,建议显式构建 linux/amd64

docker build --platform linux/amd64 -t 163mail-mcp:latest .

如果你想显式指定 Go 大版本,也可以:

docker build --build-arg GO_VERSION=1.26 -t 163mail-mcp:latest .

2. 启动容器

mkdir -p $(pwd)/data $(pwd)/attachments

docker run -d \
  --name 163mail-mcp \
  --shm-size=1g \
  -p 16161:16161 \
  -e MAIL163_USERNAME='your_account@163.com' \
  -e MAIL163_PASSWORD='your_password' \
  -e MAIL163_DEBUG_REPORT_ENABLED='true' \
  -v 163mail-browser-profile:/data/browser-profile \
  -v $(pwd)/attachments:/attachments \
  163mail-mcp:latest

Docker 参数说明

配置项 含义 是否必填 默认值
-p 16161:16161 将宿主机 16161 端口映射到容器内服务端口 建议填写
MAIL163_USERNAME 163 邮箱账号,用于自动登录 自动登录场景下必填
MAIL163_PASSWORD 163 邮箱密码,用于自动登录 自动登录场景下必填
MAIL163_DEBUG_REPORT_ENABLED 是否开启发信后自动发送调试回执 false
MAIL163_DEBUG_REPORT_RECIPIENT 调试回执收件人 默认使用 MAIL163_USERNAME
--shm-size=1g 为容器内 Chromium 提供更稳定的共享内存空间 强烈建议 Docker 默认值
-v 163mail-browser-profile:/data/browser-profile 用 Docker named volume 持久化浏览器 profile 强烈建议
-v $(pwd)/attachments:/attachments 挂载附件目录,供 send_mail_with_big_attachment 使用 带附件发信场景下建议填写

说明:

  • 容器默认会以 -headless=true 启动 Chromium
  • 容器内浏览器路径固定为 /usr/bin/chromium
  • 浏览器 profile 持久化目录为 /data/browser-profile
  • 推荐把浏览器 profile 单独放进 Docker named volume,而不是直接映射到 Windows 宿主机目录
  • 如果要发送本地大附件,建议把宿主机目录挂载到容器内 /attachments
  • 调用 send_mail_with_big_attachment 时,attachment_paths 应传容器内路径,例如 /attachments/demo.pdf
  • 如果设置 MAIL163_DEBUG_REPORT_ENABLED=true,每次发送成功后会自动向回执邮箱再发送一封调试回执
  • 默认回执邮箱取 MAIL163_USERNAME;也可以单独设置 MAIL163_DEBUG_REPORT_RECIPIENT
  • 这个调试回执开关是服务端环境配置,不是 MCP tool 参数,因此调用方不能在单次请求里随意打开它
  • 调试回执邮件内部不会再次触发调试回执,因此不会形成死循环

3. 检查服务状态

curl http://127.0.0.1:16161/healthz

4. 查看日志

docker logs -f 163mail-mcp

5. 手动登录如何处理

Docker 默认使用无头浏览器,因此更推荐配置:

  • MAIL163_USERNAME
  • MAIL163_PASSWORD

也就是优先走自动登录。

如果你确实想在容器里做“手动登录”,通常还需要额外接入可视化桌面、VNC 或远程调试方案,这不是当前 Docker 默认用法。

6. 使用 docker compose

项目根目录已经提供了 docker-compose.yml

先设置环境变量:

export MAIL163_USERNAME='your_account@163.com'
export MAIL163_PASSWORD='your_password'
export MAIL163_DEBUG_REPORT_ENABLED='true'
# 可选:不填时默认回寄到 MAIL163_USERNAME
# export MAIL163_DEBUG_REPORT_RECIPIENT='your_account@163.com'

然后启动:

docker compose up -d --build

如果你想看配置内容,当前 compose 文件等价于:

services:
  mail163-mcp:
    build: .
    container_name: 163mail-mcp
    ports:
      - "16161:16161"
    environment:
      MAIL163_USERNAME: your_account@163.com
      MAIL163_PASSWORD: your_password
      MAIL163_DEBUG_REPORT_ENABLED: "true"
      MAIL163_DEBUG_REPORT_RECIPIENT: your_account@163.com
    shm_size: "1gb"
    volumes:
      - mail163_browser_profile:/data/browser-profile
      - ./attachments:/attachments
    restart: unless-stopped

volumes:
  mail163_browser_profile:

7. 浏览器 Profile 被锁住时如何修复

如果容器启动时报类似错误:

The profile appears to be in use by another Chromium process

通常说明上一次 Chromium 没有正常退出,/data/browser-profile 下残留了锁文件。

推荐修复方式:

  1. 先停止并删除旧容器
docker rm -f 163mail-mcp
  1. 如果使用的是宿主机目录挂载,删除 profile 锁文件
cd /path/to/163mail-mcp

find data/browser-profile -maxdepth 1 \
  \( -name 'Singleton*' -o -name 'SingletonLock' -o -name 'SingletonSocket' -o -name 'SingletonCookie' \) \
  -print -delete
  1. 重新启动容器
docker run -d \
  --name 163mail-mcp \
  -p 16161:16161 \
  -e MAIL163_USERNAME='your_account@163.com' \
  -e MAIL163_PASSWORD='your_password' \
  -e MAIL163_DEBUG_REPORT_ENABLED='true' \
  -v $(pwd)/data:/data \
  -v $(pwd)/attachments:/attachments \
  163mail-mcp:latest

说明:

  • 不建议直接删除整个 data/browser-profile
  • 删除整个 profile 会丢失登录态,通常需要重新登录 163 邮箱
  • 只有在锁文件清理后仍然无法恢复,或者 profile 已损坏时,才建议删除整个 browser-profile
  • 如果使用的是 Docker named volume,更简单的做法通常是删除旧 volume 后重新启动,再重新登录一次 163 邮箱

8. Windows / Docker Desktop 常见问题

如果你的宿主机是 Windows,容器里又需要运行 Chromium,这里有几个高概率问题值得优先排查。

8.1 qemu: uncaught target signal 5 或 Chromium 一启动就崩

这通常说明当前运行的镜像架构和生产环境不匹配,例如把错误架构的镜像直接拷到了 Windows 机器上,导致 Chromium 在模拟层里运行。

推荐做法:

  1. 在构建机上显式构建 linux/amd64
docker build --platform linux/amd64 -t 163mail-mcp:latest .
  1. 构建后检查镜像架构:
docker image inspect 163mail-mcp:latest --format '{{.Architecture}}/{{.Os}}'

预期输出:

amd64/linux
  1. docker compose 中给服务补上:
platform: linux/amd64

8.2 The profile appears to be in use by another Chromium process

这通常是上一次 Chromium 异常退出后,浏览器 profile 遗留了锁文件或损坏状态。

推荐做法:

  • 优先把浏览器 profile 放在 Docker named volume 中,而不是 Windows 宿主机目录
  • 如果仍然报错,删除旧的 mail163_browser_profile volume 后重新启动容器
  • 删除旧 profile 后,通常需要重新登录一次 163 邮箱

8.3 create page: EOF / use of closed network connection

这类错误通常说明 Rod 与 Chromium 的调试连接已经断开。当前服务已经增加了浏览器会话断连后的自动重建逻辑,但如果错误在每次启动后都稳定复现,通常仍要优先排查底层 Chromium 运行环境:

  • 镜像架构是否正确
  • 是否配置了 shm_size: "1gb"--shm-size=1g
  • 浏览器 profile 是否放在 Docker named volume 中
  • 是否存在上一次异常退出遗留的锁文件或损坏 profile

8.4 docker build 时拉取 Chromium 包失败

如果日志里卡在 chromium_*.deb 下载失败、Connection failed502 Bad Gateway 之类错误,通常不是代码问题,而是构建时 APT 源网络不稳定。当前 Dockerfile 已经做了这些处理:

  • 默认切换到国内 Debian 镜像源
  • apt-get update 增加重试和超时
  • chromium 的安装拆成单独重试

建议:

  • 优先在网络更稳定的机器上构建出镜像,再导出为 tar 交给生产机 docker load
  • 如果构建成功,部署前再次确认镜像架构是 amd64/linux

8.5 Windows 上的推荐 compose 片段

services:
  mail163-mcp:
    image: 163mail-mcp:latest
    platform: linux/amd64
    container_name: 163mail-mcp
    ports:
      - "16161:16161"
    environment:
      MAIL163_USERNAME: your_account@163.com
      MAIL163_PASSWORD: your_password
      MAIL163_DEBUG_REPORT_ENABLED: "true"
      MAIL163_DEBUG_REPORT_RECIPIENT: your_account@163.com
    shm_size: "1gb"
    volumes:
      - mail163_browser_profile:/data/browser-profile
      - ./attachments:/attachments
    restart: unless-stopped

volumes:
  mail163_browser_profile:

推荐启动方式

如果你在国内网络环境,建议这样启动:

cd /path/to/163mail-mcp

GOMODCACHE=$(pwd)/.gomodcache \
GOCACHE=$(pwd)/.gocache \
GOPROXY=https://goproxy.cn,direct \
GOSUMDB=off \
/usr/local/go/bin/go run . -addr :16161

自动登录示例

先设置环境变量:

export MAIL163_USERNAME='your_account@163.com'
export MAIL163_PASSWORD='your_password'

再启动服务:

cd /path/to/163mail-mcp

GOMODCACHE=$(pwd)/.gomodcache \
GOCACHE=$(pwd)/.gocache \
GOPROXY=https://goproxy.cn,direct \
GOSUMDB=off \
/usr/local/go/bin/go run . -addr :16161

手动登录示例

如果你不想设置环境变量,也可以直接启动服务:

cd /path/to/163mail-mcp

GOMODCACHE=$(pwd)/.gomodcache \
GOCACHE=$(pwd)/.gocache \
GOPROXY=https://goproxy.cn,direct \
GOSUMDB=off \
/usr/local/go/bin/go run . -addr :16161

然后调用 login,在浏览器中手动完成登录。

HTTP 接口

服务默认提供:

  • POST /mcp
  • GET /healthz

健康检查

curl http://127.0.0.1:16161/healthz

MCP 调用示例

initialize

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {}
}

tools/list

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

send_mail_with_big_attachment

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "send_mail_with_big_attachment",
    "arguments": {
      "to": "foo@example.com;bar@example.com",
      "subject": "带附件测试",
      "content": "这是正文",
      "attachment_paths": [
        "/absolute/path/report.pdf",
        "/absolute/path/archive.tar"
      ]
    }
  }
}

login

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "login",
    "arguments": {}
  }
}

check_login_status

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "check_login_status",
    "arguments": {}
  }
}

send_mail

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "send_mail",
    "arguments": {
      "to": "foo@example.com;bar@example.com",
      "subject": "测试主题",
      "content": "测试正文"
    }
  }
}

推荐测试顺序

场景 1:手动登录

  1. 启动服务
  2. login
  3. 在浏览器中手动登录
  4. check_login_status
  5. send_mail

场景 2:自动登录

  1. 设置 MAIL163_USERNAMEMAIL163_PASSWORD
  2. 启动服务
  3. 直接调 send_mail

日志说明

服务端会输出关键步骤日志,便于排查问题,例如:

  • 浏览器路径
  • profile 目录
  • 登录检查
  • 自动登录流程
  • 写信步骤
  • 正文填写方式
  • 登录失败提示

已知限制

  • 163 邮箱页面结构如果变化,定位器可能需要调整
  • 自动登录依赖当前登录页 DOM,如果 163 登录页变更,可能需要重新适配
  • 某些情况下如果出现验证码、风控、滑块校验,仍需要手动登录
  • 正文编辑器位于 iframe 中,当前实现会优先定位 iframe.APP-editor-iframe
  • 当前实现是最小版本,没有附件、抄送、草稿、收件箱查询等能力

About

使用163网页自动发送邮箱,主要解决的是大附件的邮件不能自动发送的问题,如果不是大附件的问题,建议写代码调用smtp

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages