您的位置:首页 > Web前端

6.9.5 qmgr_active_done_3_generic函数:将邮件文件移入deferred队列

2016-04-07 15:42 344 查看
通过qmgr_active_done_2_generic和qmgr_active_done_25_generic函数,已经完成了退信、延迟提醒信、DSN状态提醒信的发送工作,接下就可以处理依然存放在active队列中的邮件文件本身了,需要将其移除或移入deferred队列:如果邮件已经没有待发收件人,则根据dont_save函数的设置移除邮件文件或将其移入save文件夹。如果邮件还有待发收件人,则仍需尝试重发该邮件,将其移入deferred队列。

/qmgr/qmgr_active.c
518 /* qmgr_active_done_3_generic -continue processing */
519
520 static void qmgr_active_done_3_generic(QMGR_MESSAGE*message)
521 {
522    const char *myname = "qmgr_active_done_3_generic";
523    int     delay;
524
525    /*
526     * Some recipients need to be tried again. Move the queue file time
527     * stamps into the future by the amount of time that the message is
528     * delayed, and move the message to the deferred queue. Impose minimal
529     * and maximal backoff times.
530     *
531     * Since we look at actual time in queue, not time since last delivery
532     * attempt, backoff times will be distributed. However, we can still see
533     * spikes in delivery activity because the interval between deferred
534     * queue scans is finite.
535     */
536    if (message->flags) {
537        if (message->create_time > 0) {
538             delay = event_time() -message->create_time;
539             if (delay >var_max_backoff_time)
540                 delay = var_max_backoff_time;
541             if (delay <var_min_backoff_time)
542                 delay = var_min_backoff_time;
543        } else {
544             delay = var_min_backoff_time;
545        }
546        qmgr_active_defer(message->queue_name, message->queue_id,
547                           MAIL_QUEUE_DEFERRED,delay);
548    }


536-548 如果邮件还有待发收件人,则仍需尝试发送该邮件。只有在邮件还有待发收件人的情况下,才需要将邮件纳入延迟重发流程。

这里要确定一个延迟时间,qmgr_active_defer函数将以此为参数设定移动到deferred队列中的邮件的存取和修改时间。

参数minimal_backoff_time(默认300秒)和maximal_backoff_time(默认4000秒)分别设定邮件在deferred队列中的最短和最长等待时间。超出maximal_backoff_time时限则该延迟邮件必然会被尝试投递,不到minimal_backoff_time时限则邮件不会被尝试投递。延迟时间为当前时间和邮件进入队列时间的差,但必须在minimal_backoff_time和maximal_backoff_time参数之间。

函数qmgr_active_defer通过rename函数将邮件移入deferred队列。它与通用的在队列间移动邮件的mail_queen_rename函数的区别是:会将邮件的存取和修改时间设为一个“未来时刻”:

struct utimbuf tbuf;

tbuf.actime = tbuf.modtime = event_time() +delay;

根据6.5节,qmgr模块使用fairness策略交替从incoming队列和deferred队列取信到active队列,正是这个“未来时刻”实现了邮件的延迟:qmgr_active_feed函数取信时将跳过时间未到的延迟邮件:

/*
* Skip files that have time stamps into the future. They need to cool
* down. Incoming and deferred files can have future time stamps.
*/
if ((scan_info->flags & QMGR_SCAN_ALL) == 0
&&st.st_mtime > time((time_t *) 0) + 1) {
if(msg_verbose)
msg_info("%s: skip %s (%ldseconds)", myname, queue_id,
(long) (st.st_mtime - event_time()));
return(0);
}


549
550    /*
551     * All recipients done. Remove the queue file.
552     */
553    else {
554        if (mail_queue_remove(message->queue_name, message->queue_id)) {
555             if (errno != ENOENT)
556                 msg_fatal("%s: remove %sfrom %s: %m", myname,
557                          message->queue_id, message->queue_name);
558             msg_warn("%s: remove %s from%s: %m", myname,
559                      message->queue_id,message->queue_name);
560        } else {
561            /* Same format as loggedby postsuper. */
562             msg_info("%s: removed",message->queue_id);
563        }
564    }
565
566    /*
567     * Finally, delete the in-core message structure.
568     */
569    qmgr_message_free(message);
570 }


553-570 至此,完成了根据邮件的状态发送退信、延迟提醒信、或DSN状态通知信的工作。对延迟邮件也做了处理。如果邮件再没有需要发送的收件人了,则可以销毁或另存邮件本身和其内存数据了。

函数mail_queue_remove根据dont_remove参数的设置决定是直接用remove函数删除邮件本身还是将其放入saved文件夹以供研究。最后释放QMGR_MESSAGE结构体。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: