设为首页 收藏本站
查看: 747|回复: 0

[经验分享] PL/SQL 下邮件发送程序

[复制链接]

尚未签到

发表于 2016-11-12 07:28:24 | 显示全部楼层 |阅读模式
   对DBA而言,尽管在os级别下发送邮件是轻而易举的事情,然而很多时候我们也需要在PL/SQL中来发送邮件,比如监控job的执行状况等。本文根据网友(源作者未考证)的代码将其改装并封装到了package,感谢这位网友的无私奉献。文章首先给出演示调用该包发送邮件的情形后面给出了完整的代码。经测试Oracle 10g,Oracle 11g下均可用。关于os下发送邮件可参考:不可或缺的 sendEmail
  
  1、调用SENDMAIL_PKG来发送邮件


gx_admin@SYBO2SZ> set serveroutput on;
gx_admin@SYBO2SZ> DECLARE
2    P_RECEIVER VARCHAR2(32767);
3    P_SUB VARCHAR2(32767);
4    P_TXT VARCHAR2(32767);
5    ERR_NUM NUMBER;
6    ERR_MSG VARCHAR2(32767);
7  
8  BEGIN
9    P_RECEIVER := 'robinson.chen@12306.com';
10    P_SUB := 'Test mail';
11    P_TXT := 'This is a test mail.';
12    ERR_NUM := NULL;
13    ERR_MSG := NULL;
14  
15    SENDMAIL_PKG.SENDMAIL ( P_RECEIVER, P_SUB, P_TXT, ERR_NUM, ERR_MSG );
16  
17    DBMS_OUTPUT.Put_Line('ERR_NUM = ' || TO_CHAR(ERR_NUM));
18    DBMS_OUTPUT.Put_Line('ERR_MSG = ' || ERR_MSG);
19  
20    DBMS_OUTPUT.Put_Line('');
21  
22    COMMIT;
23  END;
24  /
ERR_NUM = 0
ERR_MSG =
PL/SQL procedure successfully completed.

  
2、邮件发送结果
   DSC0000.jpg
  3、原代码


