Oracle 12c+中DBMS_MAIL已彻底删除,必须改用UTL_MAIL或UTL_SMTP;启用UTL_MAIL需三步:手动安装utlmail.sql与prvtmail.plb脚本、显式设置带端口的smtp_out_server参数、确保DB服务器直连SMTP端口且配置ACL权限。
Oracle 12c 及更高版本中 DBMS_MAIL 已被彻底删除,调用必报 ORA-00904: "dbms_mail": invalid identifier ——这不是权限或安装问题,是包本身不存在了。必须改用 UTL_MAIL 或 UTL_SMTP。
看起来一行 UTL_MAIL.SEND 就能发信,但 80% 的失败卡在这三步没走完:
@?/rdbms/admin/utlmail.sql 和 @?/rdbms/admin/prvtmail.plb(路径中 ? 展开为 $ORACLE_HOME)smtp_out_server 参数必须设且带端口:ALTER SYSTEM SET smtp_out_server = 'smtp.example.com:587' SCOPE=BOTH; ——不能写 http://,也不能漏端口587 或 465 端口(不是应用服务器能连就行)验证是否生效:SELECT value FROM v$parameter WHERE name = 'smtp_out_server'; 返回非空字符串才算通过。
主题或正文变问号?不是字符集没配对,就是超长触发误导性错误:
mime_type => 'text/plain; charset=utf-8'(HTML 邮件同理),否则默认用数据库字符集(如 WE8ISO8859P1),中文直接报废subject 和 message 参数上限为 32767 字节 —— 超长会抛 ORA-29260: network error: TNS:connection refused,实际和网络无关,纯长度校验失败'[email protected],[email protected]',不能传数组、集合或换行符最小可用示例:
BEGINUTL_MAIL.SEND(sender => '[email protected]',recipients => '[email protected]',subject=> '测试',message=> '这是一封测试邮件',mime_type=> 'text/plain; charset=utf-8');END;
当邮件服务器强制要求 STARTTLS(如 Gmail、Outlook、多数企业 SMTP),UTL_SMTP.OPEN_CONNECTION 后直接发 MAIL 会挂起或报 ORA-29279:
EHLO(不是 HELO),再发 STARTTLS 命令STARTTLS 后,需重新协商 TLS 层 —— Oracle 不自动处理,得手动调用 UTL_SMTP.STARTTLS(12.2+)或用 UTL_TCP 手动包装 SSL 握手(旧版本)UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(v_user)),漏掉任意一环都会 535 错误UTL_TCP.CRLF || UTL_TCP.CRLF),少或多都会被拒中文支持依赖字符集转换:UTL_RAW.cast_to_raw(CONVERT(v_msg, 'ZHS16GBK', 'AL32UTF8')),不能只靠 mime_type 声明。
即使 UTL_MAIL 或 UTL_SMTP 配置全对,没 ACL 就是白搭 —— 报错 ORA-24247: network access denied by access control list:
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl => 'email.xml', host => '*', lower_port => 25, upper_port => 587)
connect 权限:DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE('email.xml', 'MY_USER', TRUE, 'connect')
GRANT EXECUTE ON UTL_MAIL TO MY_USER(UTL_SMTP 同理)真正容易被忽略的是:ACL 主机匹配支持通配符但不支持正则;host => '*' 允许所有域名/IP,但若只配了 smtp.example.com,连 smtp.example.com:587 都会被拒绝 —— 端口必须单独放开。