我有一个发送电子邮件的程序,这个程序是从其他功能和程序调用的(主要用于发送警报和通知)。
我面临的一个问题是,如果我们的邮件服务器关闭,那么调用函数或过程会停止执行,我的意思是他们不会执行他们应该执行的任何功能。我如何确保调用函数或过程或任何调用的客户端 即使邮件服务器关闭,MailProcedure也应该发挥其功能。
我怎样才能做到这一点? 任何帮助都非常值得赞赏。
邮件程序
CREATE OR REPLACE PROCEDURE MailProcedure(frm_id IN VARCHAR2, to_id IN VARCHAR2, subject IN VARCHAR2, body_text IN VARCHAR2)
AS
c utl_tcp.connection;
rc integer;
BEGIN
c := utl_tcp.open_connection('email_server', 25);
rc := utl_tcp.write_line(c, 'string');
rc := utl_tcp.write_line(c, 'from address');
rc := utl_tcp.write_line(c, 'to address');
rc := utl_tcp.write_line(c, 'Subject');
rc := utl_tcp.write_line(c, 'body');
utl_tcp.close_connection(c);
EXCEPTION
WHEN OTHERS
THEN
null;
END;
/
答案 0 :(得分:3)
由于您希望对电子邮件进行排队以便以后投放,因此最简单的选择是异步发送所有电子邮件。您的其他过程将调用QueueMail
过程,该过程将行插入新的mail_queue
表
CREATE OR REPLACE PROCEDURE QueueMail(p_from IN VARCHAR2,
p_to IN VARCHAR2,
p_subject IN VARCHAR2,
p_body IN VARCHAR2)
AS
BEGIN
INSERT INTO mail_queue( mail_queue_id. from, to, subject, body )
VALUES( mail_queue_seq.nextval, p_from, p_to, p_subject, p_body );
END;
然后,您将拥有一个单独的过程,该过程在一个单独的线程中运行,该线程实际感知电子邮件并从队列中删除消息。像
这样的东西CREATE OR REPLACE PROCEDURE SendQueuedMessages
AS
BEGIN
FOR msg IN (SELECT * FROM mail_queue )
LOOP
sendMessage( msg.from, msg.to, msg.subject, msg.body );
DELETE FROM mail_queue
WHERE mail_queue_id = msg.mail_queue_id;
commit;
END LOOP;
END;
其中sendMessage
实现了发送电子邮件的实际逻辑。我认为您希望使用utl_mail
或utl_smtp
包来发送电子邮件而不是使用utl_tcp
,但当然,您可以使用utl_tcp
。然后,您可以使用SendQueuedMessages
或dbms_job
软件包安排dbms_scheduler
程序。像这样的东西
DECLARE
l_jobno PLS_INTEGER;
BEGIN
dbms_job.submit( l_jobno,
'BEGIN SendQueuedMessages; END;',
sysdate + interval '1' minute,
'sysdate + interval ''1'' minute' );
commit;
END;
将创建一个每分钟运行SendQueuedMessages
过程的作业。如果邮件服务器已关闭,则SendQueuedMessage
过程将失败,并且作业将自动重新安排以便稍后运行。第一次失败后,作业在1分钟后再次运行。第二次失败后,它会在2分钟后运行,然后运行4分钟,8分钟等,直到连续16次失败。如果要捕获SendQueuedMessages
过程中的异常,可以选择默认行为以外的其他内容。由于作业失败导致无法写入警报日志,因此DBA可能会要求您处理异常并处理重新安排作业以避免将不必要的数据写入警报日志。