对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. 很不错的文章---【问底】徐汉彬:亿级Web系统搭建——单机到分布式集群

    [导读]徐汉彬曾在阿里巴巴和腾讯从事4年多的技术研发工作,负责过日请求量过亿的Web系统升级与重构,目前在小满科技创业,从事SaaS服务技术建设. 大规模流量的网站架构,从来都是慢慢“成长”而来.而这 ...

  2. 初学Ajax(三)

    $.ajax() $.ajax()是所有ajax方法中最底层的方法,所有其他方法都是基于$.ajax()方法的封装.这个方法只有一个参数,传递一个各个功能键值对的对象. $.ajax()方法对象参数表 ...

  3. 如何使用JMeter来实现更大批量的并发的解决方案(即如何设置controller和Agent)

    http://www.testwo.com/blog/6373 近期在用JMeter进行负载测试的 时候,发现使用单台机器模拟测试超过比如500个进程的并发就有些力不从心或者说不能如实的反应实际情况, ...

  4. java理论基础学习一

    java的最大优势是跨平台 java的版本和体系架构 1.J2EE   Java 2 Enterprise Edition 定位在服务器端的应用 2.J2SE   Java 2 Standard Ed ...

  5. Android核心分析之二十二Android应用框架之Activity

    3 Activity设计框架 3.1 外特性空间的Activity    我们先来看看,android应用开发人员接触的外特性空间中的Activity,对于AMS来讲,这个Activity就是客服端的 ...

  6. Centos环境下部署游戏服务器-Eclipse

    一直在想这篇文章该不该写,因为这篇文章更像是教你如何使用一个ide这种文章,毫无价值可言.但思来想去还是应给写.上篇文章主要说了编译原理和过程,这篇文章就是理论联系实际的典范.并且很多工程师一辈子都不 ...

  7. Intellij Idea 15 生成serialVersionUID的方法

    默认情况下Intellij IDEA是关闭了继承了Serializable接口的类生成serialVersionUID的警告.如果需要ide提示生成serialVersionUID,那么需要做以下设置 ...

  8. Android百度地图开发05之公交信息检索 + 路线规划

    在上一篇blog中介绍过POI检索的使用,本篇blog主要介绍公交信息检索和线路规划的内容. 公交信息检索 实际上,公交信息检索与POI检索.在线建议检索非常相似,也是把你需要检索的信息发送给百度地图 ...

  9. Eclipse无法通过FileExplore打开真机data目录

    ok ——> Eclipse无法通过FileExplore打开真机data目录 ref:http://blog.csdn.net/koyoter/article/details/7657440 ...

  10. 16_采用SharedPreferences保存用户偏好设置参数

    按钮事件 <Button android:id="@+id/button" android:layout_width="wrap_content" and ...