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/* Preemptive scheduler enhancements: 63/* Patrik Rak 64/* Modra 6 65/* 155 00, Prague, Czech Republic 66/*--*/ 67 68/* System library. */ 69 70#include <sys_defs.h> 71 72/* Utility library. */ 73 74#include <msg.h> 75#include <vstream.h> 76 77/* Global library. */ 78 79#include <mail_proto.h> 80#include <defer.h> 81 82/* Application-specific. */ 83 84#include "qmgr.h" 85 86/* qmgr_defer_transport - defer todo entries for named transport */ 87 88void qmgr_defer_transport(QMGR_TRANSPORT *transport, DSN *dsn) 89{ 90 QMGR_QUEUE *queue; 91 QMGR_QUEUE *next; 92 93 if (msg_verbose) 94 msg_info("defer transport %s: %s %s", 95 transport->name, dsn->status, dsn->reason); 96 97 /* 98 * Proceed carefully. Queues may disappear as a side effect. 99 */ 100 for (queue = transport->queue_list.next; queue; queue = next) { 101 next = queue->peers.next; 102 qmgr_defer_todo(queue, dsn); 103 } 104} 105 106/* qmgr_defer_todo - defer all todo queue entries for specific site */ 107 108void qmgr_defer_todo(QMGR_QUEUE *queue, DSN *dsn) 109{ 110 QMGR_ENTRY *entry; 111 QMGR_ENTRY *next; 112 QMGR_MESSAGE *message; 113 RECIPIENT *recipient; 114 int nrcpt; 115 QMGR_QUEUE *retry_queue; 116 117 /* 118 * Sanity checks. 119 */ 120 if (msg_verbose) 121 msg_info("defer site %s: %s %s", 122 queue->name, dsn->status, dsn->reason); 123 124 /* 125 * See if we can redirect the deliveries to the retry(8) delivery agent, 126 * so that they can be handled asynchronously. If the retry(8) service is 127 * unavailable, use the synchronous defer(8) server. With a large todo 128 * queue, this blocks the queue manager for a significant time. 129 */ 130 retry_queue = qmgr_error_queue(MAIL_SERVICE_RETRY, dsn); 131 132 /* 133 * Proceed carefully. Queue entries may disappear as a side effect. 134 */ 135 for (entry = queue->todo.next; entry != 0; entry = next) { 136 next = entry->queue_peers.next; 137 if (retry_queue != 0) { 138 qmgr_entry_move_todo(retry_queue, entry); 139 continue; 140 } 141 message = entry->message; 142 for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) { 143 recipient = entry->rcpt_list.info + nrcpt; 144 qmgr_defer_recipient(message, recipient, dsn); 145 } 146 qmgr_entry_done(entry, QMGR_QUEUE_TODO); 147 } 148} 149 150/* qmgr_defer_recipient - defer delivery of specific recipient */ 151 152void qmgr_defer_recipient(QMGR_MESSAGE *message, RECIPIENT *recipient, 153 DSN *dsn) 154{ 155 MSG_STATS stats; 156 157 /* 158 * Update the message structure and log the message disposition. 159 */ 160 message->flags |= defer_append(message->tflags, message->queue_id, 161 QMGR_MSG_STATS(&stats, message), recipient, 162 "none", dsn); 163} 164