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

1、调用SENDMAIL_PKG来发送邮件

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

2、邮件发送结果

3、原代码

    1. --specification section
    2. CREATE OR REPLACE PACKAGE "SENDMAIL_PKG"
    3. IS
    4. PROCEDURE sendmail (p_receiver       VARCHAR2,
    5. p_sub            VARCHAR2,
    6. p_txt            VARCHAR2,
    7. err_num      OUT NUMBER,
    8. err_msg      OUT VARCHAR2);
    9. END;
    10. /
    11. --body section
    12. CREATE OR REPLACE PACKAGE BODY "SENDMAIL_PKG"
    13. IS
    14. PROCEDURE sendmail (p_receiver       VARCHAR2,
    15. p_sub            VARCHAR2,
    16. p_txt            VARCHAR2,
    17. err_num      OUT NUMBER,
    18. err_msg      OUT VARCHAR2)
    19. IS
    20. /*   p_receiver   =>  receiver
    21. p_sub              =>  mail subject
    22. p_txt                => mail content
    23. */
    24. p_user                         VARCHAR2 (30) := NULL;
    25. p_pass                         VARCHAR2 (30) := NULL;
    26. p_sendor                       VARCHAR2 (40) := 'DBA@gotrade.com';
    27. p_server                       VARCHAR2 (20)
    28. --             := system_pkg.get_sys_para_value ('TC_SMTP_IP'); --'192.168.7.65';
    29. :='192.168.7.65';
    30. p_port                         NUMBER := 25;
    31. p_need_smtp                    NUMBER := 0;
    32. p_subject                      VARCHAR2 (4000);
    33. l_crlf                         VARCHAR2 (2) := UTL_TCP.crlf;
    34. l_sendoraddress                VARCHAR2 (4000);
    35. l_splite                       VARCHAR2 (10) := '++';
    36. boundary              CONSTANT VARCHAR2 (256) := '-----BYSUK';
    37. first_boundary        CONSTANT VARCHAR2 (256) := '--' || boundary || l_crlf;
    38. last_boundary         CONSTANT VARCHAR2 (256)
    39. := '--' || boundary || '--' || l_crlf ;
    40. multipart_mime_type   CONSTANT VARCHAR2 (256)
    41. := 'multipart/mixed; boundary="' || boundary || '"' ;
    42. TYPE address_list IS TABLE OF VARCHAR2 (100)
    43. INDEX BY BINARY_INTEGER;
    44. my_address_list                address_list;
    45. ---------------------------------------split mail address----------------------------------------------
    46. PROCEDURE p_splite_str (p_str VARCHAR2, p_splite_flag INT DEFAULT 1)
    47. IS
    48. l_addr   VARCHAR2 (254) := '';
    49. l_len    INT;
    50. l_str    VARCHAR2 (4000);
    51. j        INT := 0;
    52. BEGIN
    53. /*Handle recieve mail address, such like blank, semicolon*/
    54. l_str :=
    55. TRIM (RTRIM (REPLACE (REPLACE (p_str, ';', ','), ' ', ''), ','));
    56. l_len := LENGTH (l_str);
    57. FOR i IN 1 .. l_len
    58. LOOP
    59. IF SUBSTR (l_str, i, 1) <> ','
    60. THEN
    61. l_addr := l_addr || SUBSTR (l_str, i, 1);
    62. ELSE
    63. j := j + 1;
    64. IF p_splite_flag = 1
    65. THEN
    66. --Add  symbol  '<>'  for each mail address. else could not send to many reciever
    67. l_addr := '<' || l_addr || '>';
    68. my_address_list (j) := l_addr;
    69. END IF;
    70. l_addr := '';
    71. END IF;
    72. IF i = l_len
    73. THEN
    74. j := j + 1;
    75. IF p_splite_flag = 1
    76. THEN
    77. l_addr := '<' || l_addr || '>';
    78. my_address_list (j) := l_addr;
    79. END IF;
    80. END IF;
    81. END LOOP;
    82. END;
    83. -----------------------------------write mail header and mail content----------------------------------
    84. PROCEDURE write_data (p_conn     IN OUT NOCOPY UTL_SMTP.connection,
    85. p_name     IN            VARCHAR2,
    86. p_value    IN            VARCHAR2,
    87. p_splite                 VARCHAR2 DEFAULT ':',
    88. p_crlf                   VARCHAR2 DEFAULT l_crlf)
    89. IS
    90. BEGIN
    91. /* utl_raw.cast_to_raw  to handle chinese code*/
    92. UTL_SMTP.write_raw_data (
    93. p_conn,
    94. UTL_RAW.cast_to_raw (
    95. CONVERT (p_name || p_splite || p_value || p_crlf,
    96. 'ZHS16CGB231280')));
    97. END;
    98. ----------------------------------------write mime mail tail-----------------------------------------------------
    99. PROCEDURE end_boundary (conn   IN OUT NOCOPY UTL_SMTP.connection,
    100. LAST   IN            BOOLEAN DEFAULT FALSE)
    101. IS
    102. BEGIN
    103. UTL_SMTP.write_data (conn, UTL_TCP.crlf);
    104. IF (LAST)
    105. THEN
    106. UTL_SMTP.write_data (conn, last_boundary);
    107. END IF;
    108. END;
    109. ---------------------------------------------send mail procedure--------------------------------------------
    110. PROCEDURE p_email (p_sendoraddress2      VARCHAR2,      --sender address
    111. p_receiveraddress2    VARCHAR2)    --reciever address
    112. IS
    113. l_conn   UTL_SMTP.connection;                   --create a connection
    114. BEGIN
    115. /*Initial mail server*/
    116. l_conn := UTL_SMTP.open_connection (p_server, p_port);
    117. UTL_SMTP.helo (l_conn, p_server);
    118. /* smtp authentication*/
    119. IF p_need_smtp = 1
    120. THEN
    121. UTL_SMTP.command (l_conn, 'AUTH LOGIN', '');
    122. UTL_SMTP.command (
    123. l_conn,
    124. UTL_RAW.cast_to_varchar2 (
    125. UTL_ENCODE.base64_encode (UTL_RAW.cast_to_raw (p_user))));
    126. UTL_SMTP.command (
    127. l_conn,
    128. UTL_RAW.cast_to_varchar2 (
    129. UTL_ENCODE.base64_encode (UTL_RAW.cast_to_raw (p_pass))));
    130. END IF;
    131. /*configure sender and reciever mail address*/
    132. UTL_SMTP.mail (l_conn, p_sendoraddress2);
    133. UTL_SMTP.rcpt (l_conn, p_receiveraddress2);
    134. /*configure mail header*/
    135. UTL_SMTP.open_data (l_conn);
    136. /*configure date*/
    137. --write_data(l_conn, 'Date', to_char(sysdate-1/3, 'dd Mon yy hh24:mi:ss'));
    138. /*configure sender*/
    139. write_data (l_conn, 'From', p_sendor);
    140. /*configure reciever*/
    141. write_data (l_conn, 'To', p_receiver);
    142. /*add mail subject*/
    143. SELECT REPLACE (
    144. '=?GB2312?B?'
    145. || UTL_RAW.cast_to_varchar2 (
    146. UTL_ENCODE.base64_encode (RAWTOHEX (p_sub)))
    147. || '?=',
    148. UTL_TCP.crlf,
    149. '')
    150. INTO p_subject
    151. FROM DUAL;
    152. write_data (l_conn, 'Subject', p_subject);
    153. write_data (l_conn, 'Content-Type', multipart_mime_type);
    154. UTL_SMTP.write_data (l_conn, UTL_TCP.crlf);
    155. UTL_SMTP.write_data (l_conn, first_boundary);
    156. write_data (l_conn, 'Content-Type', 'text/html');
    157. UTL_SMTP.write_data (l_conn, UTL_TCP.crlf);
    158. write_data (
    159. l_conn,
    160. '',
    161. REPLACE (REPLACE (p_txt, l_splite, CHR (10)), CHR (10), l_crlf),
    162. '',
    163. '');
    164. end_boundary (l_conn);
    165. /*close write data*/
    166. UTL_SMTP.close_data (l_conn);
    167. /*close connection*/
    168. UTL_SMTP.quit (l_conn);
    169. END;
    170. ---------------------------------------------main procedure -----------------------------------------------------
    171. BEGIN
    172. err_num := 0;
    173. l_sendoraddress := '<' || p_sendor || '>';
    174. p_splite_str (p_receiver);                         --handle mail address
    175. FOR k IN 1 .. my_address_list.COUNT
    176. LOOP
    177. p_email (l_sendoraddress, my_address_list (k));
    178. END LOOP;
    179. END;
    180. END;
    181. /
    182. 转:http://blog.csdn.net/leshami/article/details/18616901

