PL/SQL下邮件发送程序(一)

2014-11-24 12:13:15 · 作者: · 浏览: 2

对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.

\

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            VAR