Dee*_*ent 3 email oracle plsql oracle10g oracle11g
我有一个生产问题涉及Oracle 11g电子邮件发送日期.代码如下.
procedure email(p_recip in apex_application_global.vc_arr2,
p_subject in varchar2,
p_message in varchar2) is
c utl_smtp.connection;
msg varchar2(4000);
username varchar2(100) := 'XXX';
password varchar2(100) := '123';
l_encoded_username varchar2(200);
l_encoded_password varchar2(200);
l_recips varchar2(2000);
procedure send_header(name in varchar2, header in varchar2) as
begin
utl_smtp.write_data(c, name || ': ' || header || utl_tcp.crlf);
end;
begin
--Open SMTP connection
l_encoded_username := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(username)));
l_encoded_password := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(password)));
c := utl_smtp.open_connection('AAA.BBB.local', '25');
utl_smtp.ehlo(c, 'AAA.BBB.local'); --DO NOT USE HELO
utl_smtp.command(c, 'AUTH', 'LOGIN');
utl_smtp.command(c, l_encoded_username);
utl_smtp.command(c, l_encoded_password);
utl_smtp.mail(c, 'XXX@YYY.on.ca');
if ((p_recip is null) or p_recip.count = 0) then
return;
end if;
for i in 1 .. p_recip.count loop
utl_smtp.rcpt(c, p_recip(i));
l_recips := l_recips || p_recip(i) || ','; --mark as Multiple receivers
end loop;
--now remove the trailing comma at the end of l_recips
l_recips := substr(l_recips, 0, length(l_recips) - 1);
utl_smtp.open_data(c);
--prepare mail header
utl_smtp.write_data(c, 'Date: ' ||
to_char(sysdate, 'MM-DD-YYYY HH24:MI:SS') ||
utl_tcp.crlf);
utl_smtp.write_data(c, 'To: ' || l_recips || utl_tcp.crlf);
utl_smtp.write_data(c, 'From: ' ||
'"Company" <MMM@KKK.on.ca>' ||
utl_tcp.crlf);
utl_smtp.write_data(c, 'Subject: ' || p_subject || utl_tcp.crlf ||
utl_tcp.crlf);
--include the message body
utl_smtp.write_data(c, msg);
-- Write message body
utl_smtp.write_data(c, p_message || utl_tcp.crlf);
-- Clean up
utl_smtp.close_data(c);
utl_smtp.quit(c);
exception
when utl_smtp.transient_error or utl_smtp.permanent_error then
begin
utl_smtp.quit(c);
exception
when utl_smtp.transient_error or utl_smtp.permanent_error then
null;
-- When the SMTP server is down or unavailable, we don't have
-- a connection to the server. The QUIT call will raise an
-- exception that we can ignore.
end;
raise_application_error(-20000, 'Failed to send mail due to the following error: ' ||
sqlerrm);
end;
------------------------------------------
Unfortunately, the date on received email "Sent:" some times are wrong.
For example :
Run Code Online (Sandbox Code Playgroud)



数据格式在RFC 822中指定(在RFC1123中添加了四位数年份).您以不同的格式发送日期.看起来这有时被接受,有时候不被接受; 并且正在给出'错误'的结果.文件夹视图中的日期是接收日期,而不是发送日期,因此它实际上没有任何影响 - 除了它与消息正文中的日期对齐作为有用的交叉引用.
你这样做:
utl_smtp.write_data(c, 'Date: ' ||
to_char(sysdate, 'MM-DD-YYYY HH24:MI:SS') ||
utl_tcp.crlf);
Run Code Online (Sandbox Code Playgroud)
所以现在我得到的价值Date: 05-09-2014 17:43:28.根据应解释为2014-09-05(9月5日)的RFC .您似乎有时会发现,但并非总是如此,这表明MTA的处理方式不同.基于这三个例子,这可能取决于"错误"日期是否有效.如果我发送邮件的那个日期确实出现在Outlook中2014-09-05; 但如果我将其更改为05-23-2014 17:43:28然后它会通过正确的日期 - 可能是因为无效日期2014-23-05被静默拒绝,而MTA使用其当前日期.(或者客户端;事实上可能更有可能).
你似乎在第二个例子中有一个进一步的扭曲,因为它显示06/10/2013而不是,正如你可能期望的那样形成'正确'的日期,06/11/2013.我认为那是因为你也失去了时区偏移; 实际上你并没有设置一个,但是当你调整它时,你可能仍然会越过日期边界.
因此,请按RFC期望格式化您的日期:
utl_smtp.write_data(c, 'Date: ' ||
to_char(systimestamp, 'Dy DD Mon YYYY HH24:MI:SS TZH:TZM',
'NLS_DATE_LANGUAGE=ENGLISH') ||
utl_tcp.crlf);
Run Code Online (Sandbox Code Playgroud)
这使:
Date: Fri 09 May 2014 17:47:52 +01:00
Run Code Online (Sandbox Code Playgroud)
在我的BST时区.请注意,您必须使用systimestamp而不是sysdate获取时区信息.它必须是英文的,所以我添加了可选的第三个参数,to_char()以确保无论会话区域设置如何都是如此.
正如@ShoeLace在评论中提到的那样,上面的字符串仍然不能与RFC 822完全匹配,它可能应该是:
utl_smtp.write_data(c, 'Date: ' ||
to_char(systimestamp, 'Dy, DD Mon YYYY HH24:MI:SS TZHTZM',
'NLS_DATE_LANGUAGE=ENGLISH') ||
utl_tcp.crlf);
Run Code Online (Sandbox Code Playgroud)
现在给出:
Date: Tue, 04 Aug 2015 10:09:31 +0100
Run Code Online (Sandbox Code Playgroud)
有些服务器可以接受没有逗号或冒号,但最好是正确的...