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;

存储过程

  1. create or replace procedure p_send_mail(p_from in varchar2,
  2. p_to in varchar2,
  3. p_subject in varchar2,
  4. p_text in clob default null,
  5. p_html in clob default null,
  6. p_attachment_path varchar2,
  7. p_smtp_hostname in varchar2,
  8. p_smtp_portnum in varchar2 default 25,
  9. p_need_valid varchar2 default 'Y',
  10. p_user_name varchar2,
  11. p_user_pwd varchar2) is
  12. /*
  13. 作用:用oracle发送邮件
  14. 主要功能:1、支持多收件人。
  15. 2、支持中文
  16. 3、支持抄送人
  17. 4、支持大于32K的附件
  18. 5、支持多行正文
  19. 6、支持多附件
  20. 7、支持HTML邮件
  21. 作者:HH
  22. 参数说明:
  23. p_from 发件人
  24. p_to 收件人,多收件人用逗号或分号分隔
  25. p_subject 主题
  26. p_text 文本内容
  27. p_html HTML内容
  28. p_attachment_path 附件地址(绝对路径),多附件用逗号或分号分隔
  29. p_smtp_hostname 邮件服务器地址 例:smtp.163.com
  30. p_smtp_portnum 端口号,默认25
  31. p_need_valid 是否需要用户名密码验证,默认需要('Y')
  32. p_user_name 用户名
  33. p_user_pwd 密码
  34. */
  35. l_crlf varchar2(2) := utl_tcp.crlf;
  36. l_write_encode varchar2(20) := 'zhs16gbk';
  37. l_attachment_encode varchar2(10) := 'base64';
  38. l_attachment_mime_type varchar2(50) := 'application/octet-stream';
  39. l_attachment_disposition varchar2(10) := 'attachment';
  40. l_boundary_mail varchar2(255) default '#---hh***hh-mail---#';
  41. l_boundary_content varchar2(255) default '#---hh***hh-content---#';
  42. l_first_boundary constant varchar2(256) := '--' || l_boundary_mail ||
  43. l_crlf;
  44. l_last_boundary constant varchar2(256) := '--' || l_boundary_mail || '--' ||
  45. l_crlf;
  46. l_connection utl_smtp.connection;
  47. l_body_html clob := empty_clob; --HTML邮件内容
  48. l_offset number;
  49. l_ammount number;
  50. l_temp varchar2(32767) default null;
  51. l_file_handle utl_file.file_type;
  52. l_line varchar2(1000);
  53. l_mesg varchar2(32767);
  54. l_filepos pls_integer := 1;
  55. l_fil bfile;
  56. l_file_len number;
  57. l_modulo number;
  58. l_pieces number;
  59. l_amt number := 8580;
  60. l_chunks number;
  61. l_buf raw(32767);
  62. l_data raw(32767);
  63. l_max_line_width number := 54;
  64. l_directory_base_name varchar2(100) := 'DIR_FOR_SEND_MAIL';
  65. l_receivers varchar2(32767);
  66. l_count number;
  67. type address_list is table of varchar2(100) index by binary_integer;
  68. my_address_list address_list;
  69. type acct_list is table of varchar2(100) index by binary_integer;
  70. my_acct_list acct_list;
  71. --分割邮件地址或者附件地址
  72. procedure sub_splite_str(p_str varchar2, p_splite_flag int default 1) is
  73. l_addr varchar2(254) := '';
  74. l_len int;
  75. l_str varchar2(4000);
  76. j int := 0; --表示邮件地址或者附件的个数
  77. begin
  78. /*处理接收邮件地址列表,包括去空格、将;转换为,等*/
  79. l_str := trim(rtrim(replace(replace(p_str, ';', ','), ' ', ''), ','));
  80. l_len := length(l_str);
  81. for i in 1 .. l_len loop
  82. if substr(l_str, i, 1) <> ',' then
  83. l_addr := l_addr || substr(l_str, i, 1);
  84. else
  85. j := j + 1;
  86. if p_splite_flag = 1 then
  87. --表示处理邮件地址
  88. --前后需要加上'<>',否则很多邮箱将不能发送邮件
  89. l_addr := '<' || l_addr || '>';
  90. --调用邮件发送过程
  91. my_address_list(j) := l_addr;
  92. elsif p_splite_flag = 2 then
  93. --表示处理附件名称
  94. my_acct_list(j) := l_addr;
  95. end if;
  96. l_addr := '';
  97. end if;
  98. if i = l_len then
  99. j := j + 1;
  100. if p_splite_flag = 1 then
  101. --调用邮件发送过程
  102. l_addr := '<' || l_addr || '>';
  103. my_address_list(j) := l_addr;
  104. elsif p_splite_flag = 2 then
  105. my_acct_list(j) := l_addr;
  106. end if;
  107. end if;
  108. end loop;
  109. end;
  110.  
  111. --删除directory
  112. procedure sub_drop_directory(p_directory_name varchar2) is
  113. begin
  114. select count(1)
  115. into l_count
  116. from dba_directories
  117. where directory_name = upper(p_directory_name);
  118. if l_count > 0 then
  119. execute immediate 'drop directory ' || p_directory_name;
  120. end if;
  121. exception
  122. when others then
  123. --null;
  124. raise;
  125. end;
  126.  
  127. --创建directory
  128. procedure sub_create_directory(p_directory_name varchar2, p_dir varchar2) is
  129. begin
  130. execute immediate 'create directory ' || p_directory_name || ' as ''' ||
  131. p_dir || '''';
  132. execute immediate 'grant read,write on directory ' || p_directory_name ||
  133. ' to public';
  134. exception
  135. when others then
  136. raise;
  137. end;
  138.  
  139. --返回附件源文件所在目录或者名称
  140. function sub_get_file(p_file varchar2, p_get int) return varchar2 is
  141. --p_get=1 表示返回目录
  142. --p_get=2 表示返回文件名
  143. l_file varchar2(1000);
  144. begin
  145. if instr(p_file, '\') > 0 then
  146. if p_get = 1 then
  147. l_file := substr(p_file, 1, instr(p_file, '\', -1) - 1) || '\';
  148. elsif p_get = 2 then
  149. l_file := substr(p_file,
  150. - (length(p_file) - instr(p_file, '\', -1)));
  151. end if;
  152. elsif instr(p_file, '/') > 0 then
  153. if p_get = 1 then
  154. l_file := substr(p_file, 1, instr(p_file, '/', -1) - 1);
  155. elsif p_get = 2 then
  156. l_file := substr(p_file,
  157. - (length(p_file) - instr(p_file, '/', -1)));
  158. end if;
  159. end if;
  160. return l_file;
  161. end;
  162.  
  163. --发送附件
  164. procedure sub_attachment(conn in out nocopy utl_smtp.connection,
  165. filename in varchar2,
  166. dt_name in varchar2) is
  167. l_filename varchar2(1000);
  168. l_amount number;
  169. begin
  170. sub_drop_directory(dt_name);
  171. --创建directory
  172. sub_create_directory(dt_name, sub_get_file(filename, 1));
  173. --得到附件文件名称
  174. l_filename := sub_get_file(filename, 2);
  175. l_temp := l_temp || l_crlf || '--' || l_boundary_mail || l_crlf;
  176. l_temp := l_temp || 'Content-Type: ' || l_attachment_mime_type || ';
  177. name="' || l_filename || '"
  178. Content-Transfer-Encoding: ' || l_attachment_encode || '
  179. Content-Disposition: ' || l_attachment_disposition || ';
  180. filename="' || l_filename || '"' || l_crlf || l_crlf;
  181. utl_smtp.write_raw_data(l_connection,
  182. utl_raw.cast_to_raw(convert(l_temp,
  183. l_write_encode)));
  184. --begin
  185. --begin
  186. --把附件分成多份,这样可以发送超过32k的附件
  187. l_filepos := 1; --重置offset,在发送多个附件时,必须重置
  188. l_fil := bfilename(dt_name, l_filename);
  189. l_file_len := dbms_lob.getlength(l_fil);
  190. l_modulo := mod(l_file_len, l_amt);
  191. l_pieces := trunc(l_file_len / l_amt);
  192. if (l_modulo <> 0) then
  193. l_pieces := l_pieces + 1;
  194. end if;
  195. dbms_lob.fileopen(l_fil, dbms_lob.file_readonly);
  196. l_data := null;
  197. l_amount := l_amt;
  198. for i in 1 .. l_pieces loop
  199. dbms_lob.read(l_fil, l_amount, l_filepos, l_buf);
  200. l_filepos := i * l_amount + 1;
  201. l_file_len := l_file_len - l_amount;
  202. utl_smtp.write_raw_data(conn, utl_encode.base64_encode(l_buf));
  203. if i = l_pieces then
  204. l_amount := l_file_len;
  205. end if;
  206. end loop;
  207. dbms_lob.fileclose(l_fil);
  208. /*exception
  209. when others then
  210. dbms_lob.fileclose(l_fil);
  211. sub_end_boundary(conn);
  212. raise;
  213. end; --结束处理二进制附件*/
  214. sub_drop_directory(dt_name);
  215. end; --结束过程attachment
  216. procedure sub_send_mail is
  217. l_from varchar2(1000) := '<' || p_from || '>';
  218. begin
  219. l_connection := utl_smtp.open_connection(p_smtp_hostname,
  220. p_smtp_portnum);
  221. utl_smtp.helo(l_connection, p_smtp_hostname);
  222. /* smtp服务器登录校验 */
  223. if p_need_valid = 'Y' then
  224. utl_smtp.command(l_connection, 'AUTH LOGIN', '');
  225. utl_smtp.command(l_connection,
  226. utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(p_user_name))));
  227. utl_smtp.command(l_connection,
  228. utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(p_user_pwd))));
  229. end if;
  230. utl_smtp.mail(l_connection, l_from);
  231. sub_splite_str(p_to); --处理邮件地址
  232. for k in 1 .. my_address_list.count loop
  233. l_receivers := l_receivers || my_address_list(k) || ';';
  234. utl_smtp.rcpt(l_connection, my_address_list(k));
  235. end loop;
  236. l_temp := l_temp || 'From: ' || l_from || l_crlf;
  237. l_temp := l_temp || 'To: ' || l_receivers || l_crlf;
  238. --l_temp := l_temp || 'Cc: ' || l_receivers || l_crlf;--抄送
  239. --l_temp := l_temp || 'Bcc: ' || l_receivers || l_crlf;--密送
  240. l_temp := l_temp || 'Subject: ' || p_subject || l_crlf;
  241. --l_temp := l_temp || 'X-Mailer: Foxmail 7, 1, 3, 48[cn]' || l_crlf;--发送客户端
  242. l_temp := l_temp || 'Content-Type: multipart/mixed; boundary="' ||
  243. l_boundary_mail || '"' || l_crlf;
  244. l_temp := l_temp || 'MIME-Version: 1.0' || l_crlf || l_crlf;
  245. l_temp := l_temp || '--' || l_boundary_mail || l_crlf;
  246. if nvl(p_attachment_path, ' ') <> ' ' then
  247. l_temp := l_temp || 'content-type: multipart/alternative; boundary="' ||
  248. l_boundary_content || '"' || l_crlf || l_crlf || l_crlf;
  249. l_temp := l_temp || '--' || l_boundary_content || l_crlf;
  250. end if;
  251. --开始
  252. dbms_lob.createtemporary(l_body_html, false, 10);
  253. dbms_lob.write(l_body_html, length(l_temp), 1, l_temp);
  254. --文本内容
  255. l_offset := dbms_lob.getlength(l_body_html) + 1;
  256. l_temp := 'content-type: text/plain; charset="GB2312"; Content-Transfer-Encoding: base64' ||
  257. l_crlf || l_crlf;
  258. dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);
  259. if trim(p_text) is not null then
  260. dbms_lob.append(l_body_html, p_text);
  261. end if;
  262. --html内容
  263. if nvl(p_attachment_path, ' ') <> ' ' then
  264. l_temp := l_crlf || l_crlf || '--' || l_boundary_content ||'--' || l_crlf;
  265. else
  266. l_temp := l_crlf || l_crlf || '--' || l_boundary_mail ||'--' || l_crlf;
  267. end if;
  268. l_temp := l_temp ||
  269. 'content-type: text/html;charset="GB2312";Content-Transfer-Encoding: quoted-printable' ||
  270. l_crlf || l_crlf;
  271. l_offset := dbms_lob.getlength(l_body_html) + 1;
  272. dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);
  273. dbms_lob.append(l_body_html, nvl(p_html, ' '));
  274. --content结束
  275. if nvl(p_attachment_path, ' ') <> ' ' then
  276. l_temp := l_crlf || l_crlf || '--' || l_boundary_content || '--' ||
  277. l_crlf || l_crlf;
  278. else
  279. l_temp := l_crlf || '--' || l_boundary_mail || '--' || l_crlf ||
  280. l_crlf;
  281. end if;
  282. l_offset := dbms_lob.getlength(l_body_html) + 1;
  283. dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);
  284. --写入邮件
  285. l_offset := 1;
  286. l_ammount := 1900;
  287. utl_smtp.open_data(l_connection);
  288. while l_offset < dbms_lob.getlength(l_body_html) loop
  289. utl_smtp.write_raw_data(l_connection,
  290. utl_raw.cast_to_raw(convert(dbms_lob.substr(l_body_html,
  291. l_ammount,
  292. l_offset),
  293. l_write_encode)));
  294. l_offset := l_offset + l_ammount;
  295. l_ammount := least(1900, dbms_lob.getlength(l_body_html) - l_ammount);
  296. end loop;
  297. commit;
  298. ----------------------------------------------------
  299. l_temp := null;
  300. --附件
  301. --如果文件名称不为空,则发送附件
  302. if (p_attachment_path is not null) then
  303. --根据逗号或者分号拆分附件地址
  304. sub_splite_str(p_attachment_path, 2);
  305. --循环发送附件(在同一个邮件中)
  306. for k in 1 .. my_acct_list.count loop
  307. sub_attachment(conn => l_connection,
  308. filename => my_acct_list(k),
  309. dt_name => l_directory_base_name || to_char(k));
  310. l_temp := l_crlf;
  311. end loop;
  312. end if;
  313. l_temp := l_crlf || l_crlf || '--' || l_boundary_mail || '--' || l_crlf ||
  314. l_crlf;
  315. utl_smtp.write_raw_data(l_connection,
  316. utl_raw.cast_to_raw(convert(l_temp,
  317. l_write_encode)));
  318. commit;
  319. utl_smtp.close_data(l_connection);
  320. utl_smtp.quit(l_connection);
  321. --utl_smtp.close_connection(l_connection);
  322. dbms_lob.freetemporary(l_body_html);
  323. end;
  324.  
  325. begin
  326. sub_send_mail();
  327. /*exception
  328. when others then
  329. null;*/
  330. 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. Android线程管理之Thread使用总结

    前言 最近在一直准备总结一下Android上的线程管理,今天先来总结一下Thread使用. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Executo ...

  2. IDDD 实现领域驱动设计-上下文映射图及其相关概念

    上一篇:<IDDD 实现领域驱动设计-理解限界上下文> 距离上一篇有几天时间了,<实现领域驱动设计>第三章的内容都是围绕一个词-上下文映射图,我大概断断续续看了几天,总共看了两 ...

  3. Android官方文档

    下面的内容来自Android官方网站,由于访问这个网站需要FQ,不方便,所以我把部分内容copy下来了,不保证内容是最新的. Source Overview    Codelines, Branche ...

  4. spring aop

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将 ...

  5. javaScript笔记

    两边符号是tab键上面的那个键,不是单引号 即在sort内置的函数中先将各字符串转化为统一的大写或者小写,再进行比较即可. -------------------------------------- ...

  6. JSP实现word文档的上传,在线预览,下载

    前两天帮同学实现在线预览word文档中的内容,而且需要提供可以下载的链接!在网上找了好久,都没有什么可行的方法,只得用最笨的方法来实现了.希望得到各位大神的指教.下面我就具体谈谈自己的实现过程,总结一 ...

  7. uploadify使用的一些经验总结

    说说自己使用uploadify的一波三折的曲折过程: 之所以要选择uploadify,是源于自己先前使用过jQuery官网的上传文件插件,比较难用(页面写的代码比较多,IE下后台回传需要配置格式[不清 ...

  8. 数百个 HTML5 例子学习 HT 图形组件 – 3D建模篇

    http://www.hightopo.com/demo/pipeline/index.html <数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇>里提到 HT 很 ...

  9. ASP.NET Core官方计划路线及需要废除的一些Framework技术

    概述 下面是 ASP.NET Core的时间表和路线图. 注意日期和特性都可能更改. 作为.NET Core这么大的一个项目,很难准确预测每一个计划的是否有变动. 即便如此,我们还是计划公开和透明的实 ...

  10. .NET跨平台之旅:将QPS 100左右的ASP.NET Core站点部署到Linux服务器上

    今天下午我们将生产环境中一个单台服务器 QPS(每秒请求数)在100左右的 ASP.NET Core 站点部署到了 Linux 服务器上,这是我们解决了在 .NET Core 上使用 EnyimMem ...