Nginx代理邮件协议本质是四层代理,需启用mail模块并配置在独立mail{...}块中,不解析应用层,依赖auth_http认证脚本实现协议级干预。

Nginx 代理邮件协议(SMTP/POP3/IMAP)本质上是四层代理行为,不解析应用层内容,只依据 TCP 连接的目标端口和协议类型做透传转发。它不替代邮件服务器,而是作为前置网关,承担连接分发、认证中继与基础安全控制。关键前提是编译时启用 --with-mail 模块,且配置必须放在独立的 mail{...} 块中,不能混入 http{...} 或 stream{...}。
确认 Nginx 支持 mail 模块
运行以下命令验证:
-
nginx -V 2>&1 | grep -o with-mail—— 输出含with-mail表示已编译支持 - 若无输出,需重新编译并加入
--with-mail --with-mail_ssl_module - 注意:
mail模块与stream模块互斥使用场景不同:前者专用于标准邮件协议(带内置 auth_http 支持),后者通用 TCP/UDP 转发但无原生邮件认证机制
基础 mail 块配置结构
核心是定义监听端口、指定认证接口、声明后端能力。典型最小配置如下:
mail {-
auth_http 127.0.0.1/auth.php;—— 认证脚本地址,必须返回标准 HTTP 头(如Auth-Status: OK) -
pop3_capabilities "TOP" "USER";—— 告知客户端支持的 POP3 扩展指令 -
imap_capabilities "IMAP4rev1" "UIDPLUS";—— 同理声明 IMAP 能力 -
server { listen 110; protocol pop3; proxy on; } -
server { listen 143; protocol imap; proxy on; } -
server { listen 25; protocol smtp; proxy on; smtp_auth login plain; } }
每条 server 块绑定一个端口和协议,proxy on 表示启用代理模式;smtp_auth 指定允许的认证方式,避免客户端协商失败。
认证脚本的关键逻辑
PHP 认证脚本不是可选组件,而是强制环节。Nginx 在建立连接后,会以 HTTP GET 方式向该脚本发起请求,并附带以下头信息:
-
HTTP_AUTH_USER:客户端提供的用户名 -
HTTP_AUTH_PASS:明文或 Base64 编码密码(取决于客户端) -
HTTP_AUTH_PROTOCOL:值为pop3、imap或smtp - 脚本必须响应严格格式的 HTTP 头:
Auth-Status、Auth-Server、Auth-Port - 错误响应用
Auth-Status: Invalid login or password,成功则返回后端真实邮件服务器 IP 和端口
与 stream 模块的区别与取舍
有人误用 stream{...} 代理邮件端口,这是不可取的:
-
stream不识别邮件协议,无法触发auth_http流程,也无法处理 AUTH 命令协商 -
stream适合纯 TCP 转发(如 MySQL、Redis),但对 SMTP/POP3/IMAP 缺乏协议感知,易导致认证失败或连接中断 - 若只需简单端口映射且后端自带完整认证(如 Postfix + Dovecot 自主鉴权),可用
stream;但若需 Nginx 统一做账号校验、黑白名单或限速,则必须用mail{...}
实际部署中,mail 模块更贴近邮件服务语义,stream 更偏向基础设施层透明转发。选型应由是否需要协议级干预决定。


















