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. xamarin IOS 报错处理: an error occurred on client Build420719 while

    xamarin IOS 开发时如果报错如下: an error occurred on client Build420719 while...... 出现如下问题时,可能是1.丢失文件2.没有包括在项 ...

  2. Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结

    Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结 1. 验证码的前世今生11.1. 第一代验证码 图片验证码11.2. 第二代验证码  用户操作 ,比如 ...

  3. Ajax 加载数据 练习 自我有些迷糊了,写的大概请谅解 ^ _ ^

    查询表的显示,查询显示如果不嵌入PHP代码的话,用ajax怎么实现?   <h1>显示数据</h1> <table width="100%" bord ...

  4. JavaScript权威设计--事件处理介绍(简要学习笔记十七)

    1.事件相关概念 事件类型:一个用来说明发生什么类型事件的字符串 事件目标:是发生的事件或与之相关的对象. 事件处理程序(事件监听程序):是处理货响应事件的函数. 事件对象:是与特定事件相关并且包含有 ...

  5. ASP.NET Core管道深度剖析[共4篇]

    之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET Core应用的很多特性,比 ...

  6. 通过一个实例理解 offsetLeft,offsetTop; offsetWidth , offsetHeight

    obj.offsetTop 指 obj 相对于版面或由 offsetParent 属性指定的父坐标的计算上侧位置,整型 obj.offsetLeft 指 obj 相对于版面或由 offsetParen ...

  7. linux su和sudo命令的区别

    一. 使用 su 命令临时切换用户身份 1.su 的适用条件和威力 su命令就是切换用户的工具,怎么理解呢?比如我们以普通用户beinan登录的,但要添加用户任务,执行useradd ,beinan用 ...

  8. CloudNotes之领域建模篇:领域模型简介

    CloudNotes领域模型还是相对简单的,并不一定需要采用面向领域驱动的设计方法来解决CloudNotes的领域问题.但出于以下几个方面的原因,我还是采用了面向领域驱动的方式来开发CloudNote ...

  9. 简简单单学会C#位运算

    一.理解位运算 要学会位运算,首先要清楚什么是位运算?程序中的所有内容在计算机内存中都是以二进制的形式储存的(即:0或1),位运算就是直接对在内存中的二进制数的每位进行运算操作 二.理解数字进制 上面 ...

  10. 分享一实战性开源MVC框架<Linux、Windows跨平台开发so easy>

    一.引子   开源地址 https://github.com/564064202/Moon.Mvc 欢迎加入开发 .NET Core微软还在发力,但作为商用还有一段距离,很多开发库尚不能用于.NET ...