PL/SQL 下邮件发送程序

时间:2024-04-21 05:15:29

对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、邮件发送结果

PL/SQL 下邮件发送程序

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.****.net/leshami/article/details/18616901