最近想在Oracle中设置一个触发器,每天执行数据检测脚本之后,如果发现错误数据就自动发送邮件到我邮箱里,于是研究了一下在Oracle中发送邮件的方法。据说10g里可以使用UTL_MAIL包来简单得发送邮件了,但是觉得通用性不高,万一哪天换成9i了就要重写,于是还是决定用UTL_SMTP包来做。

    先简单看一下官方文档上的例子。其实很简单:
------------------------------------------
The following example illustrates how UTL_SMTP is used by an application to send e-mail. The application connects to an SMTP server at port 25 and sends a simple text message.
DECLARE
c UTL_SMTP.CONNECTION;
PROCEDURE send_header(name IN VARCHAR2, header IN VARCHAR2) AS
BEGIN
UTL_SMTP.WRITE_DATA(c, name || ': ' || header || UTL_TCP.CRLF);
END;
BEGIN
c := UTL_SMTP.OPEN_CONNECTION('smtp-server.acme.com');
UTL_SMTP.HELO(c, 'foo.com');
UTL_SMTP.MAIL(c, 'sender@foo.com');
UTL_SMTP.RCPT(c, 'recipient@foo.com');
UTL_SMTP.OPEN_DATA(c);
send_header('From', '"Sender" <sender@foo.com>');
send_header('To', '"Recipient" <recipient@foo.com>');
send_header('Subject', 'Hello');
UTL_SMTP.WRITE_DATA(c, UTL_TCP.CRLF || 'Hello, world!');
UTL_SMTP.CLOSE_DATA(c);
UTL_SMTP.QUIT(c);
EXCEPTION
WHEN utl_smtp.transient_error OR utl_smtp.permanent_error THEN
BEGIN
UTL_SMTP.QUIT(c);
EXCEPTION
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
NULL;
-- When the SMTP server is down or unavailable, we don't have
-- a connection to the server. The QUIT call will raise an
-- exception that we can ignore.
END;
raise_application_error(-20000,
'Failed to send mail due to the following error: ' || sqlerrm);
END;
------------------------------------------
    需要说明一下的是:必须要按照这个例子里的顺序依次执行包中的各个方法。另外注意用UTL_TCP.CRLF来作为换行符。理由如下:
------------------------------------------
The calls to OPEN_DATA, WRITE_DATA, WRITE_RAW_DATA and CLOSE_DATA must be made in the right order. A program calls OPEN_DATA to send the DATA command to
the SMTP server. After that, it can call WRITE_DATA or WRITE_RAW_DATA repeatedly to send the actual data. The data is terminated by calling CLOSE_DATA. After OPEN_DATA is called, the only subprograms that can be called are WRITE_DATA, WRITE_RAW_DATA, or CLOSE_DATA. A call to other APIs will result in an INVALID_OPERATION exception being raised.
The application must ensure that the contents of the body parameter conform to the MIME(RFC822) specification. The DATA routine will terminate the message with a <CR><LF>.<CR><LF> sequence (a single period at the beginning of a line), as required by RFC821. It will also translate any sequence of <CR><LF>.<CR><LF> (single period) in the body to <CR><LF>..<CR><LF> (double period). This
conversion provides the transparency as described in Section 4.5.2 of RFC821.

Notice that this conversion is not bullet-proof. Consider this code fragment:
UTL_SMTP.WRITE_DATA('some message.' || chr(13) || chr(10));
UTL_SMTP.WRITE_DATA('.' || chr(13) || chr(10));

Since the sequence <CR><LF>.<CR><LF> is split between two calls to WRITE_DATA,the implementation of WRITE_DATA will not detect the presence of the data-terminator sequence, and therefore, will not perform the translation. It will be the responsibility ofthe user to handle such a situation, or it may result in premature termination of themessage data.
WRITE_DATA should be called only after OPEN_CONNECTION, HELO or EHLO, MAIL,and RCPT have been called. The connection to the SMTP server must be open and amail transaction must be active when this routine is called.
Note that there is no function form of WRITE_DATA because the SMTP server does notrespond until the data-terminator is sent during the call to CLOSE_DATA.
Text (VARCHAR2) data sent using WRITE_DATA is converted to US7ASCII before it issent. If the text contains multibyte characters, each multibyte character in the text thatcannot be converted to US7ASCII is replaced by a '?' character. If 8BITMIME extensionis negotiated with the SMTP server using the EHLO subprogram, multibyte VARCHAR2data can be sent by first converting the text to RAW using the UTL_RAW package, andthen sending the RAW data using WRITE_RAW_DATA.

