PL/SQL 下邮件发送程序

简介:

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

 

1、调用SENDMAIL_PKG来发送邮件

[sql]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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.   
  29. PL/SQL procedure successfully completed.  


2、邮件发送结果

     

3、原代码

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



本文转自 张冲andy 博客园博客,原文链接:http://www.cnblogs.com/andy6/p/5877484.html    ,如需转载请自行联系原作者
相关文章
|
9月前
|
存储 SQL 数据库连接
C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
本文分析了C#程序操作Sql Server数据库时偶发的不返回、不抛异常问题,并提出了解决思路。首先解析了一个执行存储过程的函数`ExecuteProcedure`,其功能是调用存储过程并返回影响行数。针对代码执行被阻塞但无异常的情况,文章总结了可能原因,如死锁、无限循环或网络问题等。随后提供了多种解决方案:1) 增加日志定位问题;2) 使用异步操作提升响应性;3) 设置超时机制避免阻塞;4) 利用线程池分离主线程;5) 通过信号量同步线程;6) 监控数据库连接状态确保可用性。这些方法可有效应对数据库操作中的潜在问题,保障程序稳定性。
723 11
|
SQL 数据采集 监控
局域网监控电脑屏幕软件:PL/SQL 实现的数据库关联监控
在当今网络环境中,基于PL/SQL的局域网监控系统对于企业和机构的信息安全至关重要。该系统包括屏幕数据采集、数据处理与分析、数据库关联与存储三个核心模块,能够提供全面而准确的监控信息,帮助管理者有效监督局域网内的电脑使用情况。
208 2
|
SQL 安全 网络安全
SQL安装程序规则错误解决方案
在安装SQL Server时,遇到安装程序规则错误是一个比较常见的问题
|
SQL 安全 Windows
SQL安装程序规则错误解析与解决方案
在安装SQL Server时,用户可能会遇到安装程序规则错误的问题,这些错误通常与系统配置、权限设置、依赖项缺失或版本不兼容等因素有关
1106 2
|
SQL Oracle 关系型数据库
SQL与PL/SQL:数据库编程语言的比较
【8月更文挑战第31天】
534 1
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标自定义异常:数据探险家的“专属警示灯”
【4月更文挑战第19天】Oracle PL/SQL中的游标自定义异常是处理数据异常的有效工具,犹如数据探险家的警示灯。通过声明异常名(如`LOW_SALARY_EXCEPTION`)并在满足特定条件(如薪资低于阈值)时使用`RAISE`抛出异常,能灵活应对复杂业务规则。示例代码展示了如何在游标操作中定义和捕获自定义异常,提升代码可读性和维护性,确保在面对数据挑战时能及时响应。掌握自定义异常,让数据管理更从容。
|
SQL Oracle 安全
Oracle的PL/SQL游标异常处理:从“惊涛骇浪”到“风平浪静”
【4月更文挑战第19天】Oracle PL/SQL游标异常处理确保了在数据操作中遇到的问题得以优雅解决,如`NO_DATA_FOUND`或`TOO_MANY_ROWS`等异常。通过使用`EXCEPTION`块捕获并处理这些异常,开发者可以防止程序因游标问题而崩溃。例如,当查询无结果时,可以显示定制的错误信息而不是让程序终止。掌握游标异常处理是成为娴熟的Oracle数据管理员的关键,能保证在复杂的数据环境中稳健运行。
|
SQL Oracle 关系型数据库
Oracle的PL/SQL中FOR语句循环游标的奇幻之旅
【4月更文挑战第19天】在Oracle PL/SQL中,FOR语句与游标结合,提供了一种简化数据遍历的高效方法。传统游标处理涉及多个步骤,而FOR循环游标自动处理细节,使代码更简洁、易读。通过示例展示了如何使用FOR循环游标遍历员工表并打印姓名和薪资,对比传统方式,FOR语句不仅简化代码,还因内部优化提升了执行效率。推荐开发者利用这一功能提高工作效率。
|
SQL 数据库 Perl
PL/SQL中执行按钮变为灰色后如何恢复【已解决】
PL/SQL中执行按钮变为灰色后如何恢复【已解决】
1199 0
|
SQL Oracle 安全
Oracle的PL/SQL异常处理方法:守护数据之旅的“魔法盾”
【4月更文挑战第19天】Oracle PL/SQL的异常处理机制是保障数据安全的关键。通过预定义异常(如`NO_DATA_FOUND`)和自定义异常,开发者能优雅地管理错误。异常在子程序中抛出后会向上传播,直到被捕获,提供了一种集中处理错误的方式。理解和善用异常处理,如同手持“魔法盾”,确保程序在面对如除数为零、违反约束等挑战时,能有效保护数据的完整性和程序的稳定性。