1/*++ 2/* NAME 3/* qmgr_defer 4/* SUMMARY 5/* deal with mail that must be delivered later 6/* SYNOPSIS 7/* #include "qmgr.h" 8/* 9/* void qmgr_defer_recipient(message, recipient, dsn) 10/* QMGR_MESSAGE *message; 11/* RECIPIENT *recipient; 12/* DSN *dsn; 13/* 14/* void qmgr_defer_todo(queue, dsn) 15/* QMGR_QUEUE *queue; 16/* DSN *dsn; 17/* 18/* void qmgr_defer_transport(transport, dsn) 19/* QMGR_TRANSPORT *transport; 20/* DSN *dsn; 21/* DESCRIPTION 22/* qmgr_defer_recipient() defers delivery of the named message to 23/* the named recipient. It updates the message structure and writes 24/* a log entry. 25/* 26/* qmgr_defer_todo() iterates over all "todo" deliveries queued for 27/* the named site, and calls qmgr_defer_recipient() for each recipient 28/* found. Side effects caused by qmgr_entry_done(), qmgr_queue_done(), 29/* and by qmgr_active_done(): in-core queue entries will disappear, 30/* in-core queues may disappear, in-core and on-disk messages may 31/* disappear, bounces may be sent, new in-core queues, queue entries 32/* and recipients may appear. 33/* 34/* qmgr_defer_transport() calls qmgr_defer_todo() for each queue 35/* that depends on the named transport. See there for side effects. 36/* 37/* Arguments: 38/* .IP recipient 39/* A recipient address; used for logging purposes, and for updating 40/* the message-specific \fIdefer\fR log. 41/* .IP queue 42/* Specifies a queue with delivery requests for a specific next-hop 43/* host (or local user). 44/* .IP transport 45/* Specifies a message delivery transport. 46/* .IP dsn 47/* See dsn(3). 48/* BUGS 49/* The side effects of calling this routine are quite dramatic. 50/* DIAGNOSTICS 51/* Panic: consistency check failure. Fatal: out of memory. 52/* LICENSE 53/* .ad 54/* .fi 55/* The Secure Mailer license must be distributed with this software. 56/* AUTHOR(S) 57/* Wietse Venema 58/* IBM T.J. Watson Research 59/* P.O. Box 704 60/* Yorktown Heights, NY 10598, USA 61/*--*/ 62 63/* System library. */ 64 65#include <sys_defs.h> 66 67/* Utility library. */ 68 69#include <msg.h> 70#include <vstream.h> 71 72/* Global library. */ 73 74#include <mail_proto.h> 75#include <defer.h> 76 77/* Application-specific. */ 78 79#include "qmgr.h" 80 81/* qmgr_defer_transport - defer todo entries for named transport */ 82 83void qmgr_defer_transport(QMGR_TRANSPORT *transport, DSN *dsn) 84{ 85 QMGR_QUEUE *queue; 86 QMGR_QUEUE *next; 87 88 if (msg_verbose) 89 msg_info("defer transport %s: %s %s", 90 transport->name, dsn->status, dsn->reason); 91 92 /* 93 * Proceed carefully. Queues may disappear as a side effect. 94 */ 95 for (queue = transport->queue_list.next; queue; queue = next) { 96 next = queue->peers.next; 97 qmgr_defer_todo(queue, dsn); 98 } 99} 100 101/* qmgr_defer_todo - defer all todo queue entries for specific site */ 102 103void qmgr_defer_todo(QMGR_QUEUE *queue, DSN *dsn) 104{ 105 QMGR_ENTRY *entry; 106 QMGR_ENTRY *next; 107 QMGR_MESSAGE *message; 108 RECIPIENT *recipient; 109 int nrcpt; 110 QMGR_QUEUE *retry_queue; 111 112 /* 113 * Sanity checks. 114 */ 115 if (msg_verbose) 116 msg_info("defer site %s: %s %s", 117 queue->name, dsn->status, dsn->reason); 118 119 /* 120 * See if we can redirect the deliveries to the retry(8) delivery agent, 121 * so that they can be handled asynchronously. If the retry(8) service is 122 * unavailable, use the synchronous defer(8) server. With a large todo 123 * queue, this blocks the queue manager for a significant time. 124 */ 125 retry_queue = qmgr_error_queue(MAIL_SERVICE_RETRY, dsn); 126 127 /* 128 * Proceed carefully. Queue entries may disappear as a side effect. 129 */ 130 for (entry = queue->todo.next; entry != 0; entry = next) { 131 next = entry->peers.next; 132 if (retry_queue != 0) { 133 qmgr_entry_move_todo(retry_queue, entry); 134 continue; 135 } 136 message = entry->message; 137 for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) { 138 recipient = entry->rcpt_list.info + nrcpt; 139 qmgr_defer_recipient(message, recipient, dsn); 140 } 141 qmgr_entry_done(entry, QMGR_QUEUE_TODO); 142 } 143} 144 145/* qmgr_defer_recipient - defer delivery of specific recipient */ 146 147void qmgr_defer_recipient(QMGR_MESSAGE *message, RECIPIENT *recipient, 148 DSN *dsn) 149{ 150 MSG_STATS stats; 151 152 /* 153 * Update the message structure and log the message disposition. 154 */ 155 message->flags |= defer_append(message->tflags, message->queue_id, 156 QMGR_MSG_STATS(&stats, message), recipient, 157 "none", dsn); 158} 159