5
/* defer service client interface
9
/* int defer_append(flags, id, orig_rcpt, recipient, offset, relay,
10
/* entry, format, ...)
13
/* const char *orig_rcpt;
14
/* const char *recipient;
18
/* const char *format;
20
/* int vdefer_append(flags, id, orig_rcpt, recipient, offset, relay,
24
/* const char *orig_rcpt;
25
/* const char *recipient;
29
/* const char *format;
32
/* int defer_flush(flags, queue, id, encoding, sender)
36
/* const char *encoding;
37
/* const char *sender;
39
/* int defer_warn(flags, queue, id, sender)
43
/* const char *sender;
45
/* This module implements a client interface to the defer service,
46
/* which maintains a per-message logfile with status records for
47
/* each recipient whose delivery is deferred, and the reason why.
49
/* defer_append() appends a record to the per-message defer log,
50
/* with the reason for delayed delivery to the named recipient,
51
/* updates the address verification service, or updates a message
52
/* delivery record on request by the sender. The flags argument
53
/* determines the action.
54
/* The result is a convenient non-zero value.
55
/* When the fast flush cache is enabled, the fast flush server is
56
/* notified of deferred mail.
58
/* vdefer_append() implements an alternative client interface.
60
/* defer_flush() bounces the specified message to the specified
61
/* sender, including the defer log that was built with defer_append().
62
/* defer_flush() requests that the deferred recipients are deleted
63
/* from the original queue file.
64
/* The result is zero in case of success, non-zero otherwise.
66
/* defer_warn() sends a warning message that the mail in question has
67
/* been deferred. It does not flush the log.
71
/* The bit-wise OR of zero or more of the following (specify
72
/* BOUNCE_FLAG_NONE to explicitly request not special processing):
74
/* .IP BOUNCE_FLAG_CLEAN
75
/* Delete the defer log in case of an error (as in: pretend
76
/* that we never even tried to defer this message).
77
/* .IP DEL_REQ_FLAG_VERIFY
78
/* The message is an address verification probe. Update the
79
/* address verification database instead of deferring mail.
80
/* .IP DEL_REQ_FLAG_EXPAND
81
/* The message is an address expansion probe. Update the
82
/* the message delivery record instead of deferring mail.
83
/* .IP DEL_REQ_FLAG_RECORD
84
/* This is a normal message with logged delivery. Update the
85
/* message delivery record and defer mail delivery.
88
/* The message queue name of the original message file.
90
/* The queue id of the original message file.
92
/* The original envelope recipient address. If unavailable,
93
/* specify a null string or null pointer.
95
/* A recipient address that is being deferred. The domain part
96
/* of the address is marked dead (for a limited amount of time).
98
/* Queue file offset of recipient record.
100
/* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}.
102
/* The sender envelope address.
104
/* Host we could not talk to.
106
/* Message arrival time.
108
/* The reason for non-delivery.
110
/* Variable-length argument list.
112
/* For convenience, these functions always return a non-zero result.
114
/* Warnings: problems connecting to the defer service.
115
/* Fatal: out of memory.
117
/* Should be replaced by routines with an attribute-value based
118
/* interface instead of an interface that uses a rigid argument list.
122
/* The Secure Mailer license must be distributed with this software.
125
/* IBM T.J. Watson Research
127
/* Yorktown Heights, NY 10598, USA
130
/* System library. */
132
#include <sys_defs.h>
133
#include <stdlib.h> /* 44BSD stdarg.h uses abort() */
137
#ifdef STRCASECMP_IN_STRINGS_H
141
/* Utility library. */
146
/* Global library. */
148
#include <mail_params.h>
149
#include <mail_queue.h>
150
#include <mail_proto.h>
151
#include <flush_clnt.h>
153
#include <log_adhoc.h>
158
#define STR(x) vstring_str(x)
160
/* defer_append - defer message delivery */
162
int defer_append(int flags, const char *id, const char *orig_rcpt,
163
const char *recipient, long offset, const char *relay,
164
time_t entry, const char *fmt,...)
170
status = vdefer_append(flags, id, orig_rcpt, recipient,
171
offset, relay, entry, fmt, ap);
176
/* vdefer_append - defer delivery of queue file */
178
int vdefer_append(int flags, const char *id, const char *orig_rcpt,
179
const char *recipient, long offset, const char *relay,
180
time_t entry, const char *fmt, va_list ap)
182
const char *rcpt_domain;
186
* MTA-requested address verification information is stored in the verify
189
if (flags & DEL_REQ_FLAG_VERIFY) {
190
status = vverify_append(id, orig_rcpt, recipient, relay, entry,
191
"undeliverable", DEL_RCPT_STAT_DEFER, fmt, ap);
196
* User-requested address verification information is logged and mailed
197
* to the requesting user.
199
if (flags & DEL_REQ_FLAG_EXPAND) {
200
status = vtrace_append(flags, id, orig_rcpt, recipient, relay,
201
entry, "4.0.0", "undeliverable", fmt, ap);
206
* Normal mail delivery. May also send a delivery record to the user.
209
VSTRING *why = vstring_alloc(100);
211
vstring_vsprintf(why, fmt, ap);
215
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
216
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND,
217
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
218
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
219
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt,
220
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
221
ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offset,
222
ATTR_TYPE_STR, MAIL_ATTR_STATUS, "4.0.0",
223
ATTR_TYPE_STR, MAIL_ATTR_ACTION, "delayed",
224
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why),
226
msg_warn("%s: %s service failure", id, var_defer_service);
227
log_adhoc(id, orig_rcpt, recipient, relay, entry, "deferred",
228
"%s", vstring_str(why));
233
if (flags & DEL_REQ_FLAG_RECORD)
234
if (trace_append(flags, id, orig_rcpt, recipient, relay,
235
entry, "4.0.0", "deferred",
236
"%s", vstring_str(why)) != 0)
237
msg_warn("%s: %s service failure", id, var_trace_service);
240
* Notify the fast flush service. XXX Should not this belong in the
241
* bounce/defer daemon? Well, doing it here is more robust.
243
if ((rcpt_domain = strrchr(recipient, '@')) != 0 && *++rcpt_domain != 0)
244
switch (flush_add(rcpt_domain, id)) {
246
case FLUSH_STAT_DENY:
249
msg_warn("%s: %s service failure", id, var_flush_service);
257
/* defer_flush - flush the defer log and deliver to the sender */
259
int defer_flush(int flags, const char *queue, const char *id,
260
const char *encoding, const char *sender)
262
flags |= BOUNCE_FLAG_DELRCPT;
264
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
265
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH,
266
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
267
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
268
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
269
ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
270
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
271
ATTR_TYPE_END) == 0) {
278
/* defer_warn - send a copy of the defer log to the sender as a warning bounce
279
* do not flush the log */
281
int defer_warn(int flags, const char *queue, const char *id,
284
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
285
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN,
286
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
287
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
288
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
289
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
290
ATTR_TYPE_END) == 0) {