1/*	$NetBSD$	*/
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
90void    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
110void    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
154void    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