oracle系统提供的dbms_pipe包能否发送邮件

问题描述

oracle系统提供的dbms_pipe包能否发送邮件

dbms_pipe.PACK_MESSAGE(mailfrom),//mailfrom是一个邮箱地址
dbms_pipe.PACK_MESSAGE(mailfrom),//mailfrom是一个邮箱地址
dbms_pipe.SEND_MESSAGE(pipe,timeout),
dbms_pipe.RECEIVE_MESSAGE(unique,timeOut),
这样就可以向油箱里sub端的邮箱发送邮件。

解决方案

dbms_pipe是发送消息的,你可以用以下存储过程进行邮件发送

Oracle 存储过程发送邮件
CREATE OR REPLACE PROCEDURE PROCSENDEMAIL(P_TXT VARCHAR2,
P_SUB VARCHAR2,
P_SENDOR VARCHAR2,
P_RECEIVER VARCHAR2,
P_SERVER VARCHAR2,
P_PORT NUMBER DEFAULT 25,
P_NEED_SMTP INT DEFAULT 0,
P_USER VARCHAR2 DEFAULT NULL,
P_PASS VARCHAR2 DEFAULT NULL,
P_FILENAME VARCHAR2 DEFAULT NULL,
P_ENCODE VARCHAR2 DEFAULT 'bit 7')
AUTHID CURRENT_USER IS
/*
作用:用oracle发送邮件
主要功能:1、支持多收件人。
2、支持中文
3、支持抄送人
4、支持大于32K的附件
5、支持多行正文
6、支持多附件
7、支持文本附件和二进制附件
8、支持HTML格式
8、支持
作者:suk
参数说明:
p_txt :邮件正文
p_sub: 邮件标题
p_SendorAddress : 发送人邮件地址
p_ReceiverAddress : 接收地址,可以同时发送到多个地址上,地址之间用","或者";"隔开
p_EmailServer : 邮件服务器地址,可以是域名或者IP
p_Port :邮件服务器端口
p_need_smtp:是否需要smtp认证,0表示不需要,1表示需要
p_user:smtp验证需要的用户名
p_pass:smtp验证需要的密码
p_filename:附件名称,必须包含完整的路径,如"d:tempa.txt"。
可以有多个附件,附件名称只见用逗号或者分号分隔
p_encode:附件编码转换格式,其中 p_encode='bit 7' 表示文本类型附件
p_encode='base64' 表示二进制类型附件
注意:
1、对于文本类型的附件,不能用base64的方式发送,否则出错
2、对于多个附件只能用同一种格式发送
/
L_CRLF VARCHAR2(2) := UTL_TCP.CRLF;
L_SENDORADDRESS VARCHAR2(4000);
L_SPLITE VARCHAR2(10) := '++';
BOUNDARY CONSTANT VARCHAR2(256) := '-----BYSUK';
FIRST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || L_CRLF;
LAST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || '--' ||
L_CRLF;
MULTIPART_MIME_TYPE CONSTANT VARCHAR2(256) := 'multipart/mixed; boundary="' ||
BOUNDARY || '"';
/
以下部分是发送大二进制附件时用到的变量 /
L_FIL BFILE;
L_FILE_LEN NUMBER;
L_MODULO NUMBER;
L_PIECES NUMBER;
L_FILE_HANDLE UTL_FILE.FILE_TYPE;
L_AMT BINARY_INTEGER := 672 * 3; /
ensures proper format; 2016 /
L_FILEPOS PLS_INTEGER := 1; /
pointer for the file /
L_CHUNKS NUMBER;
L_BUF RAW(2100);
L_DATA RAW(2100);
L_MAX_LINE_WIDTH NUMBER := 54;
L_DIRECTORY_BASE_NAME VARCHAR2(100) := 'DIR_FOR_SEND_MAIL';
L_LINE VARCHAR2(1000);
L_MESG VARCHAR2(32767);
/
以上部分是发送大二进制附件时用到的变量 /
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;
-------------------------------------返回附件源文件所在目录或者名称--------------------------------------
FUNCTION 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
--windows
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
--linux/unix
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;
---------------------------------------------删除directory------------------------------------
PROCEDURE DROP_DIRECTORY(P_DIRECTORY_NAME VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'drop directory ' || P_DIRECTORY_NAME;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
--------------------------------------------------创建directory-----------------------------------------
PROCEDURE 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;
--------------------------------------------分割邮件地址或者附件地址-----------------------------------
PROCEDURE P_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;
------------------------------------------------写邮件头和邮件内容------------------------------------------
PROCEDURE WRITE_DATA(P_CONN IN OUT NOCOPY UTL_SMTP.CONNECTION,
P_NAME IN VARCHAR2,
P_VALUE IN VARCHAR2,
P_SPLITE VARCHAR2 DEFAULT ':',
P_CRLF VARCHAR2 DEFAULT L_CRLF) IS
BEGIN
/* utl_raw.cast_to_raw 对解决中文乱码问题很重要*/
UTL_SMTP.WRITE_RAW_DATA(P_CONN,
UTL_RAW.CAST_TO_RAW(CONVERT(P_NAME || P_SPLITE ||
P_VALUE || P_CRLF,
'ZHS16GBK')));
END;
----------------------------------------写MIME邮件尾部-----------------------------------------------------
PROCEDURE END_BOUNDARY(CONN IN OUT NOCOPY UTL_SMTP.CONNECTION,
LAST IN BOOLEAN DEFAULT FALSE) IS
BEGIN
UTL_SMTP.WRITE_DATA(CONN, UTL_TCP.CRLF);
IF (LAST) THEN
UTL_SMTP.WRITE_DATA(CONN, LAST_BOUNDARY);
END IF;
END;
----------------------------------------------发送附件----------------------------------------------------
PROCEDURE ATTACHMENT(CONN IN OUT NOCOPY UTL_SMTP.CONNECTION,
MIME_TYPE IN VARCHAR2 DEFAULT 'text/plain',
INLINE IN BOOLEAN DEFAULT TRUE,
FILENAME IN VARCHAR2 DEFAULT 't.txt',
TRANSFER_ENC IN VARCHAR2 DEFAULT '7 bit',
DT_NAME IN VARCHAR2 DEFAULT '0') IS

