2012-07-29 64 views
0

我有一个程序发送电子邮件,并从其他功能和程序(主要用于发送警报和通知)调用此过程。程序发送邮件提醒

我面对的一个问题是,如果我们的邮件服务器关闭,然后调用函数或过程停止执行,我的意思是他们不做任何他们应该做的功能。我如何确保调用函数或过程,或者对于那些调用 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

如果邮件服务器发生故障,您希望发生什么?你想让来电成功,并且不发送电子邮件吗?你想让电子邮件排队以备后用吗?还有别的吗?如果'MailProcedure'确实有'WHEN OTHERS THEN'异常处理程序,它是如何导致调用程序失败的?正如所写的,'MailProcedure'只会默默地失败,这可能不是最好的解决方案,但肯定不应该引发异常被调用者。 – 2012-07-29 18:03:07

+0

如果邮件服务器关闭,则不会发送要发送的邮件,并希望排队以备后用。我怎样才能做到这一点?。谢谢 – user75ponic 2012-07-30 01:56:42

回答

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_mailutl_smtp包发送电子邮件,而不是使用utl_tcp,但当然,您可以使用utl_tcp。然后,您可以使用dbms_jobdbms_scheduler程序包安排SendQueuedMessages程序。这样

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可能会要求您处理异常并处理重新调度作业,以避免将不必要的数据写入警报日志。

+0

感谢贾斯汀您的神话般的答案。我会在特定时间完成工作。非常感激。 – user75ponic 2012-08-06 07:16:12