对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. 最大 / 小的K个数

    在<剑指offer>上看到的,而且Qunar去年的校招笔试也考了这题,今天晚上去西电腾讯的宣讲会,来宣讲的学长也说他当时一面的时候面试官问了“一亿个数据的最大的十个数”的面试题.今晚就写写 ...

  2. nil和NULL

  3. 纯CSS实现的右侧底部简洁悬浮效果

    我们见过很多页面右侧浮动效果,最早有QQ联系面板,对联广告等,大多数都是基于Javascript实现的动态效果,今天我给大家分享一个只需要CSS结合DIV实现的右侧浮动效果. HTML 我们希望悬浮效 ...

  4. JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-002Table per concrete class with implicit polymorphism(@MappedSuperclass、@AttributeOverride)

    一.结构 二.代码 1. package org.jpwh.model.inheritance.mappedsuperclass; import javax.persistence.MappedSup ...

  5. DP-母函数

    DP---母函数 先由钱币兑换问题开始 http://acm.hdu.edu.cn/showproblem.php?pid=1284 Problem Description 在一个国家仅有1分,2分, ...

  6. lua简化cocos2dx的Action动画序列

    情景 今天写代码时,又要写一个很常见的动画,就是变大变小模拟那个弹性的赶脚,很常用但写起来挺麻烦,封装一下用起来就简单多了. 当然我也知道有缓动动画(EaseAction)可以实现反弹效果,但这不是重 ...

  7. python操作json

    概念 序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON.XML等.反序列化就是从存储区域(JSON,XML)读取反序列化对象的状态 ...

  8. 巧用cssText属性批量操作样式

    给一个HTML元素设置css属性,如 1 2 3 4 var head= document.getElementById("head"); head.style.width = & ...

  9. git 创建branch分支【转】

    转自:http://www.cnblogs.com/jackluo/p/3499731.html 开发者user1 负责用getopt 进行命令解析的功能,因为这个功能用到getopt 函数,于是将这 ...

  10. Eclipse下运行Maven项目提示缺少maven-resources-plugin:2.4.3

    将一个手动创建的Maven项目(命令行下可正常运行)导入到Eclipse中,运行时提示这样的错误信息:[ERROR] Plugin org.apache.maven.plugins:maven-res ...