PL/SQL 下邮件发送程序的更多相关文章

  1. C# SMTP邮件发送程序

    邮件发送在网站应用程序中经常会用到,包括您现在看到的博客,在添加评论后,系统会自动发送邮件通知到我邮箱的,把系统发送邮件的功能整理了下,做了一个客户端Demo,希望对有需要的童鞋有所帮助: 核心代码: ...

  2. mailto - 简单多媒体邮件发送程序

    SYNOPSIS mailto  [-a] [-c] [-s] [recipient name(s)] DESCRIPTION mailto 程序是一个用于发送MIME格式的多媒体邮件(MIME格式是 ...

  3. python3实现邮件发送程序

    刚开始的想法很简单,由于有上千封的邮件需要发出去,并且需要一条一条发送,不能转发或群发,每条邮件要署对方的姓名,并加上几个相同的符件,考虑到手工操作繁琐无趣,所以想到用程序实现,python好像非常胜 ...

  4. linux(debian)下邮件发送

    关键字: exim4  mutt  smtp 主要的事情就是配置exim4,按照网上的流程来.在这里总结一下: 需要修改的文件有三个:/etc/exim4/update-exim4.conf.conf ...

  5. pl/sql学习(6): 引号/程序调试/列中的字符串合并/正则表达式

    有关自治事务的问题: https://www.cnblogs.com/princessd8251/p/4132649.html 我在plsql development学习中遇到的常见问题: (一) 引 ...

  6. PL/SQL 下 Command window 与 SQL window 的区别

    1.Command window实现了SQL*Plus的所有功能,允许运行sql*plus命令,sql命令,sql脚本. 2.SQL window用于执行sql语句,显示sql输出,执行统计信息.(测 ...

  7. Oracle+PL+SQL从入门到精通.丁士锋.清华大学出版社.2012

    \t第1篇 pl/sql开发入门第1章 oracle 11g数据库系统1.1 关系型数据库系统介绍1.1.1 什么是关系型数据模型1.1.2 数据库系统范式1.1.3 关系型数据库管理系统1.1.4 ...

  8. Chilkat----开源站点之VS2010 CKMailMan一个很好的邮件发送开源开发包

    Chilkat 是一个很好的开源站点,有各种开源库. 开发语言主要有Classic ASP •C • C++ • C# • Delphi ActiveX • Delphi DLL • Visual F ...

  9. Oracle学习笔记之五sp1,PL/SQL之BULK COLLECT

    Bulk Collect特性可以让我们在PL/SQL中能使用批查询,批查询在某些情况下能显著提高查询效率. BULK COLLECT 子句会批量检索结果,即一次性将结果集绑定到一个集合变量中,并从SQ ...

随机推荐

  1. 2013 ACM/ICPC Asia Regional Changsha Online G Goldbach

    比赛的时候,被题目误导了,题目最后说结果可能很大,要取模,那时就想直接求会TLE的!!! 赛后才知道,坑啊………… 代码如下: #include<iostream> #include< ...

  2. m_pMainWnd(转载)

    今天写程序时遇到个简单而又很有意思的问题,封装了一个网络接口类,发送数据以及网络的回调接口都在这个类里面,打算在回调函数里给AfxGetMainWnd()发送消息以更新主界面的数据,同时程序有一个登录 ...

  3. Good Bye 2015 A. New Year and Days 签到

    A. New Year and Days   Today is Wednesday, the third day of the week. What's more interesting is tha ...

  4. 关于yum仓库的中的软件包下载

    在Linux系统下,很多软件的安装我们都会选择使用yum的方式安装,因为简单方便,易于管理. 有时我们可能会有这样的一个需求:即喜欢上yum仓库中的一个软件了,想要下载到本地.该怎么办呢? 实现方法不 ...

  5. 负载均衡之Haproxy配置详解(及httpd配置)

    下图描述了使用keepalived+Haproxy主从配置来达到能够针对前段流量进行负载均衡到多台后端web1.web2.web3.img1.img2.但是由于haproxy会存在单点故障问题,因此使 ...

  6. Android笔记——Drawerlayout创建侧滑出菜单

    1.首先务必导入support-v4包 2.布局文件主标签为<android.support.v4.widget.DrawerLayout>,并为其设置id         其子标签必须包 ...

  7. JavaWeb笔记——JSTL标签

    JSTL 1. jstl的概述   * apache的东西,依赖EL   * 使用jstl需要导入jstl.jar.standard.jar   * 四大库:     > core:核心库,重点 ...

  8. 浅析c语言中的变量(局部变量,外部变量,静态变量,寄存器变量)[转]

    c语言中变量分为四类,分别是 1.auto   自动变量 2.static   静态存贮分配变量(又分为内部静态和外部静态) 3.extern  全程变量(用于外部变量说明) 4.register   ...

  9. Activity Recognition行为识别

    暑假听了computer vision的一个Summer School,里面Jason J. Corso讲了他们运用Low-Mid-High层次结构进行Video Understanding 和 Ac ...

  10. URAL 1200 Horns and Hoofs 枚举

    设horns和hoofs的数量分别为 x 和 y ,题目要求: 满足 x+y <= K,使得A*x + B*y - x*x - y*y 最大. 枚举 i 从0~K,直接解方程得对称轴 x = ( ...