------------------------------------------

    别的也没有什么可说的了,自己随手写了一个,因为是单位的邮箱,也不需要验证身份,而且只是发给自己就可以了。贴一下,很简陋不过够用了:
create or replace procedure P_Mail(sender    in varchar2 default 'wangxiaoqi@xxxx.com',
                                   recipient in varchar2 default 'wangxiaoqi@xxxx.com',
                                   subject   in varchar2 default 'The Wrong Data Noticement',
                                   message   in varchar2) is
  mailhost varchar2(30) := '10.27.9.24';
  c        utl_smtp.connection;
  msg      varchar2(1000);
begin
  msg := 'Date: ' || to_char(sysdate - 1, 'dd mon yy hh24:mi:ss') || UTL_TCP.CRLF ||
         'From: <' || sender || '>' || UTL_TCP.CRLF ||
         'subject: ' || subject || UTL_TCP.CRLF ||
         'To: <' || recipient || '>' || UTL_TCP.CRLF ||
         '' || UTL_TCP.CRLF || message;
  c := utl_smtp.open_connection(mailhost, 25);
  utl_smtp.helo(c, mailhost);
  utl_smtp.mail(c, sender);
  utl_smtp.rcpt(c, recipient);
  utl_smtp.data(c, msg);
  utl_smtp.quit(c);
end P_Mail;
------------------------------------------
    但是这个脚本存在一个比较严重的问题,就是不能发送中文,中文发出去是乱码的,要解决这个问题,需要把: utl_smtp.data 改成用utl_smtp.write_raw_data, 修改为:
create or replace procedure P_Mail(sender    in varchar2 default 'wangxiaoqi@xxxx.com',
                                   recipient in varchar2 default 'wangxiaoqi@xxxx.com',
                                   subject   in varchar2 default 'The Wrong Data Noticement',
                                   message   in varchar2) is
  mailhost varchar2(30) := '10.27.9.24';
  c        utl_smtp.connection;
  msg      varchar2(1000);
begin
  msg := 'Date: ' || to_char(sysdate - 1, 'dd mon yy hh24:mi:ss') || UTL_TCP.CRLF ||
         'From: <' || sender || '>' || UTL_TCP.CRLF ||
         'subject: ' || subject || UTL_TCP.CRLF ||
         'To: <' || recipient || '>' || UTL_TCP.CRLF ||
         '' || UTL_TCP.CRLF || message;
  c := utl_smtp.open_connection(mailhost, 25);
  utl_smtp.helo(c, mailhost);
  utl_smtp.mail(c, sender);
  utl_smtp.rcpt(c, recipient);
  utl_smtp.open_data(c);
  utl_smtp.write_raw_data(c, utl_raw.cast_to_raw(msg));
  utl_smtp.close_data(c);
  utl_smtp.quit(c);
end P_Mail;
------------------------------------------
    如果需要使用外网邮箱登陆后发送邮件,则要加入下面的代码:
utl_smtp.command(c, 'auth login');
utl_smtp.command(c, utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(username))));
utl_smtp.command(c, utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(password))));
    具体测试通过的代码如下:
create or replace procedure P_Mail_Sina(sender    in varchar2 default 'decode360@sina.com',
                                        recipient in varchar2 default 'decode360@gmail.com',
                                        subject   in varchar2 default '我的邮件测试',
                                        message   in varchar2) is
  mailhost varchar2(30) := '202.108.3.190'; --ping smpt.sina.com
  c        utl_smtp.connection;
  msg      varchar2(1000);
