Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / abounce.c
blobd5d2eb029b4667747903ed50ba5860d659eddbc8
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* abounce 3
6 /* SUMMARY
7 /* asynchronous bounce/defer service client
8 /* SYNOPSIS
9 /* #include <abounce.h>
11 /* void abounce_flush(flags, queue, id, encoding, sender,
12 /* dsn_envid, dsn_ret, callback, context)
13 /* int flags;
14 /* const char *queue;
15 /* const char *id;
16 /* const char *encoding;
17 /* const char *sender;
18 /* const char *dsn_envid;
19 /* int dsn_ret;
20 /* void (*callback)(int status, char *context);
21 /* char *context;
23 /* void abounce_flush_verp(flags, queue, id, encoding, sender,
24 /* dsn_envid, dsn_ret, verp, callback, context)
25 /* int flags;
26 /* const char *queue;
27 /* const char *id;
28 /* const char *encoding;
29 /* const char *sender;
30 /* const char *dsn_envid;
31 /* int dsn_ret;
32 /* const char *verp;
33 /* void (*callback)(int status, char *context);
34 /* char *context;
36 /* void adefer_flush(flags, queue, id, encoding, sender,
37 /* dsn_envid, dsn_ret, callback, context)
38 /* int flags;
39 /* const char *queue;
40 /* const char *id;
41 /* const char *encoding;
42 /* const char *sender;
43 /* const char *dsn_envid;
44 /* int dsn_ret;
45 /* void (*callback)(int status, char *context);
46 /* char *context;
48 /* void adefer_flush_verp(flags, queue, id, encoding, sender,
49 /* dsn_envid, dsn_ret, verp, callback, context)
50 /* int flags;
51 /* const char *queue;
52 /* const char *id;
53 /* const char *encoding;
54 /* const char *sender;
55 /* const char *dsn_envid;
56 /* int dsn_ret;
57 /* const char *verp;
58 /* void (*callback)(int status, char *context);
59 /* char *context;
61 /* void adefer_warn(flags, queue, id, encoding, sender,
62 /* dsn_envid, dsn_ret, callback, context)
63 /* int flags;
64 /* const char *queue;
65 /* const char *id;
66 /* const char *encoding;
67 /* const char *sender;
68 /* const char *dsn_envid;
69 /* int dsn_ret;
70 /* void (*callback)(int status, char *context);
71 /* char *context;
72 /* DESCRIPTION
73 /* This module implements an asynchronous interface to the
74 /* bounce/defer service for submitting sender notifications
75 /* without waiting for completion of the request.
77 /* abounce_flush() bounces the specified message to
78 /* the specified sender, including the bounce log that was
79 /* built with bounce_append().
81 /* abounce_flush_verp() is like abounce_flush() but sends
82 /* one VERP style notification per undeliverable recipient.
84 /* adefer_flush() bounces the specified message to
85 /* the specified sender, including the defer log that was
86 /* built with defer_append().
87 /* adefer_flush() requests that the deferred recipients are deleted
88 /* from the original queue file.
90 /* adefer_flush_verp() is like adefer_flush() but sends
91 /* one VERP style notification per undeliverable recipient.
93 /* adefer_warn() sends a "mail is delayed" notification to
94 /* the specified sender, including the defer log that was
95 /* built with defer_append().
97 /* Arguments:
98 /* .IP flags
99 /* The bitwise OR of zero or more of the following (specify
100 /* BOUNCE_FLAG_NONE to request no special processing):
101 /* .RS
102 /* .IP BOUNCE_FLAG_CLEAN
103 /* Delete the bounce log in case of an error (as in: pretend
104 /* that we never even tried to bounce this message).
105 /* .IP BOUNCE_FLAG_DELRCPT
106 /* When specified with a flush operation, request that
107 /* recipients be deleted from the queue file.
109 /* Note: the bounce daemon ignores this request when the
110 /* recipient queue file offset is <= 0.
111 /* .IP BOUNCE_FLAG_COPY
112 /* Request that a postmaster copy is sent.
113 /* .RE
114 /* .IP queue
115 /* The message queue name of the original message file.
116 /* .IP id
117 /* The message queue id if the original message file. The bounce log
118 /* file has the same name as the original message file.
119 /* .IP encoding
120 /* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}.
121 /* .IP sender
122 /* The sender envelope address.
123 /* .IP dsn_envid
124 /* Optional DSN envelope ID.
125 /* .IP ret
126 /* Optional DSN return full/headers option.
127 /* .IP verp
128 /* VERP delimiter characters.
129 /* .IP callback
130 /* Name of a routine that receives the notification status as
131 /* documented for bounce_flush() or defer_flush().
132 /* .IP context
133 /* Application-specific context that is passed through to the
134 /* callback routine. Use proper casts or the world will come
135 /* to an end.
136 /* DIAGNOSTICS
137 /* In case of success, these functions log the action, and return a
138 /* zero result via the callback routine. Otherwise, the functions
139 /* return a non-zero result via the callback routine, and when
140 /* BOUNCE_FLAG_CLEAN is disabled, log that message delivery is deferred.
141 /* LICENSE
142 /* .ad
143 /* .fi
144 /* The Secure Mailer license must be distributed with this software.
145 /* AUTHOR(S)
146 /* Wietse Venema
147 /* IBM T.J. Watson Research
148 /* P.O. Box 704
149 /* Yorktown Heights, NY 10598, USA
150 /*--*/
152 /* System library. */
154 #include <sys_defs.h>
156 /* Utility library. */
158 #include <msg.h>
159 #include <mymalloc.h>
160 #include <events.h>
161 #include <vstream.h>
163 /* Global library. */
165 #include <mail_params.h>
166 #include <mail_proto.h>
167 #include <abounce.h>
169 /* Application-specific. */
172 * Each bounce/defer flush/warn request is implemented by sending the
173 * request to the bounce/defer server, and by creating a pseudo thread that
174 * suspends itself until the server replies (or dies). Upon wakeup, the
175 * pseudo thread delivers the request completion status to the application
176 * and destroys itself. The structure below maintains all the necessary
177 * request state while the pseudo thread is suspended.
179 typedef struct {
180 int command; /* bounce request type */
181 int flags; /* bounce options */
182 char *id; /* queue ID for logging */
183 ABOUNCE_FN callback; /* application callback */
184 char *context; /* application context */
185 VSTREAM *fp; /* server I/O handle */
186 } ABOUNCE;
188 /* abounce_done - deliver status to application and clean up pseudo thread */
190 static void abounce_done(ABOUNCE *ap, int status)
192 (void) vstream_fclose(ap->fp);
193 if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
194 msg_info("%s: status=deferred (%s failed)", ap->id,
195 ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
196 ap->command == BOUNCE_CMD_WARN ? "delay warning" :
197 "whatever");
198 ap->callback(status, ap->context);
199 myfree(ap->id);
200 myfree((char *) ap);
203 /* abounce_event - resume pseudo thread after server reply event */
205 static void abounce_event(int unused_event, char *context)
207 ABOUNCE *ap = (ABOUNCE *) context;
208 int status;
210 event_disable_readwrite(vstream_fileno(ap->fp));
211 abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_STRICT,
212 ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
213 ATTR_TYPE_END) == 1 ? status : -1);
216 /* abounce_request_verp - suspend pseudo thread until server reply event */
218 static void abounce_request_verp(const char *class, const char *service,
219 int command, int flags,
220 const char *queue, const char *id,
221 const char *encoding,
222 const char *sender,
223 const char *dsn_envid,
224 int dsn_ret,
225 const char *verp,
226 ABOUNCE_FN callback,
227 char *context)
229 ABOUNCE *ap;
232 * Save pseudo thread state. Connect to the server. Send the request and
233 * suspend the pseudo thread until the server replies (or dies).
235 ap = (ABOUNCE *) mymalloc(sizeof(*ap));
236 ap->command = command;
237 ap->flags = flags;
238 ap->id = mystrdup(id);
239 ap->callback = callback;
240 ap->context = context;
241 ap->fp = mail_connect_wait(class, service);
243 if (attr_print(ap->fp, ATTR_FLAG_NONE,
244 ATTR_TYPE_INT, MAIL_ATTR_NREQ, command,
245 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
246 ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
247 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
248 ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
249 ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
250 ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
251 ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret,
252 ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp,
253 ATTR_TYPE_END) == 0
254 && vstream_fflush(ap->fp) == 0) {
255 event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
256 } else {
257 abounce_done(ap, -1);
261 /* abounce_flush_verp - asynchronous bounce flush */
263 void abounce_flush_verp(int flags, const char *queue, const char *id,
264 const char *encoding, const char *sender,
265 const char *dsn_envid, int dsn_ret,
266 const char *verp, ABOUNCE_FN callback,
267 char *context)
269 abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service,
270 BOUNCE_CMD_VERP, flags, queue, id, encoding,
271 sender, dsn_envid, dsn_ret, verp, callback, context);
274 /* adefer_flush_verp - asynchronous defer flush */
276 void adefer_flush_verp(int flags, const char *queue, const char *id,
277 const char *encoding, const char *sender,
278 const char *dsn_envid, int dsn_ret,
279 const char *verp, ABOUNCE_FN callback,
280 char *context)
282 flags |= BOUNCE_FLAG_DELRCPT;
283 abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service,
284 BOUNCE_CMD_VERP, flags, queue, id, encoding,
285 sender, dsn_envid, dsn_ret, verp, callback, context);
288 /* abounce_request - suspend pseudo thread until server reply event */
290 static void abounce_request(const char *class, const char *service,
291 int command, int flags,
292 const char *queue, const char *id,
293 const char *encoding, const char *sender,
294 const char *dsn_envid, int dsn_ret,
295 ABOUNCE_FN callback, char *context)
297 ABOUNCE *ap;
300 * Save pseudo thread state. Connect to the server. Send the request and
301 * suspend the pseudo thread until the server replies (or dies).
303 ap = (ABOUNCE *) mymalloc(sizeof(*ap));
304 ap->command = command;
305 ap->flags = flags;
306 ap->id = mystrdup(id);
307 ap->callback = callback;
308 ap->context = context;
309 ap->fp = mail_connect_wait(class, service);
311 if (attr_print(ap->fp, ATTR_FLAG_NONE,
312 ATTR_TYPE_INT, MAIL_ATTR_NREQ, command,
313 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
314 ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
315 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
316 ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
317 ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
318 ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
319 ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret,
320 ATTR_TYPE_END) == 0
321 && vstream_fflush(ap->fp) == 0) {
322 event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
323 } else {
324 abounce_done(ap, -1);
328 /* abounce_flush - asynchronous bounce flush */
330 void abounce_flush(int flags, const char *queue, const char *id,
331 const char *encoding, const char *sender,
332 const char *dsn_envid, int dsn_ret,
333 ABOUNCE_FN callback, char *context)
335 abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
336 flags, queue, id, encoding, sender, dsn_envid, dsn_ret,
337 callback, context);
340 /* adefer_flush - asynchronous defer flush */
342 void adefer_flush(int flags, const char *queue, const char *id,
343 const char *encoding, const char *sender,
344 const char *dsn_envid, int dsn_ret,
345 ABOUNCE_FN callback, char *context)
347 flags |= BOUNCE_FLAG_DELRCPT;
348 abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
349 flags, queue, id, encoding, sender, dsn_envid, dsn_ret,
350 callback, context);
353 /* adefer_warn - send copy of defer log to sender as warning bounce */
355 void adefer_warn(int flags, const char *queue, const char *id,
356 const char *encoding, const char *sender,
357 const char *dsn_envid, int dsn_ret,
358 ABOUNCE_FN callback, char *context)
360 abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
361 flags, queue, id, encoding, sender, dsn_envid, dsn_ret,
362 callback, context);