xref: /netbsd-src/external/ibm-public/postfix/dist/src/qmgr/qmgr_defer.c (revision 41fbaed053f8fbfdf9d2a4ee0a7386a3c83f8505)
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 
qmgr_defer_transport(QMGR_TRANSPORT * transport,DSN * dsn)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 
qmgr_defer_todo(QMGR_QUEUE * queue,DSN * dsn)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 
qmgr_defer_recipient(QMGR_MESSAGE * message,RECIPIENT * recipient,DSN * dsn)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