begin
  msg := 'Date: ' || to_char(sysdate - 1, 'dd mon yy hh24:mi:ss') || UTL_TCP.CRLF ||
         'From: <' || sender || '>' || UTL_TCP.CRLF ||
         'subject: ' || subject || UTL_TCP.CRLF ||
         'To: <' || recipient || '>' || UTL_TCP.CRLF ||
         '' || UTL_TCP.CRLF || message;
  c := utl_smtp.open_connection(mailhost, 25);
utl_smtp.command(c, 'auth login');
utl_smtp.command(c, utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('decode360'))));
utl_smtp.command(c, utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('82654643'))));
  utl_smtp.helo(c, mailhost);
  utl_smtp.mail(c, sender);
  utl_smtp.rcpt(c, recipient);
  utl_smtp.open_data(c);
  utl_smtp.write_raw_data(c, utl_raw.cast_to_raw(msg));
  utl_smtp.close_data(c);
  utl_smtp.quit(c);
end P_Mail_Sina;
------------------------------------------

 
    如果需要加入抄送,则在msg中加入'Cc:'作为name的行即可,如果需要多个接受者,则在收件人中列明,并分别用utl_smtp.rcpt连接,如下:
create or replace procedure P_Mail(sender    in varchar2 default 'wangxiaoqi@xxxx.com',
                                   recipient1 in varchar2 default 'wangxiaoqi@xxxx.com',
                                   recipient2 in varchar2 default 'test01@xxxx.com',
                                   recipient3 in varchar2 default 'test02@xxxx.com',
                                   subject   in varchar2 default 'The Wrong Data Noticement',
                                   message   in varchar2) is
  mailhost varchar2(30) := '10.27.9.24';
  c        utl_smtp.connection;
  msg      varchar2(1000);
begin
  msg := 'Date: ' || to_char(sysdate - 1, 'dd mon yy hh24:mi:ss') || UTL_TCP.CRLF ||
         'From: <' || sender || '>' || UTL_TCP.CRLF ||
         'subject: ' || subject || UTL_TCP.CRLF ||
         'To: <' || recipient1 || '>;<'||recipient2||'>'|| UTL_TCP.CRLF ||
         'Cc: <' || recipient3 || '>' || UTL_TCP.CRLF ||
         '' || UTL_TCP.CRLF || message;
  c := utl_smtp.open_connection(mailhost, 25);
  utl_smtp.helo(c, mailhost);
  utl_smtp.mail(c, sender);
  utl_smtp.rcpt(c, recipient1);
  utl_smtp.rcpt(c, recipient2);
  utl_smtp.rcpt(c, recipient3);
  utl_smtp.open_data(c);
  utl_smtp.write_raw_data(c, utl_raw.cast_to_raw(msg));
  utl_smtp.close_data(c);
  utl_smtp.quit(c);
end P_Mail;

------------------------------------------

    基本上先了解这些了,其实还有很多其他的功能,例如:支持HTML、支持发送附件等等。具体操作有需要时再学一下,以下列出地址:
----------------------------
HTML功能传送门: http://www.itpub.net/viewthread.php?tid=633486&extra=&page=1
附件功能传送门: http://lz726.javaeye.com/blog/141456
ASK TOM传送门: http://asktom.oracle.com/pls/asktom/f?p=100:11:93372672528637::::P11_QUESTION_ID:255615160805
Java发邮件传送门: http://www.itpub.net/thread-825426-1-1.html

转载于:https://blog.51cto.com/baser/871086

