使用Oracle发送邮件 - 亲测

qq 邮箱开启smtp发送邮件

https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256


在上面这个地址记住授权码


注意:qq邮箱第三方收发邮件最多180天,超过180天需重新设置

oracle 基本设置

-- 1.创建访问控制列表(ACLemail_server_permissions),
BEGIN
 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
  acl          => 'email_server_permissions.xml', 
  description  => 'Enables network permissions for the e-mail server',
  principal    => 'JAVAUSER', --此为将来要进行操作的用户, 在Oracle用户表中必须存在
  is_grant     => TRUE, 
  privilege    => 'connect');
END;
/

-- 2. 将此 ACL 与邮件服务器相关联,
BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => 'email_server_permissions.xml',
    host        => '113.96.232.106', --SMTP服务器地址, 此例为qq的smtp地址
    lower_port  => 25,
    upper_port  => 25);
  COMMIT;
END;
/

--3.创建访问控制列表(ACL)network_services,
BEGIN
 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
  acl          => 'network_services.xml', 
  description  => 'Enables network permissions for the e-mail server',
  principal    => 'JAVAUSER', --此为将来要进行操作的用户, 在oracle用户列表中必须存在
  is_grant     => TRUE, 
  privilege    => 'connect');
END;
/

--4. 将此 ACL 与邮件服务器相关联,
BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => 'network_services.xml',
    host        => '*', --SMTP服务器地址, 通配符设置匹配所有
    lower_port  => NULL,
    upper_port  => NULL);
  COMMIT;
END;
/


----查询,验证以上四步设置成功
 SELECT host, lower_port, upper_port, acl FROM dba_network_acls;
 
 
 SELECT acl,
       principal,
       privilege,
       is_grant,
       TO_CHAR(start_date, 'DD-MON-YYYY') AS start_date,
       TO_CHAR(end_date, 'DD-MON-YYYY') AS end_date
  FROM dba_network_acl_privileges;
删除ACL:(与assign相对应)

begin
-- 删除acl这个列表文件,使用它的用户也就取消了对应的权限

begin
dbms_network_acl_admin.drop_acl(
 '/sys/acls/BRDG_BMS_TO_OA.xml'
);
commit;
end;

Oracle 存储过程

create or replace procedure send_email(
  p_recipient VARCHAR2, -- 邮件接收人
  p_subject   VARCHAR2, -- 邮件标题
  p_message   VARCHAR2  -- 邮件正文
) is
 
     --下面四个变量请根据实际邮件服务器进行赋值
     v_mailhost  VARCHAR2(30) := 'smtp.qq.com';    --SMTP服务器地址
     v_user      VARCHAR2(30) := 'xxxxxx';            --登录SMTP服务器的用户名
     v_pass      VARCHAR2(20) := 'xxxxxx';             --登录SMTP服务器的密码 -- qq的授权码
     v_sender    VARCHAR2(50) := 'xxxxxx@qq.com';    --发送者邮箱,一般与 ps_user 对应
      
     v_conn  UTL_SMTP. connection ; --到邮件服务器的连接
     v_msg varchar2(4000);  --邮件内容
 
BEGIN
 
     v_conn := UTL_SMTP.open_connection(v_mailhost, 25);
     UTL_SMTP.ehlo(v_conn, v_mailhost); --是用 ehlo() 而不是 helo() 函数
     --否则会报:ORA-29279: SMTP 永久性错误: 503 5.5.2 Send hello first.
 
     UTL_SMTP.command(v_conn, 'AUTH LOGIN' );   -- smtp服务器登录校验
     UTL_SMTP.command(v_conn,UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(v_user))));
     UTL_SMTP.command(v_conn,UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(v_pass))));
 
    UTL_SMTP.MAIL(V_CONN,'<' || V_SENDER || '>');
    UTL_SMTP.RCPT(V_CONN,'<' || P_RECIPIENT || '>');

     -- 创建要发送的邮件内容 注意报头信息和邮件正文之间要空一行
     v_msg := 'Date:' || TO_CHAR(SYSDATE, 'dd mon yy hh24:mi:ss') ||  'nls_date_language = ''SIMPLIFIED CHINESE'''  --这样写标题和内容都能用中文, 且时区为中国时区(默认为美国时区)
         || UTL_TCP.CRLF || 'From: ' || '<' || v_sender || '>'
         || UTL_TCP.CRLF || 'To: ' || '<' || p_recipient || '>'
         || UTL_TCP.CRLF || 'Subject: ' || p_subject
         || UTL_TCP.CRLF || UTL_TCP.CRLF  -- 这前面是报头信息
         || p_message;    -- 这个是邮件正文
 
     UTL_SMTP.open_data(v_conn); --打开流
     UTL_SMTP.write_raw_data(v_conn, UTL_RAW.cast_to_raw(v_msg));
     UTL_SMTP.close_data(v_conn); --关闭流
     UTL_SMTP.quit(v_conn); --关闭连接
      
EXCEPTION
 
     WHEN OTHERS THEN
         DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);
         DBMS_OUTPUT.put_line(DBMS_UTILITY.format_call_stack);
  
end send_email;

Oracle 存储过程调用示例

call send_emal('xxxxxx@qq.com', 'test email', 'test send email through oracle procedures')

过程中遇到问题及解决

  1. ORA-24247: 网络访问被访问控制列表 (ACL) 拒绝, 需设置oracle ACL访问权限,设置方式见第二部分
  2. ORA-44416: Invalid ACL: Unresolved principal ‘…’,用户名在oracle数据库中不存在,注意oracle的用户名都应该是大写
  3. ora-… 编码丢失,意思是需使用授权码登录,结果是smtp地址设置不正确,正确地址为:smtp.qq.com 但设置的是 smtp.exmail.qq.com, 修改地址正确后,即可发送邮件
  4. 发送邮件时区为美国时区,在邮件内容处 加上 ‘nls_date_language = ‘‘SIMPLIFIED CHINESE’’’ 即可解决
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值