--specification section
CREATE OR REPLACE PACKAGE "SENDMAIL_PKG"
IS
PROCEDURE sendmail (p_receiver       VARCHAR2,
p_sub            VARCHAR2,
p_txt            VARCHAR2,
err_num      OUT NUMBER,
err_msg      OUT VARCHAR2);
END;
/
--body section
CREATE OR REPLACE PACKAGE BODY "SENDMAIL_PKG"
IS
PROCEDURE sendmail (p_receiver       VARCHAR2,
p_sub            VARCHAR2,
p_txt            VARCHAR2,
err_num      OUT NUMBER,
err_msg      OUT VARCHAR2)
IS
/*   p_receiver   =>  receiver
p_sub              =>  mail subject
p_txt                => mail content
*/
p_user                         VARCHAR2 (30) := NULL;
p_pass                         VARCHAR2 (30) := NULL;
p_sendor                       VARCHAR2 (40) := 'DBA@gotrade.com';
p_server                       VARCHAR2 (20)
--             := system_pkg.get_sys_para_value ('TC_SMTP_IP'); --'192.168.7.65';
:='192.168.7.65';
p_port                         NUMBER := 25;
p_need_smtp                    NUMBER := 0;
p_subject                      VARCHAR2 (4000);
l_crlf                         VARCHAR2 (2) := UTL_TCP.crlf;
l_sendoraddress                VARCHAR2 (4000);
l_splite                       VARCHAR2 (10) := '++';
boundary              CONSTANT VARCHAR2 (256) := '-----BYSUK';
first_boundary        CONSTANT VARCHAR2 (256) := '--' || boundary || l_crlf;
last_boundary         CONSTANT VARCHAR2 (256)
:= '--' || boundary || '--' || l_crlf ;
multipart_mime_type   CONSTANT VARCHAR2 (256)
:= 'multipart/mixed; boundary="' || boundary || '"' ;
TYPE address_list IS TABLE OF VARCHAR2 (100)
INDEX BY BINARY_INTEGER;
my_address_list                address_list;
---------------------------------------split mail address----------------------------------------------
PROCEDURE p_splite_str (p_str VARCHAR2, p_splite_flag INT DEFAULT 1)
IS
l_addr   VARCHAR2 (254) := '';
l_len    INT;
l_str    VARCHAR2 (4000);
j        INT := 0;
BEGIN
/*Handle recieve mail address, such like blank, semicolon*/
l_str :=
TRIM (RTRIM (REPLACE (REPLACE (p_str, ';', ','), ' ', ''), ','));
l_len := LENGTH (l_str);
FOR i IN 1 .. l_len
LOOP
IF SUBSTR (l_str, i, 1) <> ','
THEN
l_addr := l_addr || SUBSTR (l_str, i, 1);
ELSE
j := j + 1;
IF p_splite_flag = 1
THEN
--Add  symbol  '<>'  for each mail address. else could not send to many reciever
l_addr := '<' || l_addr || '>';
my_address_list (j) := l_addr;
END IF;
l_addr := '';
END IF;
IF i = l_len
THEN
j := j + 1;
IF p_splite_flag = 1
THEN
l_addr := '<' || l_addr || '>';
my_address_list (j) := l_addr;
END IF;
END IF;
END LOOP;
END;
-----------------------------------write mail header and mail content----------------------------------
PROCEDURE write_data (p_conn     IN OUT NOCOPY UTL_SMTP.connection,
p_name     IN            VARCHAR2,
p_value    IN            VARCHAR2,
p_splite                 VARCHAR2 DEFAULT ':',
p_crlf                   VARCHAR2 DEFAULT l_crlf)
IS
BEGIN
/* utl_raw.cast_to_raw  to handle chinese code*/
UTL_SMTP.write_raw_data (
p_conn,
UTL_RAW.cast_to_raw (
CONVERT (p_name || p_splite || p_value || p_crlf,
'ZHS16CGB231280')));
END;
----------------------------------------write mime mail tail-----------------------------------------------------
PROCEDURE end_boundary (conn   IN OUT NOCOPY UTL_SMTP.connection,
LAST   IN            BOOLEAN DEFAULT FALSE)
IS
BEGIN
UTL_SMTP.write_data (conn, UTL_TCP.crlf);
IF (LAST)
THEN
UTL_SMTP.write_data (conn, last_boundary);
END IF;
END;
---------------------------------------------send mail procedure--------------------------------------------
PROCEDURE p_email (p_sendoraddress2      VARCHAR2,      --sender address
p_receiveraddress2    VARCHAR2)    --reciever address
IS
l_conn   UTL_SMTP.connection;                   --create a connection
BEGIN
/*Initial mail server*/
l_conn := UTL_SMTP.open_connection (p_server, p_port);
UTL_SMTP.helo (l_conn, p_server);
/* smtp authentication*/
IF p_need_smtp = 1
THEN
UTL_SMTP.command (l_conn, 'AUTH LOGIN', '');
UTL_SMTP.command (
l_conn,
UTL_RAW.cast_to_varchar2 (
UTL_ENCODE.base64_encode (UTL_RAW.cast_to_raw (p_user))));
UTL_SMTP.command (
l_conn,
UTL_RAW.cast_to_varchar2 (
UTL_ENCODE.base64_encode (UTL_RAW.cast_to_raw (p_pass))));
END IF;
/*configure sender and reciever mail address*/
UTL_SMTP.mail (l_conn, p_sendoraddress2);
UTL_SMTP.rcpt (l_conn, p_receiveraddress2);
/*configure mail header*/
UTL_SMTP.open_data (l_conn);
/*configure date*/
--write_data(l_conn, 'Date', to_char(sysdate-1/3, 'dd Mon yy hh24:mi:ss'));
/*configure sender*/
write_data (l_conn, 'From', p_sendor);
/*configure reciever*/
write_data (l_conn, 'To', p_receiver);
/*add mail subject*/
SELECT REPLACE (
'=?GB2312?B?'
|| UTL_RAW.cast_to_varchar2 (
UTL_ENCODE.base64_encode (RAWTOHEX (p_sub)))
|| '?=',
UTL_TCP.crlf,
'')
INTO p_subject
FROM DUAL;
write_data (l_conn, 'Subject', p_subject);
write_data (l_conn, 'Content-Type', multipart_mime_type);
UTL_SMTP.write_data (l_conn, UTL_TCP.crlf);
UTL_SMTP.write_data (l_conn, first_boundary);
write_data (l_conn, 'Content-Type', 'text/html');
UTL_SMTP.write_data (l_conn, UTL_TCP.crlf);
write_data (
l_conn,
'',
REPLACE (REPLACE (p_txt, l_splite, CHR (10)), CHR (10), l_crlf),
'',
'');
end_boundary (l_conn);
/*close write data*/
UTL_SMTP.close_data (l_conn);
/*close connection*/
UTL_SMTP.quit (l_conn);
END;
---------------------------------------------main procedure -----------------------------------------------------
BEGIN
err_num := 0;
l_sendoraddress := '<' || p_sendor || '>';
p_splite_str (p_receiver);                         --handle mail address
FOR k IN 1 .. my_address_list.COUNT
LOOP
p_email (l_sendoraddress, my_address_list (k));
END LOOP;
END;
END;
/

DSC0001.png

  更多参考
  使用 DBMS_PROFILER 定位 PL/SQL 瓶颈代码
  使用PL/SQL Developer剖析PL/SQL代码
  对比 PL/SQL profiler 剖析结果
  PL/SQL Profiler 剖析报告生成html
  DMLError Logging 特性
  PL/SQL --> 游标
  PL/SQL --> 隐式游标(SQL%FOUND)
  批量SQL之 FORALL 语句
  批量SQL之 BULK COLLECT 子句
  PL/SQL 集合的初始化与赋值

  PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录
  SQL tuning 步骤
  高效SQL语句必杀技

  父游标、子游标及共享游标
  绑定变量及其优缺点
  dbms_xplan之display_cursor函数的使用
  dbms_xplan之display函数的使用
  执行计划中各字段各模块描述
  使用 EXPLAIN PLAN 获取SQL语句执行计划

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-299064-1-1.html 上篇帖子: 数据采集中常用的SQL语句 下篇帖子: 使用Apache Phoenix 实现 SQL 操作HBase
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表