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