Oracle发邮件,权限问题

- 创建 ACL

BEGIN

DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(acl => 'email_server_permissions.xml',

description => 'Enables network permissions for the e-mail server',

principal => 'LJZ',

is_grant => TRUE,

privilege => 'connect');

END;

-- 与邮件服务关联

BEGIN

DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl => 'email_server_permissions.xml',

host => 'smtp.163.com',

lower_port => 25,

upper_port => NULL);

END;

-- 这样 email_user 用户帐户创建的存储过程便可以向此邮件服务器发送邮件

--删除

BEGIN

DBMS_NETWORK_ACL_ADMIN.drop_acl(acl => 'email_server_permissions.xml');

COMMIT;

END;

--查询

SELECT host, lower_port, upper_port, acl FROM dba_network_acls;

SELECT acl,

principal,

privilege,

is_grant,

TO_CHAR(start_date, 'DD-MON-YYYY') AS start_date,

TO_CHAR(end_date, 'DD-MON-YYYY') AS end_date

FROM dba_network_acl_privileges;

存储过程

create or replace procedure p_send_mail(p_from            in varchar2,
p_to in varchar2,
p_subject in varchar2,
p_text in clob default null,
p_html in clob default null,
p_attachment_path varchar2,
p_smtp_hostname in varchar2,
p_smtp_portnum in varchar2 default 25,
p_need_valid varchar2 default 'Y',
p_user_name varchar2,
p_user_pwd varchar2) is
/*
作用:用oracle发送邮件
主要功能:1、支持多收件人。
2、支持中文
3、支持抄送人
4、支持大于32K的附件
5、支持多行正文
6、支持多附件
7、支持HTML邮件
作者:HH
参数说明:
p_from 发件人
p_to 收件人,多收件人用逗号或分号分隔
p_subject 主题
p_text 文本内容
p_html HTML内容
p_attachment_path 附件地址(绝对路径),多附件用逗号或分号分隔
p_smtp_hostname 邮件服务器地址 例:smtp.163.com
p_smtp_portnum 端口号,默认25
p_need_valid 是否需要用户名密码验证,默认需要('Y')
p_user_name 用户名
p_user_pwd 密码
*/
l_crlf varchar2(2) := utl_tcp.crlf;
l_write_encode varchar2(20) := 'zhs16gbk';
l_attachment_encode varchar2(10) := 'base64';
l_attachment_mime_type varchar2(50) := 'application/octet-stream';
l_attachment_disposition varchar2(10) := 'attachment';
l_boundary_mail varchar2(255) default '#---hh***hh-mail---#';
l_boundary_content varchar2(255) default '#---hh***hh-content---#';
l_first_boundary constant varchar2(256) := '--' || l_boundary_mail ||
l_crlf;
l_last_boundary constant varchar2(256) := '--' || l_boundary_mail || '--' ||
l_crlf;
l_connection utl_smtp.connection;
l_body_html clob := empty_clob; --HTML邮件内容
l_offset number;
l_ammount number;
l_temp varchar2(32767) default null;
l_file_handle utl_file.file_type;
l_line varchar2(1000);
l_mesg varchar2(32767);
l_filepos pls_integer := 1;
l_fil bfile;
l_file_len number;
l_modulo number;
l_pieces number;
l_amt number := 8580;
l_chunks number;
l_buf raw(32767);
l_data raw(32767);
l_max_line_width number := 54;
l_directory_base_name varchar2(100) := 'DIR_FOR_SEND_MAIL';
l_receivers varchar2(32767);
l_count number;
type address_list is table of varchar2(100) index by binary_integer;
my_address_list address_list;
type acct_list is table of varchar2(100) index by binary_integer;
my_acct_list acct_list;
--分割邮件地址或者附件地址
procedure sub_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
/*处理接收邮件地址列表,包括去空格、将;转换为,等*/
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
--表示处理邮件地址
--前后需要加上'<>',否则很多邮箱将不能发送邮件
l_addr := '<' || l_addr || '>';
--调用邮件发送过程
my_address_list(j) := l_addr;
elsif p_splite_flag = 2 then
--表示处理附件名称
my_acct_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;
elsif p_splite_flag = 2 then
my_acct_list(j) := l_addr;
end if;
end if;
end loop;
end; --删除directory
procedure sub_drop_directory(p_directory_name varchar2) is
begin
select count(1)
into l_count
from dba_directories
where directory_name = upper(p_directory_name);
if l_count > 0 then
execute immediate 'drop directory ' || p_directory_name;
end if;
exception
when others then
--null;
raise;
end; --创建directory
procedure sub_create_directory(p_directory_name varchar2, p_dir varchar2) is
begin
execute immediate 'create directory ' || p_directory_name || ' as ''' ||
p_dir || '''';
execute immediate 'grant read,write on directory ' || p_directory_name ||
' to public';
exception
when others then
raise;
end; --返回附件源文件所在目录或者名称
function sub_get_file(p_file varchar2, p_get int) return varchar2 is
--p_get=1 表示返回目录
--p_get=2 表示返回文件名
l_file varchar2(1000);
begin
if instr(p_file, '\') > 0 then
if p_get = 1 then
l_file := substr(p_file, 1, instr(p_file, '\', -1) - 1) || '\';
elsif p_get = 2 then
l_file := substr(p_file,
- (length(p_file) - instr(p_file, '\', -1)));
end if;
elsif instr(p_file, '/') > 0 then
if p_get = 1 then
l_file := substr(p_file, 1, instr(p_file, '/', -1) - 1);
elsif p_get = 2 then
l_file := substr(p_file,
- (length(p_file) - instr(p_file, '/', -1)));
end if;
end if;
return l_file;
end; --发送附件
procedure sub_attachment(conn in out nocopy utl_smtp.connection,
filename in varchar2,
dt_name in varchar2) is
l_filename varchar2(1000);
l_amount number;
begin
sub_drop_directory(dt_name);
--创建directory
sub_create_directory(dt_name, sub_get_file(filename, 1));
--得到附件文件名称
l_filename := sub_get_file(filename, 2);
l_temp := l_temp || l_crlf || '--' || l_boundary_mail || l_crlf;
l_temp := l_temp || 'Content-Type: ' || l_attachment_mime_type || ';
name="' || l_filename || '"
Content-Transfer-Encoding: ' || l_attachment_encode || '
Content-Disposition: ' || l_attachment_disposition || ';
filename="' || l_filename || '"' || l_crlf || l_crlf;
utl_smtp.write_raw_data(l_connection,
utl_raw.cast_to_raw(convert(l_temp,
l_write_encode)));
--begin
--begin
--把附件分成多份,这样可以发送超过32k的附件
l_filepos := 1; --重置offset,在发送多个附件时,必须重置
l_fil := bfilename(dt_name, l_filename);
l_file_len := dbms_lob.getlength(l_fil);
l_modulo := mod(l_file_len, l_amt);
l_pieces := trunc(l_file_len / l_amt);
if (l_modulo <> 0) then
l_pieces := l_pieces + 1;
end if;
dbms_lob.fileopen(l_fil, dbms_lob.file_readonly);
l_data := null;
l_amount := l_amt;
for i in 1 .. l_pieces loop
dbms_lob.read(l_fil, l_amount, l_filepos, l_buf);
l_filepos := i * l_amount + 1;
l_file_len := l_file_len - l_amount;
utl_smtp.write_raw_data(conn, utl_encode.base64_encode(l_buf));
if i = l_pieces then
l_amount := l_file_len;
end if;
end loop;
dbms_lob.fileclose(l_fil);
/*exception
when others then
dbms_lob.fileclose(l_fil);
sub_end_boundary(conn);
raise;
end; --结束处理二进制附件*/
sub_drop_directory(dt_name);
end; --结束过程attachment
procedure sub_send_mail is
l_from varchar2(1000) := '<' || p_from || '>';
begin
l_connection := utl_smtp.open_connection(p_smtp_hostname,
p_smtp_portnum);
utl_smtp.helo(l_connection, p_smtp_hostname);
/* smtp服务器登录校验 */
if p_need_valid = 'Y' then
utl_smtp.command(l_connection, 'AUTH LOGIN', '');
utl_smtp.command(l_connection,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(p_user_name))));
utl_smtp.command(l_connection,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(p_user_pwd))));
end if;
utl_smtp.mail(l_connection, l_from);
sub_splite_str(p_to); --处理邮件地址
for k in 1 .. my_address_list.count loop
l_receivers := l_receivers || my_address_list(k) || ';';
utl_smtp.rcpt(l_connection, my_address_list(k));
end loop;
l_temp := l_temp || 'From: ' || l_from || l_crlf;
l_temp := l_temp || 'To: ' || l_receivers || l_crlf;
--l_temp := l_temp || 'Cc: ' || l_receivers || l_crlf;--抄送
--l_temp := l_temp || 'Bcc: ' || l_receivers || l_crlf;--密送
l_temp := l_temp || 'Subject: ' || p_subject || l_crlf;
--l_temp := l_temp || 'X-Mailer: Foxmail 7, 1, 3, 48[cn]' || l_crlf;--发送客户端
l_temp := l_temp || 'Content-Type: multipart/mixed; boundary="' ||
l_boundary_mail || '"' || l_crlf;
l_temp := l_temp || 'MIME-Version: 1.0' || l_crlf || l_crlf;
l_temp := l_temp || '--' || l_boundary_mail || l_crlf;
if nvl(p_attachment_path, ' ') <> ' ' then
l_temp := l_temp || 'content-type: multipart/alternative; boundary="' ||
l_boundary_content || '"' || l_crlf || l_crlf || l_crlf;
l_temp := l_temp || '--' || l_boundary_content || l_crlf;
end if;
--开始
dbms_lob.createtemporary(l_body_html, false, 10);
dbms_lob.write(l_body_html, length(l_temp), 1, l_temp);
--文本内容
l_offset := dbms_lob.getlength(l_body_html) + 1;
l_temp := 'content-type: text/plain; charset="GB2312"; Content-Transfer-Encoding: base64' ||
l_crlf || l_crlf;
dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);
if trim(p_text) is not null then
dbms_lob.append(l_body_html, p_text);
end if;
--html内容
if nvl(p_attachment_path, ' ') <> ' ' then
l_temp := l_crlf || l_crlf || '--' || l_boundary_content ||'--' || l_crlf;
else
l_temp := l_crlf || l_crlf || '--' || l_boundary_mail ||'--' || l_crlf;
end if;
l_temp := l_temp ||
'content-type: text/html;charset="GB2312";Content-Transfer-Encoding: quoted-printable' ||
l_crlf || l_crlf;
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);
dbms_lob.append(l_body_html, nvl(p_html, ' '));
--content结束
if nvl(p_attachment_path, ' ') <> ' ' then
l_temp := l_crlf || l_crlf || '--' || l_boundary_content || '--' ||
l_crlf || l_crlf;
else
l_temp := l_crlf || '--' || l_boundary_mail || '--' || l_crlf ||
l_crlf;
end if;
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);
--写入邮件
l_offset := 1;
l_ammount := 1900;
utl_smtp.open_data(l_connection);
while l_offset < dbms_lob.getlength(l_body_html) loop
utl_smtp.write_raw_data(l_connection,
utl_raw.cast_to_raw(convert(dbms_lob.substr(l_body_html,
l_ammount,
l_offset),
l_write_encode)));
l_offset := l_offset + l_ammount;
l_ammount := least(1900, dbms_lob.getlength(l_body_html) - l_ammount);
end loop;
commit;
----------------------------------------------------
l_temp := null;
--附件
--如果文件名称不为空,则发送附件
if (p_attachment_path is not null) then
--根据逗号或者分号拆分附件地址
sub_splite_str(p_attachment_path, 2);
--循环发送附件(在同一个邮件中)
for k in 1 .. my_acct_list.count loop
sub_attachment(conn => l_connection,
filename => my_acct_list(k),
dt_name => l_directory_base_name || to_char(k));
l_temp := l_crlf;
end loop;
end if;
l_temp := l_crlf || l_crlf || '--' || l_boundary_mail || '--' || l_crlf ||
l_crlf;
utl_smtp.write_raw_data(l_connection,
utl_raw.cast_to_raw(convert(l_temp,
l_write_encode)));
commit;
utl_smtp.close_data(l_connection);
utl_smtp.quit(l_connection);
--utl_smtp.close_connection(l_connection);
dbms_lob.freetemporary(l_body_html);
end; begin
sub_send_mail();
/*exception
when others then
null;*/
end;

Oracle发送邮件,支持HTML,多收件人,多附件的更多相关文章

  1. ci框架(codeigniter)Email发送邮件、收件人、附件、Email调试工具

        ci框架(codeigniter)Email发送邮件.收件人.附件.Email调试工具 Email 类         CodeIgniter 拥有强大的 Email 类来提供如下的功能: 多 ...

  2. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

  3. 安装oracle10g“程序异常终止。发生内部错误。请将以下文件提供给oracle技术支持部门

    发生情景:测试环境搭建的是windows 2008 r2 sp1系统 在安装Oracle 10g数据库时发生了错误,现在把解决问题的方法和原因分享给大家. *  安装出现的现象: 输入完密码后下一步时 ...

  4. windows2008 安装oracle10g“程序异常终止。发生内部错误。请将以下文件提供给oracle技术支持部门

    在安装oracle10g客户端程序的时候发生了错误!错误如下:“程序异常终止.发生内部错误.请将以下文件提供给oracle技术支持部门:“未知”“未知”“未知” 解决办法: 右键点setup.exe ...

  5. Oracle GoldenGate 支持 从SAP HANA database抽取或者复制数据到SAP HANA database 吗?

    Oracle GoldenGate 支持 从SAP  HANA database抽取或者复制数据到SAP HANA database 吗? 来源于: Does Oracle GoldenGate Su ...

  6. 【从翻译mos文章】在oracle db 11gR2版本号被启用 Oracle NUMA 支持

    在oracle db 11gR2版本号被启用 Oracle NUMA 支持 参考原始: Enable Oracle NUMA support with Oracle Server Version 11 ...

  7. python发送邮件的实例代码(支持html、图片、附件)

    转自http://www.jb51.net/article/34498.htm 第一段代码 #!/usr/bin/python# -*- coding: utf-8 -*- import emaili ...

  8. mono中发送邮件并保存本次收件人的地址

    在ios端mono开发中,发送邮件可以选择调用ios原生email程序.有两种方式实现这种功能,一是程序跳转到ipad中email程序,另外一种是将发送邮件的界面在自己应用里弹出. 首先第一种方式的代 ...

  9. Python使用SMTP发送邮件[HTML格式、送带附件]

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. python的smtplib提供了一 ...

随机推荐

  1. 死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?

    写在前面 阅读目录: 设计误区 数据库已死 枚举映射 关联映射 后记 在上一篇<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>博文中, ...

  2. python装饰器

    今天看了装饰器的一些内容,感觉@修饰符还是挺抽象的. 装饰器就是在不用改变函数实现的情况下,附加的实现一些功能,比如打印日志信息等.需要主意的是装饰器本质是一个高阶函数,她可以返回一个函数. 装饰器需 ...

  3. AngularJS_01之基础概述、设计原则及MVC设计模式

    1.AngularJS: 开源的JS框架,用来开发单一页面应用,以及数据操作频繁的场景:2.设计原则: ①YAGNI原则:You Aren't Gonna Need It! 不要写不需要的代码! ②K ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(31)-MVC使用RDL报表

    系列目录 这次我们来演示MVC3怎么显示RDL报表,坑爹的微软把MVC升级到5都木有良好的支持报表,让MVC在某些领域趋于短板 我们只能通过一些方式来使用rdl报表. Razor视图不支持asp.ne ...

  5. java中异常抛出后代码还会继续执行吗

    今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element){ i ...

  6. C# ListView点击列头进行排序

    /// <summary> /// This class is an implementation of the 'IComparer' interface. /// </summa ...

  7. agsXMPP

    agsXMPP使用 agsXMPP中的例子已经有注册.登录.添加好友.接收好友添加请求.发送消息.接收消息等功能. 修改用户密码 登录后可用以下方法修改密码 IQ iq = new IQ(IqType ...

  8. 【C#公共帮助类】 WebHelper帮助类

    如果你是一个新手,如果你刚接触MVC,如果你跟着置顶的那个项目,我们肯定会用到这里面的几个帮助类 它们都在Common类库下,大家一定要记住要点:取其精华去其糟粕,切勿拿来主义~ Applicatio ...

  9. php函数强大的 strtotime

    使用strtotime可以将各种格式的时间字符串转换为时间戳 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 转换常规时间格式 echo date('Y-m-d H:i: ...

  10. C标准头文件<ctype.h>

    主要包括了一些字符识别和转换函数 字符判断 isalnum() //函数原型 #include<ctype.h> int isalum(int c); 功能:如果输入的字符是字母(alph ...