5 /* bounce_warn_service 3
7 /* send non-delivery report to sender, server side
9 /* #include "bounce_service.h"
11 /* int bounce_warn_service(flags, queue_name, queue_id, encoding,
12 /* sender, envid, dsn_ret, templates)
20 /* BOUNCE_TEMPLATES *ts;
22 /* This module implements the server side of the bounce_warn()
23 /* (send delay notice) request. The logfile
24 /* is not removed, and a warning is sent instead of a bounce.
26 /* When a message bounces, a full copy is sent to the originator,
27 /* and an optional copy of the diagnostics with message headers is
28 /* sent to the postmaster. The result is non-zero when the operation
29 /* should be tried again.
31 /* When a bounce is sent, the sender address is the empty
32 /* address. When a bounce bounces, an optional double bounce
33 /* with the entire undeliverable mail is sent to the postmaster,
34 /* with as sender address the double bounce address.
36 /* Fatal error: error opening existing file.
39 /* bounce(3) basic bounce service client interface
43 /* The Secure Mailer license must be distributed with this software.
46 /* IBM T.J. Watson Research
48 /* Yorktown Heights, NY 10598, USA
59 #ifdef STRCASECMP_IN_STRINGS_H
63 /* Utility library. */
67 #include <name_mask.h>
71 #include <mail_params.h>
72 #include <mail_queue.h>
73 #include <post_mail.h>
74 #include <mail_addr.h>
75 #include <mail_error.h>
78 /* Application-specific. */
80 #include "bounce_service.h"
82 #define STR vstring_str
84 /* bounce_warn_service - send a delayed mail notice */
86 int bounce_warn_service(int unused_flags
, char *service
, char *queue_name
,
87 char *queue_id
, char *encoding
,
88 char *recipient
, char *dsn_envid
,
89 int dsn_ret
, BOUNCE_TEMPLATES
*ts
)
91 BOUNCE_INFO
*bounce_info
;
92 int bounce_status
= 1;
93 int postmaster_status
= 1;
95 int notify_mask
= name_mask(VAR_NOTIFY_CLASSES
, mail_error_masks
,
97 VSTRING
*new_id
= vstring_alloc(10);
102 * Initialize. Open queue file, bounce log, etc.
104 * XXX DSN This service produces RFC 3464-style "delayed mail" reports from
105 * information in the defer logfile. That same file is used for three
106 * different types of report:
108 * a) On-demand reports of all delayed deliveries by the mailq(1) command.
109 * This reports all recipients that have a transient delivery error.
111 * b) RFC 3464-style "delayed mail" notifications by the defer(8) service.
112 * This reports to the sender all recipients that have no DSN NOTIFY
113 * information (compatibility) and all recipients that have DSN
114 * NOTIFY=DELAY; this reports to postmaster all recipients, subject to
115 * notify_classes restrictions.
117 * c) RFC 3464-style bounce reports by the bounce(8) service when mail is
118 * too old. This reports to the sender all recipients that have no DSN
119 * NOTIFY information (compatibility) and all recipients that have DSN
120 * NOTIFY=FAILURE; this reports to postmaster all recipients, subject to
121 * notify_classes restrictions.
123 bounce_info
= bounce_mail_init(service
, queue_name
, queue_id
,
124 encoding
, dsn_envid
, ts
->delay
);
126 #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
127 #define NULL_TRACE_FLAGS 0
130 * The choice of sender address depends on the recipient address. For a
131 * single bounce (a non-delivery notification to the message originator),
132 * the sender address is the empty string. For a double bounce (typically
133 * a failed single bounce, or a postmaster notification that was produced
134 * by any of the mail processes) the sender address is defined by the
135 * var_double_bounce_sender configuration variable. When a double bounce
136 * cannot be delivered, the queue manager blackholes the resulting triple
141 * Double bounce failed. Never send a triple bounce.
143 * However, this does not prevent double bounces from bouncing on other
144 * systems. In order to cope with this, either the queue manager must
145 * recognize the double-bounce recipient address and discard mail, or
146 * every delivery agent must recognize the double-bounce sender address
147 * and substitute something else so mail does not come back at us.
149 if (strcasecmp(recipient
, mail_addr_double_bounce()) == 0) {
150 msg_warn("%s: undeliverable postmaster notification discarded",
156 * Single bounce failed. Optionally send a double bounce to postmaster,
157 * subject to notify_classes restrictions.
159 #define ANY_BOUNCE (MAIL_ERROR_2BOUNCE | MAIL_ERROR_BOUNCE)
160 #define SEND_POSTMASTER_DELAY_NOTICE (notify_mask & MAIL_ERROR_DELAY)
162 else if (*recipient
== 0) {
163 if (!SEND_POSTMASTER_DELAY_NOTICE
) {
166 postmaster
= var_delay_rcpt
;
167 if ((bounce
= post_mail_fopen_nowait(mail_addr_double_bounce(),
169 INT_FILT_MASK_BOUNCE
,
174 * Double bounce to Postmaster. This is the last opportunity
175 * for this message to be delivered. Send the text with
176 * reason for the bounce, and the headers of the original
177 * message. Don't bother sending the boiler-plate text.
180 if (!bounce_header(bounce
, bounce_info
, postmaster
,
182 && (count
= bounce_diagnostic_log(bounce
, bounce_info
,
183 DSN_NOTIFY_OVERRIDE
)) > 0
184 && bounce_header_dsn(bounce
, bounce_info
) == 0
185 && bounce_diagnostic_dsn(bounce
, bounce_info
,
186 DSN_NOTIFY_OVERRIDE
) > 0) {
187 bounce_original(bounce
, bounce_info
, DSN_RET_FULL
);
188 bounce_status
= post_mail_fclose(bounce
);
189 if (bounce_status
== 0)
190 msg_info("%s: postmaster delay notification: %s",
191 queue_id
, STR(new_id
));
193 (void) vstream_fclose(bounce
);
202 * Non-bounce failed. Send a single bounce, subject to DSN NOTIFY
206 if ((bounce
= post_mail_fopen_nowait(NULL_SENDER
, recipient
,
207 INT_FILT_MASK_BOUNCE
,
212 * Send the bounce message header, some boilerplate text that
213 * pretends that we are a polite mail system, the text with
214 * reason for the bounce, and a copy of the original message.
217 if (bounce_header(bounce
, bounce_info
, recipient
,
218 NO_POSTMASTER_COPY
) == 0
219 && bounce_boilerplate(bounce
, bounce_info
) == 0
220 && (count
= bounce_diagnostic_log(bounce
, bounce_info
,
221 DSN_NOTIFY_DELAY
)) > 0
222 && bounce_header_dsn(bounce
, bounce_info
) == 0
223 && bounce_diagnostic_dsn(bounce
, bounce_info
,
224 DSN_NOTIFY_DELAY
) > 0) {
225 bounce_original(bounce
, bounce_info
, DSN_RET_HDRS
);
226 bounce_status
= post_mail_fclose(bounce
);
227 if (bounce_status
== 0)
228 msg_info("%s: sender delay notification: %s",
229 queue_id
, STR(new_id
));
231 (void) vstream_fclose(bounce
);
238 * Optionally send a postmaster notice, subject to notify_classes
241 * This postmaster notice is not critical, so if it fails don't
242 * retransmit the bounce that we just generated, just log a warning.
244 if (bounce_status
== 0 && SEND_POSTMASTER_DELAY_NOTICE
245 && strcasecmp(recipient
, mail_addr_double_bounce()) != 0) {
248 * Send the text with reason for the bounce, and the headers of
249 * the original message. Don't bother sending the boiler-plate
250 * text. This postmaster notice is not critical, so if it fails
251 * don't retransmit the bounce that we just generated, just log a
254 postmaster
= var_delay_rcpt
;
255 if ((bounce
= post_mail_fopen_nowait(mail_addr_double_bounce(),
257 INT_FILT_MASK_BOUNCE
,
261 if (bounce_header(bounce
, bounce_info
, postmaster
,
262 POSTMASTER_COPY
) == 0
263 && (count
= bounce_diagnostic_log(bounce
, bounce_info
,
264 DSN_NOTIFY_OVERRIDE
)) > 0
265 && bounce_header_dsn(bounce
, bounce_info
) == 0
266 && bounce_diagnostic_dsn(bounce
, bounce_info
,
267 DSN_NOTIFY_OVERRIDE
) > 0) {
268 bounce_original(bounce
, bounce_info
, DSN_RET_HDRS
);
269 postmaster_status
= post_mail_fclose(bounce
);
270 if (postmaster_status
== 0)
271 msg_info("%s: postmaster delay notification: %s",
272 queue_id
, STR(new_id
));
274 (void) vstream_fclose(bounce
);
276 postmaster_status
= 0;
279 if (postmaster_status
)
280 msg_warn("%s: postmaster notice failed while warning %s",
281 queue_id
, recipient
);
288 bounce_mail_free(bounce_info
);
289 vstring_free(new_id
);
291 return (bounce_status
);