網上太多發郵件儲存過程,我就不轉發了,弄個簡單的作為示例;
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('[email protected]'))); 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:[email protected]'||utl_tcp.CRLF|| 'To:[email protected]'||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,'<[email protected]>'); --發件人郵箱 utl_smtp.rcpt(smtp_conn,'<[email protected]>'); --收件人郵箱 utl_smtp.open_data(smtp_conn); utl_smtp.write_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_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', --smtp服務器地址 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'
這三個主要錯誤,按照上述步驟均能解決這些問題)