L_FILENAME VARCHAR2(1000);

BEGIN
--写附件头
UTL_SMTP.WRITE_DATA(CONN, FIRST_BOUNDARY);
--设置附件格式
WRITE_DATA(CONN, 'Content-Type', MIME_TYPE);
--如果文件名称非空,表示有附件
DROP_DIRECTORY(DT_NAME);
--创建directory
CREATE_DIRECTORY(DT_NAME, GET_FILE(FILENAME, 1));
--得到附件文件名称
L_FILENAME := GET_FILE(FILENAME, 2);
IF (INLINE) THEN
WRITE_DATA(CONN,
'Content-Disposition',
'inline; filename="' || L_FILENAME || '"');
ELSE
WRITE_DATA(CONN,
'Content-Disposition',
'attachment; filename="' || L_FILENAME || '"');
END IF;
--设置附件的转换格式
IF (TRANSFER_ENC IS NOT NULL) THEN
WRITE_DATA(CONN, 'Content-Transfer-Encoding', TRANSFER_ENC);
END IF;

UTL_SMTP.WRITE_DATA(CONN, UTL_TCP.CRLF);

--begin 贴附件内容
IF TRANSFER_ENC = 'bit 7' THEN
  --如果是文本类型的附件
  BEGIN
    L_FILE_HANDLE := UTL_FILE.FOPEN(DT_NAME, L_FILENAME, 'r'); --打开文件
    --把附件分成多份,这样可以发送超过32K的附件
    LOOP
      UTL_FILE.GET_LINE(L_FILE_HANDLE, L_LINE);
      L_MESG := L_LINE || L_CRLF;
      WRITE_DATA(CONN, '', L_MESG, '', '');
    END LOOP;
    UTL_FILE.FCLOSE(L_FILE_HANDLE);
    END_BOUNDARY(CONN);
  EXCEPTION
    WHEN OTHERS THEN
      UTL_FILE.FCLOSE(L_FILE_HANDLE);
      END_BOUNDARY(CONN);
      NULL;
  END; --结束文本类型附件的处理

