Oracle 11g 环境,使用utl_smtp创建一个存储过

系统 1457 0

太多的在线电子邮件存储过程。我不转发,弄个作为一个简单的例子演示。

      create or replace procedure Send_mail(mail_body varchar2) is
  smtp_conn  utl_smtp.connection;
  user_name  varchar2(20) := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('username@email.com'))); 
  user_paswd varchar2(20) := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('password')));
  lv_mail_header varchar2(200):='From:username@email.com'||utl_tcp.CRLF||
                                'To:sanoul@email.com'||utl_tcp.CRLF||
                                'Subject:Oracle数据库'||utl_tcp.CRLF;
  lv_mail_content varchar2(2000);
begin
  lv_mail_content := utl_tcp.CRLF||mail_body;  

  smtp_conn := utl_smtp.open_connection('smtp.email.com',25);
  utl_smtp.helo(smtp_conn,'smtp.email.com');
  utl_smtp.command(smtp_conn,'AUTH LOGIN');
  utl_smtp.command(smtp_conn,user_name); --邮件用户名
  utl_smtp.command(smtp_conn,user_paswd); --邮件密码
  utl_smtp.mail(smtp_conn,'<username@email.com>'); --发件人邮箱
  utl_smtp.rcpt(smtp_conn,'<sanoul@email.com>'); --收件人邮箱

  utl_smtp.open_data(smtp_conn);

  utl_smtp.write_raw_data(smtp_conn,utl_raw.cast_to_raw(lv_mail_header));
  utl_smtp.write_raw_data(smtp_conn,utl_raw.cast_to_raw(lv_mail_content));
  --顺便说一句utl_raw.cast_to_raw最大长度是16383,假设你的邮件正文超大,请循环插入正文write_raw_data
  --否则肯定会得到 ORA-06502: PL/SQL: 数字或值错误

  utl_smtp.close_data(smtp_conn);
  utl_smtp.quit(smtp_conn);
exception
  when others then
    utl_smtp.quit(smtp_conn);
end Send_mail;
/

--储存过程已创建
    

第二步直接測试函数;

      begin
  send_mail('測试内容');
end;
/

ORA-29278: SMTP 暂时性错误: 421 Service not available
ORA-06512: 在 "SYS.UTL_SMTP", line 21
ORA-06512: 在 "SYS.UTL_SMTP", line 97
ORA-06512: 在 "SYS.UTL_SMTP", line 139
ORA-06512: 在 "SYS.UTL_MAIL", line 405
ORA-06512: 在 "SYS.UTL_MAIL", line 594
ORA-06512: 在 line 2
    

话说我第一次看到这个错误很震惊,由于整个邮件发送的存储过程是先用PL/SQL直接測试代码后,再封装到存储过程中的。后来经过搜索才知道为了更仔细地控制网络权限,Oracle 11g中针对UTL_TCP。 UTL_SMTP, UTL_MAIL, UTL_HTTP和 UTL_INADDR的訪问设置了单独的权限訪问控制方式(ACL).

OK,第三步。设置ACL;

      --ACL第一步。创建
BEGIN  
        dbms_network_acl_admin.create_acl(acl         => 'httprequestpermission.xml',  --文件名称,能够随意取名
                                          DESCRIPTION => 'Normal Access',  
                                          principal   => 'CONNECT',  --角色
                                          is_grant    => TRUE,  
                                          PRIVILEGE   => 'connect',  
                                          start_date  => NULL,  
                                          end_date    => NULL);  
END;  
/

commit; --必需要提交;

    

然后检查是否创建了该 ACL控制文件;

      SQL> SELECT any_path FROM resource_view WHERE any_path like '/sys/acls/%.xml';
    

假设列表里出现刚才创建的文件 httprequestpermission.xml ,请继续ACL第二步

      --ACL第二步,授权用户(演示样例用scott作为測试)
begin  
        dbms_network_acl_admin.add_privilege(acl        => 'httprequestpermission.xml',  
                                             principal  => 'SCOTT',  --用户。请依照实际变更
                                             is_grant   => TRUE,  
                                             privilege  => 'connect',  
                                             start_date => null,  
                                             end_date   => null);  
end;  
/

    

      --ACL第三步。加入主机或域名
    begin  
        dbms_network_acl_admin.assign_acl(acl        => 'httprequestpermission.xml',  
                                          host       => 'www.baidu.com',  --http网页地址
                                          lower_port => 80,  --http端口
                                          upper_port => NULL);  
    end;  
/

commit;

    begin  
        dbms_network_acl_admin.assign_acl(acl        => 'httprequestpermission.xml',  
                                          host       => 'smtp.sina.com.cn',  --smtpserver地址
                                          lower_port => 25,  --smtp端口
                                          upper_port => NULL);  
    end;  
/
commit;
    

最后就是再次測试存储过程

      SQL> begin
  2    send_mail(mail_body => 'afafagaga');
  3  end;
  4  /
 
PL/SQL procedure successfully completed
    

没有不论什么错误,邮件正确收到;(本文測试环境:Oracle 11.2.0.0。OS:Windows 2008 Server)

(作者測试过程中曾遇到过

ORA-24247: 网络訪问被訪问控制列表 (ACL) 拒绝;

ORA-29278: SMTP 暂时性错误: 421 Service not available。

ORA-44416: ACL 无效: 无法解析的主用户 'AGENT'

三大错误,为了解决根据上述方法,这些问题可以)

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Oracle 11g 环境,使用utl_smtp创建一个存储过程来发送邮件


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论