yangtingkun
===========================================================
利用UTL_SMTP发送邮件
===========================================================

Oracle提供了UTL_SMTP包,可以发送EMAIL


写了一个很简单的小例子:

SQL> DECLARE
2 MAIL_CONN UTL_SMTP.CONNECTION;
3 BEGIN
4 MAIL_CONN := UTL_SMTP.OPEN_CONNECTION('mail.itpub.net', 25);
5 UTL_SMTP.HELO(MAIL_CONN, 'mail.itpub.net');
6 UTL_SMTP.COMMAND(MAIL_CONN, 'AUTH LOGIN');
7 UTL_SMTP.COMMAND(MAIL_CONN,
8 UTL_RAW.CAST_TO_VARCHAR2(
9 UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW('yangtingkun@itpub.net'))));
10 UTL_SMTP.COMMAND(MAIL_CONN,
11 UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW('password'))));
12 UTL_SMTP.MAIL(MAIL_CONN, 'yangtingkun@itpub.net');
13 UTL_SMTP.RCPT(MAIL_CONN, 'yangtk@cis.com.cn');
14 UTL_SMTP.DATA(MAIL_CONN, 'TEST');
15 UTL_SMTP.QUIT(MAIL_CONN);
16 END;
17 /

PL/SQL 过程已成功完成。

就这么一个简单的不能在简单的过程,居然花了N个小时才搞定。

首先打开一个SMTP连接,输入一个邮件服务器的地址,注意如果邮件服务器地址不正确会出现类似这样的错误:

1 行出现错误:
ORA-29278: SMTP
临时性错误
: 421 Service not available
ORA-06512:
"SYS.UTL_SMTP", line 21
ORA-06512:
"SYS.UTL_SMTP", line 97
ORA-06512:
"SYS.UTL_SMTP", line 139
ORA-06512:
line 4

随后输入的分别是用户名和密码。

其实本来打算用UTL_MAIL包实现发邮件的功能,使用UTL_MAIL包基本上一行代码就可以了,但是现在几乎所有的邮件服务器都要求授权验证,因此只能使用UTL_SMTP包来实现,注意如果用户名、密码出现错误,则会报错:

1 行出现错误:
ORA-29279: SMTP
永久性错误
: 535 authorization failed (#5.7.0)
ORA-06512:
"SYS.UTL_SMTP", line 21
ORA-06512:
"SYS.UTL_SMTP", line 99
ORA-06512:
"SYS.UTL_SMTP", line 159
ORA-06512:
line 8

如果没有将用户名密码进行编码就直接发送,会碰到下面的错误:

1 行出现错误:
ORA-29279: SMTP
永久性错误
: 501 malformed auth input (#5.5.4)
ORA-06512:
"SYS.UTL_SMTP", line 21
ORA-06512:
"SYS.UTL_SMTP", line 99
ORA-06512:
"SYS.UTL_SMTP", line 159
ORA-06512:
line 7

如果没有设置用户名、密码,或者使用UTL_MAIL包连接到需要授权验证的邮件服务器,则会报错如下:

1 行出现错误:
ORA-29279: SMTP
永久性错误
: 554 auth login first
ORA-06512:
"SYS.UTL_SMTP", line 21
ORA-06512:
"SYS.UTL_SMTP", line 99
ORA-06512:
"SYS.UTL_SMTP", line 241
ORA-06512:
"SYS.UTL_MAIL", line 424
ORA-06512:
"SYS.UTL_MAIL", line 594
ORA-06512:
line 2

yangtingkun 发表于:2009.06.29 23:13 ::分类: ( ORACLE ) ::阅读:(2750次) :: 评论 (2)
re: 利用UTL_SMTP发送邮件 [回复]

CREATE OR REPLACE PROCEDURE send_mail(
p_recipient VARCHAR2, -- 邮件接收人
p_subject VARCHAR2, -- 邮件标题
p_message VARCHAR2 -- 邮件正文
)
IS

--下面四个变量请根据实际邮件服务器进行赋值
v_mailhost VARCHAR2(30) := 'mail.itpub.net'; --SMTP服务器地址
v_user VARCHAR2(30) := username; --登录SMTP服务器的用户名
v_pass VARCHAR2(20) := password; --登录SMTP服务器的密码
v_sender VARCHAR2(50) := email; --发送者邮箱,一般与 ps_user 对应

v_conn UTL_SMTP.connection; --到邮件服务器的连接
v_msg varchar2(4000); --邮件内容

BEGIN

v_conn := UTL_SMTP.open_connection(v_mailhost, 25);
UTL_SMTP.ehlo(v_conn, v_mailhost); --是用 ehlo() 而不是 helo() 函数
--否则会报:ORA-29279: SMTP 永久性错误: 503 5.5.2 Send hello first.

UTL_SMTP.command(v_conn, 'AUTH LOGIN'); -- smtp服务器登录校验
UTL_SMTP.command(v_conn,UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(v_user))));
UTL_SMTP.command(v_conn,UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(v_pass))));

UTL_SMTP.mail(v_conn, v_sender); --设置发件人
UTL_SMTP.rcpt(v_conn, p_recipient); --设置收件人

-- 创建要发送的邮件内容 注意报头信息和邮件正文之间要空一行
v_msg :='Date:'|| TO_CHAR(SYSDATE, 'yyyy mm dd hh24:mi:ss')
|| UTL_TCP.CRLF || 'From: '|| v_sender || ''
|| UTL_TCP.CRLF || 'To: ' || p_recipient || ''
|| UTL_TCP.CRLF || 'Subject: ' || p_subject
|| UTL_TCP.CRLF || UTL_TCP.CRLF -- 这前面是报头信息
|| p_message; -- 这个是邮件正文

UTL_SMTP.open_data(v_conn); --打开流
UTL_SMTP.write_raw_data(v_conn, UTL_RAW.cast_to_raw(v_msg)); --这样写标题和内容都能用中文
UTL_SMTP.close_data(v_conn); --关闭流
UTL_SMTP.quit(v_conn); --关闭连接

EXCEPTION

WHEN OTHERS THEN
DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);
DBMS_OUTPUT.put_line(DBMS_UTILITY.format_call_stack);

END send_mail;

一直在用的发送Email的存储过程,还不错,呵呵。
BTW:每天都会来关注你的BLOG,学习到了很多smile

吉庆 评论于: 2009.06.30 10:53
re: 利用UTL_SMTP发送邮件 [回复]

嗯,感谢“吉庆”的分享。ITPUB里面其实有很多篇类似的用ORACLE收发邮件的例子,有些功能做的还很强,不过我还是第一次自己写这个代码,写的过程还真是碰到不少问题。

yangtingkun 评论于: 2009.06.30 11:20

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...