ELSIF TRANSFER_ENC = 'base64' THEN
  --如果是二进制类型的附件
  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);
    DBMS_LOB.READ(L_FIL, L_AMT, L_FILEPOS, L_BUF);
    L_DATA := NULL;
    FOR I IN 1 .. L_PIECES LOOP
      L_FILEPOS  := I * L_AMT + 1;
      L_FILE_LEN := L_FILE_LEN - L_AMT;
      L_DATA     := UTL_RAW.CONCAT(L_DATA, L_BUF);
      L_CHUNKS   := TRUNC(UTL_RAW.LENGTH(L_DATA) / L_MAX_LINE_WIDTH);
      IF (I <> L_PIECES) THEN
        L_CHUNKS := L_CHUNKS - 1;
      END IF;
      UTL_SMTP.WRITE_RAW_DATA(CONN, UTL_ENCODE.BASE64_ENCODE(L_DATA));
      L_DATA := NULL;
      IF (L_FILE_LEN < L_AMT AND L_FILE_LEN > 0) THEN
        L_AMT := L_FILE_LEN;
      END IF;
      DBMS_LOB.READ(L_FIL, L_AMT, L_FILEPOS, L_BUF);
    END LOOP;
    DBMS_LOB.FILECLOSE(L_FIL);
    END_BOUNDARY(CONN);
  EXCEPTION
    WHEN OTHERS THEN
      DBMS_LOB.FILECLOSE(L_FIL);
      END_BOUNDARY(CONN);
      RAISE;
  END; --结束处理二进制附件

END IF; --结束处理附件内容
DROP_DIRECTORY(DT_NAME);

END; --结束过程ATTACHMENT
---------------------------------------------真正发送邮件的过程--------------------------------------------
PROCEDURE P_EMAIL(P_SENDORADDRESS2 VARCHAR2, --发送地址
P_RECEIVERADDRESS2 VARCHAR2) --接受地址
IS
L_CONN UTL_SMTP.CONNECTION; --定义连接
BEGIN
/*初始化邮件服务器信息,连接邮件服务器*/
L_CONN := UTL_SMTP.OPEN_CONNECTION(P_SERVER, P_PORT);
UTL_SMTP.HELO(L_CONN, P_SERVER);
/* smtp服务器登录校验 */
IF P_NEED_SMTP = 1 THEN
UTL_SMTP.COMMAND(L_CONN, 'AUTH LOGIN', '');
UTL_SMTP.COMMAND(L_CONN,
UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(P_USER))));
UTL_SMTP.COMMAND(L_CONN,
UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(P_PASS))));
END IF;

/*设置发送地址和接收地址*/
UTL_SMTP.MAIL(L_CONN, P_SENDORADDRESS2);
UTL_SMTP.RCPT(L_CONN, P_RECEIVERADDRESS2);

/*设置邮件头*/
UTL_SMTP.OPEN_DATA(L_CONN);

WRITE_DATA(L_CONN, 'Date', TO_CHAR(SYSDATE, 'yyyy-mm-dd hh24:mi:ss'));
/*设置发送人*/
WRITE_DATA(L_CONN, 'From', P_SENDOR);
/*设置接收人*/
WRITE_DATA(L_CONN, 'To', P_RECEIVER);
/*设置邮件主题*/
WRITE_DATA(L_CONN, 'Subject', P_SUB);