使用UTL_SMTP包发送邮件相关推荐

  1. oracle通过UTL_SMTP包发送邮件

    文章目录 oracle通过UTL_SMTP包发送邮件 存储过程代码 数据库服务器配置 常见异常 异常1-ORA-29278 oracle通过UTL_SMTP包发送邮件 Oracle的UTL_SMTP包 ...

  2. Oracle 利用 UTL_SMTP 包发送邮件

    是这样子,上周末的时候逛了下itpub,看到个挺好玩的东西,通过Oracle的UTL_SMTP包的功能,用定时任务检查数据库状态并发送邮件,因为之前没用过这个包,不知道还有这么好玩的功能,特记录分享一 ...

  3. oracle utl_smtp,Oracle实时通信:UTL_SMTP包详解

    建站学院(LieHuo.Net)文档由于Oracle不提供用于实时输出消息的工具,Oracle数据库开发者总是要面临实时监视他们的储备过程执行的挑战.他们必须使用dbms_output.put_lin ...

  4. oracle utl_smtp,Oracle 11g 环境下,利用utl_smtp创建发送邮件的存储过程

    网上太多发邮件储存过程,我就不转发了,弄个简单的作为示例: create or replace procedure Send_mail(mail_body varchar2) is smtp_conn ...

  5. 使用UTL_MAIL包实现存储过程邮件发送(转)

    邮件通知预警和提示在当前系统中已经是一个比较常见的功能.各类型语言分别针对邮件提供了功能包和API接口方法,本篇介绍如何在PL/SQL代码中使用UTL_MAIL工具包发送邮件,同时还介绍配置中注意的细 ...

  6. oracle存储过程借助utl,使用UTL_MAIL包实现存储过程邮件发送

    邮件通知预警和提示在当前系统中已经是一个比较常见的功能.各类型语言分别针对邮件提供了功能包和API接口方法,本篇介绍如何在PL/SQL代码中使用UTL_MAIL工具包发送邮件,同时还介绍配置中注意的细 ...

  7. java邮件设置成可修改_Java实现发送邮件(可配置)忘记密码,发送邮件

    学过Java基础的应该知道Java里有邮件这一块,不熟悉的话可以简单复习一下 本文章把发送邮件做为可配置可配置文件,这样方便以后维护 一.Maven依赖包 (发送邮件所依赖的jar包) javax.m ...

  8. Maven项目实现简单发送邮件

    Maven项目java后端实现发送邮件 需求 实现邮箱验证找回密码功能,本文介绍后端java实现 实现 pom.xml引入依赖包 <!-- 发送邮件 --> <dependency& ...

  9. php 实现邮件定时发送,PHP 定时发送邮件

    由于工作需要,做了一个PHP自动发送邮件的功能,为了以后可能需要,先简单记录一下 1. 下载专门为PHP发送邮件服务的包class.phpmailer,这个网上可以下载 2. 那么如何使用这个包发送邮 ...

最新文章

  1. python 生成器与迭代器
  2. 软件系统设计 表驱动法
  3. SQL Server 2005“备份集中的数据库备份与现有的数据库不同”解决方法此信息转载自BlueSky's Blog,www.heuupk.com,为尊重无价的知识请保留此版权信息。...
  4. 将SQL文件导入Hive
  5. 【STM32】I2C详解
  6. iOS常见问题(5)
  7. Linux mount挂载和umont卸载U盘
  8. vue使用canvas开发漂亮的多功能手写板组件
  9. 《Java 8实战》读书笔记
  10. Java实现Map集合二级联动
  11. Excel永远不会消亡!
  12. win10修改C盘Users底下的账号名字
  13. golang flag
  14. 什么是mysql 的冗余备份_什么是数据库中的“数据冗余”?
  15. HTML中的元素分类
  16. 在地址栏中显示网站图标的方法(增加网站ico图标)
  17. 计算机科学四个名校,计算机科学CS四大名校来啦
  18. 成都电子科技大学计算机尹佳,电子科技大学成都研究院
  19. 研发效能度量标准与实践
  20. echo -e 命令详解

热门文章

  1. Effective JavaScript Item 37 认识this的隐式指向
  2. taobao-pamirs-schedule-2.0源码分析——任务队列分配源码分析
  3. centos7使用记录
  4. Android第五十二期 - 云之讯的代码混淆
  5. Vagrant常见问题汇总
  6. .Net时间运算 - DateTime类,TimeSpan类
  7. 经典水晶报表设计三则
  8. oracle清空回收站指定表,清空Oracle 10g回收站中以BIN$开头的表
  9. 工业大数据有哪些特征
  10. linux中手动配置ip命令,手动配置linux(centos)的IP地址