转:http://www.blogjava.net/decode360/archive/2009/06/11/282879.html
使用UTL_SMTP包发送邮件
最近想在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;
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,
-- 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;
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 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.
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);
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;
'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.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;
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))));
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;
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;
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
相关推荐
下面是一个简单的例子,演示如何使用 UTL_SMTP 包发送电子邮件: 首先,需要声明一个 UTL_SMTP 连接对象,然后打开一个 SMTP 连接,输入一个邮件服务器的地址。注意,如果邮件服务器地址不正确,会出现类似这样的...
该软件包通过utl_smtp编写符合RFC的MIME邮件正文。 它允许简单的文本消息,带有嵌入式图像HTML消息等,以及附件。
以下是使用UTL_SMTP发送带附件的邮件的基本步骤: 1. 打开SMTP连接。 2. 设置邮件头部信息,如发件人、收件人、主题等。 3. 创建MIME多部分消息,添加邮件正文和附件。 4. 使用UTL_SMTP的`DATA`命令发送邮件内容。 5...
3. **使用UTL_SMTP包**:Oracle提供了`UTL_SMTP`包,这是一个PL/SQL API,用于通过SMTP协议发送电子邮件。在存储过程中,我们需要创建一个连接到SMTP服务器的会话,并使用`UTL_SMTP.WRITE_DATA`等函数发送邮件数据。...
UTL_MAIL是Oracle提供的一个用于发送电子邮件的内置程序包。通过UTL_MAIL,开发人员可以在Oracle环境中轻松实现邮件通知功能,这对于系统监控、错误报告及日常业务处理都非常有用。 ##### 安装与配置UTL_MAIL 1. *...
Oracle数据库提供了内置的功能来发送电子邮件,这项功能主要通过PL/SQL包`UTL_SMTP`、`UTL_MAIL`以及`DBMS_NETWORK_ACL_ADMIN`等来实现。下面我们将详细介绍这些组件的作用及其使用方法。 ### 使用`DBMS_NETWORK_...
完全可用的oracle发邮件程序,只要编译一下就可以用
Oracle提供了一个名为UTL_SMTP的包,使得开发人员能够在Oracle8i及以上版本的数据库中发送电子邮件。 UTL_SMTP包是Oracle数据库内置的一个工具,它依赖于Java虚拟机(JVM)。在Oracle 8i中,如果要使用UTL_SMTP,...
为了解决这个问题,我们可以利用Oracle 8i引入的UTL_SMTP包来实现数据库直接发送电子邮件,从而实现实时通信。 UTL_SMTP是Oracle提供的一组PL/SQL接口,允许开发者通过SMTP协议直接从数据库发送邮件。不过,这个...
Oracle提供了一种称为UTL_MAIL的内置包,用于在PL/SQL代码中实现邮件发送功能。本篇文章将深入探讨如何利用Oracle的UTL_MAIL包来发送邮件,并结合提供的`procsendemail.sql`脚本,解析其核心概念和步骤。 UTL_MAIL...
此过程涉及Oracle数据库提供的多个包,如`UTL_SMTP`用于SMTP协议的交互、`UTL_FILE`用于文件读取等。 #### 核心知识点详解 ##### 存储过程定义 存储过程`PROCSENDEMAIL`被设计为接收多个参数,这些参数用于配置...
通过Oracle utl_smtp 发送中文电邮最佳方案:不限字数,UTF-8支持繁简体,html格式
3. **Oracle的UTL_SMTP包**:Oracle 10g及更高版本提供了一个名为UTL_SMTP的包,允许在PL/SQL中直接处理SMTP事务。这个包包含了一系列的子程序,如`OPEN_CONNECTION`、`DATA`、`QUIT`等,可以直接在存储过程中使用。...
Oracle提供了一套名为UTL_SMTP的内置包,允许我们通过SMTP(简单邮件传输协议)与邮件服务器交互来发送邮件。以下是一个利用Oracle数据库发送邮件的实例代码解析: 1. **UTL_SMTP包**: UTL_SMTP是Oracle提供的一...
### Oracle 发送邮件存储过程详解 在IT领域,数据库与应用程序之间的邮件通知功能是一个常见的需求。Oracle数据库提供了强大的工具和API来实现这一功能,其中包括利用存储过程发送邮件的能力。本篇将深入解析一个...
- **电子邮件发送**:使用UTL_MAIL和UTL_SMTP包发送电子邮件。 - **Web I/O**:利用UTL_HTTP包进行HTTP请求,实现与Web服务的交互。 #### 七、全球化和本地化 - **字符集支持**:讨论了如何处理不同字符集的问题,...
Oracle P/L SQL实现发送Email、浏览网页等网络操作功能,以下是此过程包的头部,包体经常打包处理plb,感兴趣用户可以下载下来。 --.使用聚合函数实现 多行合并 Drop Type Strcat_type; Drop Function f_StrCat; ...
- UTL_SMTP包也可以辅助发送邮件,但在此场景中不直接用于Web Service调用。 3. **调用步骤** - **解析WSDL**:首先,你需要获取到Web Service的WSDL文件,通过这个文件理解服务的接口、输入参数和返回类型。 - ...
接着,它使用 UTL_TCP 包来连接邮件服务器,并发送电子邮件。 PROCSENDEMAIL 存储过程的优点 PROCSENDEMAIL 存储过程有很多优点,包括: * 支持多收件人 * 支持中文 * 支持抄送人 * 支持大于 32K 的附件 * 支持...