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


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

    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'

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

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

  • 相关阅读:
    泛型总结
    Java多线程(学习篇)
    Java线程:总结
    Java线程:线程交互
    Java线程:线程安全类和Callable与Future(有返回值的线程)
    Java线程:条件变量、原子量、线程池等
    Java线程:堵塞队列与堵塞栈
    Java线程:锁
    poj 1679 The Unique MST(唯一的最小生成树)
    poj 1659 Frogs' Neighborhood (DFS)
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4655517.html
Copyright © 2020-2023  润新知