WRITE_DATA(L_CONN, 'Content-Type', MULTIPART_MIME_TYPE);
UTL_SMTP.WRITE_DATA(L_CONN, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(L_CONN, FIRST_BOUNDARY);
WRITE_DATA(L_CONN, 'Content-Type', 'text/plain;charset=gb2312');
--单独空一行,否则,正文内容不显示
UTL_SMTP.WRITE_DATA(L_CONN, UTL_TCP.CRLF);
/* 设置邮件正文
  把分隔符还原成chr(10)。这主要是为了shell中调用该过程,如果有多行,则先把多行的内容合并成一行,并用 l_splite分隔
  然后用 l_crlf替换chr(10)。这一步是必须的,否则将不能发送邮件正文有多行的邮件
*/
WRITE_DATA(L_CONN,
           '',
           REPLACE(REPLACE(P_TXT, L_SPLITE, CHR(10)), CHR(10), L_CRLF),
           '',
           '');
END_BOUNDARY(L_CONN);

--如果文件名称不为空,则发送附件
IF (P_FILENAME IS NOT NULL) THEN
  --根据逗号或者分号拆分附件地址
  P_SPLITE_STR(P_FILENAME, 2);
  --循环发送附件(在同一个邮件中)
  FOR K IN 1 .. MY_ACCT_LIST.COUNT LOOP
    ATTACHMENT(CONN         => L_CONN,
               FILENAME     => MY_ACCT_LIST(K),
               TRANSFER_ENC => P_ENCODE,
               DT_NAME      => L_DIRECTORY_BASE_NAME || TO_CHAR(K));
  END LOOP;
END IF;

/*关闭数据写入*/
UTL_SMTP.CLOSE_DATA(L_CONN);
/*关闭连接*/
UTL_SMTP.QUIT(L_CONN);

/*异常处理*/

EXCEPTION
WHEN OTHERS THEN
NULL;
RAISE;

END;
---------------------------------------------------主过程-----------------------------------------------------
BEGIN
L_SENDORADDRESS := '<' || P_SENDOR || '>';
P_SPLITE_STR(P_RECEIVER); --处理邮件地址
FOR K IN 1 .. MY_ADDRESS_LIST.COUNT LOOP
P_EMAIL(L_SENDORADDRESS, MY_ADDRESS_LIST(K));
END LOOP;
/*处理邮件地址,根据逗号分割邮件*/
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
  

PROCSENDEMAIL('邮件内容','邮件主题','发件人','收件人','邮件服务器ip地址',25,1,'用户名','密码','','base64');
注意邮件服务器一定要用ip,用域名不行。

时间: 2024-12-21 20:20:35

oracle系统提供的dbms_pipe包能否发送邮件的相关文章

win8.1系统无法安装语言包怎么办?

  win8.1系统无法安装语言包怎么办?         1.下载中文语言包,无需解压. 注:这里只提供64位系统的语言包下载,如果你是32位,还请搜索32位语言包,下载后继续后续步骤即可. 2.按住win+R → 对话框中输入"lpksetup" → 点击回车键; 3.出现如下界面 → 点击红色方框部分; 4.出现如下界面 → 点击browse → 找到下载到的语言包 → 点击next; 5.出现如下界面,显示正在安装,你需要做的就是等待,安装完成后,重启电脑,中文版系统即展现在你

介绍VMControl 2.4对IBM i系统提供了哪些支持

IBM Systems Director VMControl 致力于简化 IT 环境中工作量的管理.VMControl 能在一个平台上管理多种硬件平台上的虚拟设备,虚拟服务器,http://www.aliyun.com/zixun/aggregation/13999.html">工作负载和系统池等.VMControl 2.3 已经对 AIX 和 Linux 提供了很好的支持.从 VMControl2.4 版本起,增加了对 IBM i V7.1 TR3 的支持.本文主要介绍 VMContro

Oracle系统统计信息

Oracle系统统计信息 系统统计信息主要描述了与系统硬件相关的某些特性,例如cpu和io系统的性能和利用率等.这些信息对于查询优化器来说是非常重要的,在选择执行计划的过程中,oracle优化器会利用系统统计信息来评估执行计划的成本,因此,准确无误的系统统计信息可以帮助优化器做出正确的选择. 我们可以通过DBMS_STATS.GATHER_SYSTEM_STATS过程来收集系统统计信息,收集的方式有两种:负载统计(WORKLOAD STATISTICS)在具有真实系统负载的数据库系统上,收集某一

win8.1正式版系统如何新增语言包

  win8.1正式版如何新增语言包:在如今这个信息爆棚的时代,电脑是人们工作生活必不可少的工具,电脑的普及也就让用户有了更多的选择性,其中系统语言就是不同用户的需求,因此学会更换语言包也是我们必学的技能哦,下面系统城的小编为大家介绍一下Win8.1系统如何更改语言设置. 1.思想进入控制台/时钟.语言和区域/语言,按下"新增语言"; 2.选取要新增的语言後,按下"开启"; 3.选好语言之後,按下"新增"; 4.按下上个步骤新增语言包中的&quo

领先的无线网络优化系统提供商和设备供应商

邦讯技术(300312,股吧)股份有限公司是国内领先的无线网络优化系统提供商和设备供应商,专业从事无线网络优化系统的设计.实施和代维服务以及无线网络优化系统设备的研发.生产和销售,是行业内为数不多的系统集成.设备销售和代维服务等综合实力较强的企业.经过长期经营积累,公司已具备完备的综合服务平台和直营营销服务体系,充分满足三大运营商的需求,与中国移动.中国联通(600050,股吧).中国电信等国内三大运营商建立了长期互信的合作关系.公司注重技术创新.研发投入,在射频技术领域拥有多项较高水平的核心技

未在本地计算机上注册“OraOleDb.Oracle.1”提供程序。

问题描述 "/soilwater"应用程序中的服务器错误.--------------------------------------------------------------------------------没有可用的错误信息:REGDB_E_CLASSNOTREG(0x80040154).说明:执行当前Web请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息.异常详细信息:System.Data.OleDb.OleDbExce

visual studio 2010-利用系统提供的msiexec.exe,如何在卸载时将全部文件及目录都清除以及删除数据库文件

问题描述 利用系统提供的msiexec.exe,如何在卸载时将全部文件及目录都清除以及删除数据库文件 在VS2010打包项目中,利用系统提供的msiexec.exe制作卸载程序,请帮忙看看以下两个问题如何解决,谢谢! 目前遇到如下问题: 1.卸载完成后,安装目录下还有残留文件,如何将想把整个安装目录都卸掉? 2.在打包安装时将安装目录下的数据库文件还原到本地数据库中.在卸载完成后,打开本地数据库发现还有数据库文件在上面,如何直接在卸载后将数据库文件从数据库中分离并且删除掉? 解决方案 自己定义c

独立网店系统提供商取胜的关键

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;   在当今网店系统泛滥的电子商务圈中,要找到一款好的网店系统要怎么衡量,也就是说网店系统提供商想取胜的关键是什么? 我在这里拿一款网店系统做下比喻:看了他们的讲述和他们顾客的感言,你就知道那关键是什么了. 2009年6月8日 ,威博网络金牌售后服务试行一个月正式启动,本次调整重要主题包括: 1.一对一指定技术工程师服务:为客户专门指定技术支持人员,责任到人.任务到人

java oracle-java连接Oracle时出错,架包什么的都导入了,哪错了啊,还得交作业呢,请大神解救

问题描述 java连接Oracle时出错,架包什么的都导入了,哪错了啊,还得交作业呢,请大神解救 public class JavaToOracle01 { public static void main(String[] args){ String strQuery="SELECT g_ID,t_ID,g_Name,g_Number FROM SCOTT.GOODS"; Connection conn; Statement stat; ResultSet rs; String gid