使用Oracle的utl_smtp进行调试
时间:2020-03-06 14:46:39 来源:igfitidea点击:
我的一个客户使用Oracle 9i的utl_smtp在员工提出差旅请求时希望向经理发送邮件通知,并且他们希望对已完成的邮件发送进行许多更改。
让utl_smtp与我们网络上的任何smtp服务器通信时,我们遇到很多问题。我们甚至尝试在oracle盒上安装免费的smtp服务器,但它不会发现在端口25上运行的邮件服务器。错误代码为ORA-29278.
所以确实有两个问题。
- 有没有人有使用Oracle的utl_smtp实用程序设置电子邮件的经验,并且对我们可能会出错的地方有任何建议。
- 有谁知道是否有可能像使用system.net.mail的指定的pickupdirectory配置设置一样,使utl_smtp将文本电子邮件转储到目录中。到目前为止,这将是更可取的选择。
谢谢,丹
解决方案
是的,我们可以远程登录到服务器。
-- ****** Object: Stored Procedure TRAVELADMIN_DEV.HTML_EMAIL Script Date: 22/08/2008 12:41:02 ****** CREATE PROCEDURE "HTML_EMAIL" ( p_to in varchar2, p_cc in varchar2, p_from in varchar2, p_subject in varchar2, p_text in varchar2 default null, p_html in varchar2 default null ) is l_boundary varchar2(255) default 'a1b2c3d4e3f2g1'; l_connection utl_smtp.connection; l_body_html clob := empty_clob; --This LOB will be the email message l_offset number; l_ammount number; l_temp varchar2(32767) default null; p_smtp_hostname varchar2(30):= 'rockies'; p_smtp_portnum varchar2(2) := '25'; begin l_connection := utl_smtp.open_connection( p_smtp_hostname, p_smtp_portnum ); utl_smtp.helo( l_connection, p_smtp_hostname ); utl_smtp.mail( l_connection, p_from ); utl_smtp.rcpt( l_connection, p_to ); l_temp := l_temp || 'MIME-Version: 1.0' || chr(13) || chr(10); l_temp := l_temp || 'To: ' || p_to || chr(13) || chr(10); IF ((p_cc <> NULL) OR (LENGTH(p_cc) > 0)) THEN l_temp := l_temp || 'Cc: ' || p_cc || chr(13) || chr(10); utl_smtp.rcpt( l_connection, p_cc ); END IF; l_temp := l_temp || 'From: ' || p_from || chr(13) || chr(10); l_temp := l_temp || 'Subject: ' || p_subject || chr(13) || chr(10); l_temp := l_temp || 'Reply-To: ' || p_from || chr(13) || chr(10); l_temp := l_temp || 'Content-Type: multipart/alternative; boundary=' || chr(34) || l_boundary || chr(34) || chr(13) || chr(10); ---------------------------------------------------- -- Write the headers dbms_lob.createtemporary( l_body_html, false, 10 ); dbms_lob.write(l_body_html,length(l_temp),1,l_temp); ---------------------------------------------------- -- Write the text boundary l_offset := dbms_lob.getlength(l_body_html) + 1; l_temp := '--' || l_boundary || chr(13)||chr(10); l_temp := l_temp || 'content-type: text/plain; charset=us-ascii' || chr(13) || chr(10) || chr(13) || chr(10); dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp); ---------------------------------------------------- -- Write the plain text portion of the email l_offset := dbms_lob.getlength(l_body_html) + 1; dbms_lob.write(l_body_html,length(p_text),l_offset,p_text); ---------------------------------------------------- -- Write the HTML boundary l_temp := chr(13)||chr(10)||chr(13)||chr(10)||'--' || l_boundary || chr(13) || chr(10); l_temp := l_temp || 'content-type: text/html;' || chr(13) || chr(10) || chr(13) || chr(10); l_offset := dbms_lob.getlength(l_body_html) + 1; dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp); ---------------------------------------------------- -- Write the HTML portion of the message l_offset := dbms_lob.getlength(l_body_html) + 1; dbms_lob.write(l_body_html,length(p_html),l_offset,p_html); ---------------------------------------------------- -- Write the final html boundary l_temp := chr(13) || chr(10) || '--' || l_boundary || '--' || chr(13); l_offset := dbms_lob.getlength(l_body_html) + 1; dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp); ---------------------------------------------------- -- Send the email in 1900 byte chunks to UTL_SMTP 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_data(l_connection, dbms_lob.substr(l_body_html,l_ammount,l_offset)); l_offset := l_offset + l_ammount ; l_ammount := least(1900,dbms_lob.getlength(l_body_html) - l_ammount); end loop; utl_smtp.close_data(l_connection); utl_smtp.quit( l_connection ); dbms_lob.freetemporary(l_body_html); end;
- OPEN_CONNECTION参数应该是我们要连接的服务器的FQDN或者IP地址。
- HELO参数应该是我们要连接的计算机的FQDN。
如果这行不通,我们知道错误发生在哪一行吗?
看来HELO是问题所在。我们可以用一个简单的测试用例来检查吗...
set serveroutput on declare lConnection UTL_SMTP.CONNECTION; begin lConnection := UTL_SMTP.OPEN_CONNECTION(your_smtp_server); DBMS_OUTPUT.PUT_LINE('Opened ok'); UTL_SMTP.HELO(lConnection, your_client_machine_name); DBMS_OUTPUT.PUT_LINE('HELO ok'); UTL_SMTP.MAIL(lConnection, your_email_address); UTL_SMTP.RCPT(lConnection, your_email_address); DBMS_OUTPUT.PUT_LINE('Addressing ok'); end; /
看来我们已经解决了这个问题。
回答两个问题。
- 仔细检查调用utl_smtp的模式是否具有对sys.utl_smtp,sys.utl_tcp和sys.dbms_lob的执行权限。还要检查发送的消息的时间是否大于32Kb。
- 没有,没有办法让utl_smtp将电子邮件转储到system.net.mail目录中。
感谢cagcowboy的帮助。