xref: /netbsd-src/external/ibm-public/postfix/dist/src/oqmgr/qmgr_defer.c (revision 41fbaed053f8fbfdf9d2a4ee0a7386a3c83f8505)
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