Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / bounce.c
blob1bb90b46e441b987d022b51f4bac5517155acc46
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* bounce 3
6 /* SUMMARY
7 /* bounce service client
8 /* SYNOPSIS
9 /* #include <bounce.h>
11 /* int bounce_append(flags, id, stats, recipient, relay, dsn)
12 /* int flags;
13 /* const char *id;
14 /* MSG_STATS *stats;
15 /* RECIPIENT *rcpt;
16 /* const char *relay;
17 /* DSN *dsn;
19 /* int bounce_flush(flags, queue, id, encoding, sender,
20 /* dsn_envid, dsn_ret)
21 /* int flags;
22 /* const char *queue;
23 /* const char *id;
24 /* const char *encoding;
25 /* const char *sender;
26 /* const char *dsn_envid;
27 /* int dsn_ret;
29 /* int bounce_flush_verp(flags, queue, id, encoding, sender,
30 /* dsn_envid, dsn_ret, verp_delims)
31 /* int flags;
32 /* const char *queue;
33 /* const char *id;
34 /* const char *encoding;
35 /* const char *sender;
36 /* const char *dsn_envid;
37 /* int dsn_ret;
38 /* const char *verp_delims;
40 /* int bounce_one(flags, queue, id, encoding, sender, envid, ret,
41 /* stats, recipient, relay, dsn)
42 /* int flags;
43 /* const char *queue;
44 /* const char *id;
45 /* const char *encoding;
46 /* const char *sender;
47 /* const char *dsn_envid;
48 /* int dsn_ret;
49 /* MSG_STATS *stats;
50 /* RECIPIENT *rcpt;
51 /* const char *relay;
52 /* DSN *dsn;
53 /* DESCRIPTION
54 /* This module implements the client interface to the message
55 /* bounce service, which maintains a per-message log of status
56 /* records with recipients that were bounced, and the dsn_text why.
58 /* bounce_append() appends a dsn_text for non-delivery to the
59 /* bounce log for the named recipient, updates the address
60 /* verification service, or updates a message delivery record
61 /* on request by the sender. The flags argument determines
62 /* the action.
64 /* bounce_flush() actually bounces the specified message to
65 /* the specified sender, including the bounce log that was
66 /* built with bounce_append(). The bounce logfile is removed
67 /* upon successful completion.
69 /* bounce_flush_verp() is like bounce_flush(), but sends one
70 /* notification per recipient, with the failed recipient encoded
71 /* into the sender address.
73 /* bounce_one() bounces one recipient and immediately sends a
74 /* notification to the sender. This procedure does not append
75 /* the recipient and dsn_text to the per-message bounce log, and
76 /* should be used when a delivery agent changes the error
77 /* return address in a manner that depends on the recipient
78 /* address.
80 /* Arguments:
81 /* .IP flags
82 /* The bitwise OR of zero or more of the following (specify
83 /* BOUNCE_FLAG_NONE to request no special processing):
84 /* .RS
85 /* .IP BOUNCE_FLAG_CLEAN
86 /* Delete the bounce log in case of an error (as in: pretend
87 /* that we never even tried to bounce this message).
88 /* .IP BOUNCE_FLAG_DELRCPT
89 /* When specified with a flush request, request that
90 /* recipients be deleted from the queue file.
92 /* Note: the bounce daemon ignores this request when the
93 /* recipient queue file offset is <= 0.
94 /* .IP DEL_REQ_FLAG_MTA_VRFY
95 /* The message is an MTA-requested address verification probe.
96 /* Update the address verification database instead of bouncing
97 /* mail.
98 /* .IP DEL_REQ_FLAG_USR_VRFY
99 /* The message is a user-requested address expansion probe.
100 /* Update the message delivery record instead of bouncing mail.
101 /* .IP DEL_REQ_FLAG_RECORD
102 /* This is a normal message with logged delivery. Update the
103 /* message delivery record and bounce the mail.
104 /* .RE
105 /* .IP queue
106 /* The message queue name of the original message file.
107 /* .IP id
108 /* The message queue id if the original message file. The bounce log
109 /* file has the same name as the original message file.
110 /* .IP stats
111 /* Time stamps from different message delivery stages
112 /* and session reuse count.
113 /* .IP rcpt
114 /* Recipient information. See recipient_list(3).
115 /* .IP relay
116 /* Name of the host that the message could not be delivered to.
117 /* This information is used for syslogging only.
118 /* .IP encoding
119 /* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}.
120 /* .IP sender
121 /* The sender envelope address.
122 /* .IP dsn_envid
123 /* Optional DSN envelope ID.
124 /* .IP dsn_ret
125 /* Optional DSN return full/headers option.
126 /* .IP dsn
127 /* Delivery status. See dsn(3). The specified action is ignored.
128 /* .IP verp_delims
129 /* VERP delimiter characters, used when encoding the failed
130 /* sender into the envelope sender address.
131 /* DIAGNOSTICS
132 /* In case of success, these functions log the action, and return a
133 /* zero value. Otherwise, the functions return a non-zero result,
134 /* and when BOUNCE_FLAG_CLEAN is disabled, log that message
135 /* delivery is deferred.
136 /* BUGS
137 /* Should be replaced by routines with an attribute-value based
138 /* interface instead of an interface that uses a rigid argument list.
139 /* LICENSE
140 /* .ad
141 /* .fi
142 /* The Secure Mailer license must be distributed with this software.
143 /* AUTHOR(S)
144 /* Wietse Venema
145 /* IBM T.J. Watson Research
146 /* P.O. Box 704
147 /* Yorktown Heights, NY 10598, USA
148 /*--*/
150 /* System library. */
152 #include <sys_defs.h>
153 #include <string.h>
155 /* Utility library. */
157 #include <msg.h>
158 #include <vstring.h>
159 #include <mymalloc.h>
161 /* Global library. */
163 #include <mail_params.h>
164 #include <mail_proto.h>
165 #include <log_adhoc.h>
166 #include <dsn_util.h>
167 #include <rcpt_print.h>
168 #include <dsn_print.h>
169 #include <verify.h>
170 #include <defer.h>
171 #include <trace.h>
172 #include <bounce.h>
174 /* bounce_append - append dsn_text to per-message bounce log */
176 int bounce_append(int flags, const char *id, MSG_STATS *stats,
177 RECIPIENT *rcpt, const char *relay,
178 DSN *dsn)
180 DSN my_dsn = *dsn;
181 int status;
184 * Sanity check. If we're really confident, change this into msg_panic
185 * (remember, this information may be under control by a hostile server).
187 if (my_dsn.status[0] != '5' || !dsn_valid(my_dsn.status)) {
188 msg_warn("bounce_append: ignoring dsn code \"%s\"", my_dsn.status);
189 my_dsn.status = "5.0.0";
193 * MTA-requested address verification information is stored in the verify
194 * service database.
196 if (flags & DEL_REQ_FLAG_MTA_VRFY) {
197 my_dsn.action = "undeliverable";
198 status = verify_append(id, stats, rcpt, relay, &my_dsn,
199 DEL_RCPT_STAT_BOUNCE);
200 return (status);
204 * User-requested address verification information is logged and mailed
205 * to the requesting user.
207 if (flags & DEL_REQ_FLAG_USR_VRFY) {
208 my_dsn.action = "undeliverable";
209 status = trace_append(flags, id, stats, rcpt, relay, &my_dsn);
210 return (status);
214 * Normal (well almost) delivery. When we're pretending that we can't
215 * bounce, don't create a defer log file when we wouldn't keep the bounce
216 * log file. That's a lot of negatives in one sentence.
218 else if (var_soft_bounce && (flags & BOUNCE_FLAG_CLEAN)) {
219 return (-1);
223 * Normal mail delivery. May also send a delivery record to the user.
225 * XXX DSN We write all recipients to the bounce logfile regardless of DSN
226 * NOTIFY options, because those options don't apply to postmaster
227 * notifications.
229 else {
230 char *my_status = mystrdup(my_dsn.status);
231 const char *log_status = var_soft_bounce ? "SOFTBOUNCE" : "bounced";
234 * Supply default action.
236 my_dsn.status = my_status;
237 if (var_soft_bounce) {
238 my_status[0] = '4';
239 my_dsn.action = "delayed";
240 } else {
241 my_dsn.action = "failed";
244 if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ?
245 var_defer_service : var_bounce_service,
246 ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND,
247 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
248 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
249 ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt,
250 ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn,
251 ATTR_TYPE_END) == 0
252 && ((flags & DEL_REQ_FLAG_RECORD) == 0
253 || trace_append(flags, id, stats, rcpt, relay,
254 &my_dsn) == 0)) {
255 log_adhoc(id, stats, rcpt, relay, &my_dsn, log_status);
256 status = (var_soft_bounce ? -1 : 0);
257 } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
258 VSTRING *junk = vstring_alloc(100);
260 my_dsn.status = "4.3.0";
261 vstring_sprintf(junk, "%s or %s service failure",
262 var_bounce_service, var_trace_service);
263 my_dsn.reason = vstring_str(junk);
264 status = defer_append(flags, id, stats, rcpt, relay, &my_dsn);
265 vstring_free(junk);
266 } else {
267 status = -1;
269 myfree(my_status);
270 return (status);
274 /* bounce_flush - flush the bounce log and deliver to the sender */
276 int bounce_flush(int flags, const char *queue, const char *id,
277 const char *encoding, const char *sender,
278 const char *dsn_envid, int dsn_ret)
282 * When we're pretending that we can't bounce, don't send a bounce
283 * message.
285 if (var_soft_bounce)
286 return (-1);
287 if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
288 ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH,
289 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
290 ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
291 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
292 ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
293 ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
294 ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
295 ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret,
296 ATTR_TYPE_END) == 0) {
297 return (0);
298 } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
299 msg_info("%s: status=deferred (bounce failed)", id);
300 return (-1);
301 } else {
302 return (-1);
306 /* bounce_flush_verp - verpified notification */
308 int bounce_flush_verp(int flags, const char *queue, const char *id,
309 const char *encoding, const char *sender,
310 const char *dsn_envid, int dsn_ret,
311 const char *verp_delims)
315 * When we're pretending that we can't bounce, don't send a bounce
316 * message.
318 if (var_soft_bounce)
319 return (-1);
320 if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
321 ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_VERP,
322 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
323 ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
324 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
325 ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
326 ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
327 ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
328 ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret,
329 ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims,
330 ATTR_TYPE_END) == 0) {
331 return (0);
332 } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
333 msg_info("%s: status=deferred (bounce failed)", id);
334 return (-1);
335 } else {
336 return (-1);
340 /* bounce_one - send notice for one recipient */
342 int bounce_one(int flags, const char *queue, const char *id,
343 const char *encoding, const char *sender,
344 const char *dsn_envid, int dsn_ret,
345 MSG_STATS *stats, RECIPIENT *rcpt,
346 const char *relay, DSN *dsn)
348 DSN my_dsn = *dsn;
349 int status;
352 * Sanity check.
354 if (my_dsn.status[0] != '5' || !dsn_valid(my_dsn.status)) {
355 msg_warn("bounce_one: ignoring dsn code \"%s\"", my_dsn.status);
356 my_dsn.status = "5.0.0";
360 * MTA-requested address verification information is stored in the verify
361 * service database.
363 if (flags & DEL_REQ_FLAG_MTA_VRFY) {
364 my_dsn.action = "undeliverable";
365 status = verify_append(id, stats, rcpt, relay, &my_dsn,
366 DEL_RCPT_STAT_BOUNCE);
367 return (status);
371 * User-requested address verification information is logged and mailed
372 * to the requesting user.
374 if (flags & DEL_REQ_FLAG_USR_VRFY) {
375 my_dsn.action = "undeliverable";
376 status = trace_append(flags, id, stats, rcpt, relay, &my_dsn);
377 return (status);
381 * When we're not bouncing, then use the standard multi-recipient logfile
382 * based procedure.
384 else if (var_soft_bounce) {
385 return (bounce_append(flags, id, stats, rcpt, relay, &my_dsn));
389 * Normal mail delivery. May also send a delivery record to the user.
391 * XXX DSN We send all recipients regardless of DSN NOTIFY options, because
392 * those options don't apply to postmaster notifications.
394 else {
397 * Supply default action.
399 my_dsn.action = "failed";
401 if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
402 ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_ONE,
403 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
404 ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
405 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
406 ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
407 ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
408 ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
409 ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret,
410 ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt,
411 ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn,
412 ATTR_TYPE_END) == 0
413 && ((flags & DEL_REQ_FLAG_RECORD) == 0
414 || trace_append(flags, id, stats, rcpt, relay,
415 &my_dsn) == 0)) {
416 log_adhoc(id, stats, rcpt, relay, &my_dsn, "bounced");
417 status = 0;
418 } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
419 VSTRING *junk = vstring_alloc(100);
421 my_dsn.status = "4.3.0";
422 vstring_sprintf(junk, "%s or %s service failure",
423 var_bounce_service, var_trace_service);
424 my_dsn.reason = vstring_str(junk);
425 status = defer_append(flags, id, stats, rcpt, relay, &my_dsn);
426 vstring_free(junk);
427 } else {
428 status = -1;
430 return (status);