ORA-29260 根本原因是数据库服务器无外网出向连接或防火墙拦截SMTP端口;需用telnet/openssl验证连通性,确认出向策略、SELinux及代理设置,并正确配置TLS端口与加密握手。
ORA-29260 网络错误:UTL_SMTP 连不上邮件服务器
根本原因不是密码错,而是 oracle 数据库服务器本身没开通外网出向连接,或者防火墙拦了 smtp 端口(通常是 25、465 或 587)。dba 往往只配了监听和内网访问,忘了 smtp 是“往外打”的。
实操建议:
- 先在数据库服务器上用系统命令验证连通性:
telnet smtp.example.com 587(或openssl s_client -connect smtp.example.com:465 -crlf) - 如果超时或拒绝连接,找运维确认:出向策略、SELinux 是否限制
oracle用户发起网络连接、是否需走代理 -
UTL_SMTP.OPEN_CONNECTION的第 2 个参数是端口,别硬写死25—— 现代邮箱(如腾讯企业邮、Outlook、Gmail)基本都要求 TLS/SSL,得用465或587,且后续必须调用UTL_SMTP.START_TLS或用UTL_SMTP.OPEN_CONNECTION(..., UTL_TCP.CRLF)配合加密握手
认证失败:ORA-29278 SMTP 无法登录
错误信息里带 535 5.7.8 Authentication failed,大概率是账号密码不对,但更常被忽略的是:Oracle 默认不支持现代邮箱的「应用专用密码」或「OAuth2」,只能用传统 SMTP 密码,且该密码可能被邮箱后台禁用(比如 QQ 邮箱默认关闭 SMTP 服务)。
实操建议:
- 登录邮箱网页后台,手动开启 SMTP 服务,并生成/重置「SMTP 密码」(不是你的登录密码)
- 在
UTL_SMTP.AUTH调用中,用户名必须是完整邮箱地址(如'user@example.com'),不能只写'user' - 部分邮件服务器(如阿里云企业邮)要求用户名带域名后缀,且大小写敏感;密码若含特殊字符(如
+、/),需确认是否被 PL/SQL 字符串解析截断 —— 建议先赋值给VARCHAR2变量再传入
中文乱码与附件缺失:MIME 头没写对
收件人看到主题是 =?UTF-8?B?5byg5LiJ?= 或正文一堆问号,说明 MIME 头缺失或格式错误;附件显示为乱码名或根本没出现,是因为 Content-Disposition 没声明 filename*=UTF-8''xxx。
实操建议:
- 主题和收件人姓名必须用
MIME_HEADER_ENCODE编码(Oracle 12c+ 自带),不要手拼=?UTF-8?B?...;若版本低,用UTL_ENCODE.BASE64_ENCODE+ 手动加头 - 发 HTML 邮时,
Content-Type必须设为text/html; charset=UTF-8,且第一行空行前要写全头,否则 Outlook 直接当纯文本 - 附件名含中文,必须用
filename*=UTF-8''xxx格式(注意两个单引号),不能只写filename="xxx"—— 后者在大多数客户端里会丢名或乱码
UTL_SMTP 发信卡住或超时:缺少超时控制与异常兜底
最隐蔽的问题:没设 UTL_TCP.OPEN_CONNECTION 的 tx_timeout 参数,导致 DNS 解析失败或服务器无响应时,整个 PL/SQL 过程挂起 60 秒以上,还占着连接不释放。
实操建议:
- 所有
UTL_TCP.OPEN_CONNECTION调用必须显式指定tx_timeout => 10(单位秒),避免阻塞 - 每个
UTL_SMTP步骤后检查返回码(如UTL_SMTP.HELO返回250),非 2xx 码立刻UTL_SMTP.QUIT并抛异常 - 务必在
EXCEPTION块里加UTL_SMTP.CLOSE_CONNECTION,否则连接泄漏,跑几次就触发ORA-29261: bad argument
真正难的不是写几行 UTL_SMTP.SEND_MAIL,而是让这套逻辑在生产环境里不掉链子——网络抖动、邮箱策略变更、字符集混用、连接没关干净,任何一个点漏掉,都会变成半夜告警。










