Skip to content

feat: 连接代理(HTTP CONNECT / SOCKS)for IMAP and SMTP - #32

Open
sujianddd-dev wants to merge 1 commit into
STARDUSTLC666:mainfrom
sujianddd-dev:feat/proxy-support
Open

sujianddd-dev wants to merge 1 commit into
STARDUSTLC666:mainfrom
sujianddd-dev:feat/proxy-support

Conversation

@sujianddd-dev

Copy link
Copy Markdown

问题

插件只能直连邮箱服务器:nodemailer 本身没有代理选项,插件也没有把代理传给 imapflow(它其实自带 proxy 选项)。在网络必须经代理才能连 Gmail/Outlook 的环境里(例如国内直连 smtp.gmail.com:465、imap.gmail.com:993 不通),email_send 表现为 60 秒工具超时或 ESOCKET connect ETIMEDOUT,只能靠外部中继脚本绕过。

改动

  • 账号新增 proxy:http(CONNECT) / https / socks4 / socks4a / socks5 / socks5h;省略协议按 http 处理(127.0.0.1:7897 这种粘贴写法直接可用)。账号级覆盖顶层简写,具名账号可各自不同。
  • 未配置时依次回退 HTTPS_PROXY → HTTP_PROXY → ALL_PROXY(大小写皆可),并遵守 NO_PROXY。显式配置的 proxy 优先于 NO_PROXY:那是用户对这个账号的直接意图。
  • IMAP 交给 imapflow 自带的代理实现;SMTP 在插件已有的 getSocket 钩子里建立 CONNECT / SOCKS 隧道,再由 nodemailer 在隧道上起 TLS,servername 固定为真实邮箱主机——证书校验落在邮箱服务器而不是代理上。
  • 代理地址在配置解析阶段校验(src/config.ts),写错会在「设置 → 邮件」报 代理地址无效,而不是使用时报一个说不清的超时。
  • 直连路径零改动:不传 proxy 时不新增任何传输选项。
  • socks 提升为显式依赖(原本只是 imapflow 的传递依赖,直接 import 必须声明)。
  • 文档:docs/USAGE.md、docs/USAGE.en.md 新增「代理」一节与配置项表格行;README 中英文各加一句;CHANGELOG 加「未发布」条目。

验证

  • node --test "test/*.test.mjs":413 项全部通过(新增 test/proxy.test.mjs 6 项:地址解析、环境回退与 NO_PROXY、CONNECT 隧道真实回显、代理 407 拒绝、代理不可达、配置继承与校验)。
  • 真机端到端(Windows,Clash 监听 127.0.0.1:7897,Gmail 账号):
    • IMAP:new ImapFlow({..., proxy:'http://127.0.0.1:7897'}) → 连接成功,列出 9 个文件夹,\Sent 为 [Gmail]/已发邮件。
    • SMTP:openProxiedSocket('http://127.0.0.1:7897','smtp.gmail.com',465) 交给 nodemailer 的 getSocket + servername → transporter.verify() 返回 true,1.7 秒。

说明与后续

  • 设置页暂未加「代理」输入框:当前可用 cordis.patch.yml 的 proxy、账号卡片的 YAML 区(accountsYaml),或直接设环境变量 HTTPS_PROXY。如果作者希望设置页也可编辑,我可以在这个 PR 里补上账号卡片的字段与三态序列化。
  • POP3 收信暂未支持代理(node-pop3 客户端自行建连),文档已写明;需要的话另开一个 PR。
  • 没有改动版本号与发布流程,按仓库惯例留给维护者。

网络经代理才能连邮箱服务器时(例如 Gmail 在部分网络下直连不通),插件此前只能直连:
nodemailer 没有代理选项,插件也没有把代理传给 imapflow。

- 账号新增 `proxy`(`http` CONNECT / `https` / `socks4` / `socks4a` / `socks5` / `socks5h`,
  省略协议按 http 处理),账号级覆盖顶层简写,具名账号可各自不同。
- 未配置时按 `HTTPS_PROXY` → `HTTP_PROXY` → `ALL_PROXY` 回退,并遵守 `NO_PROXY`;
  显式配置优先于 `NO_PROXY`,因为那是用户对这个账号的直接意图。
- IMAP 交给 imapflow 自带的 `proxy` 选项;SMTP 在插件已有的 `getSocket` 钩子里
  建立 CONNECT / SOCKS 隧道,再由 nodemailer 在隧道上起 TLS,`servername` 固定为真实
  邮箱主机,证书校验不会落到代理上。
- 代理地址在配置解析阶段校验,写错会在「设置 → 邮件」报错,而不是使用时报一个
  连接超时。直连路径与之前完全一致(不传 proxy 时不新增任何选项)。
- POP3 收信暂不支持代理,文档已注明。
- 测试:test/proxy.test.mjs 覆盖地址解析、环境回退与 NO_PROXY、CONNECT 隧道、
  代理拒绝(407)与不可达报错、配置继承与校验;全套 413 项通过。

Add connection proxies for IMAP and SMTP: account-level `proxy`
(http CONNECT / https / socks4 / socks4a / socks5 / socks5h) with
HTTPS_PROXY / HTTP_PROXY / ALL_PROXY and NO_PROXY fallback. IMAP uses
imapflow's proxy option; SMTP tunnels inside the existing getSocket hook and
leaves TLS to nodemailer with servername pinned to the real mail host, so
certificates keep validating the mail server rather than the proxy. POP3 is
documented as not yet covered.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants