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