3
/* bounce_warn_service 3
5
/* send non-delivery report to sender, server side
7
/* #include "bounce_service.h"
9
/* int bounce_warn_service(flags, queue_name, queue_id, encoding, sender)
16
/* This module implements the server side of the bounce_warn()
17
/* (send delay notice) request. The logfile
18
/* is not removed, and a warning is sent instead of a bounce.
20
/* When a message bounces, a full copy is sent to the originator,
21
/* and an optional copy of the diagnostics with message headers is
22
/* sent to the postmaster. The result is non-zero when the operation
23
/* should be tried again.
25
/* When a bounce is sent, the sender address is the empty
26
/* address. When a bounce bounces, an optional double bounce
27
/* with the entire undeliverable mail is sent to the postmaster,
28
/* with as sender address the double bounce address.
30
/* Fatal error: error opening existing file. Warnings: corrupt
31
/* message file. A corrupt message is saved to the "corrupt"
32
/* queue for further inspection.
35
/* bounce(3) basic bounce service client interface
39
/* The Secure Mailer license must be distributed with this software.
42
/* IBM T.J. Watson Research
44
/* Yorktown Heights, NY 10598, USA
55
#ifdef STRCASECMP_IN_STRINGS_H
59
/* Utility library. */
63
#include <name_mask.h>
67
#include <mail_params.h>
68
#include <mail_queue.h>
69
#include <post_mail.h>
70
#include <mail_addr.h>
71
#include <mail_error.h>
73
/* Application-specific. */
75
#include "bounce_service.h"
77
#define STR vstring_str
79
/* bounce_warn_service - send a delayed mail notice */
81
int bounce_warn_service(int unused_flags, char *service, char *queue_name,
82
char *queue_id, char *encoding,
85
BOUNCE_INFO *bounce_info;
86
int bounce_status = 1;
87
int postmaster_status = 1;
89
int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
94
* Initialize. Open queue file, bounce log, etc.
96
bounce_info = bounce_mail_init(service, queue_name, queue_id,
97
encoding, BOUNCE_MSG_WARN);
99
#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
100
#define NULL_TRACE_FLAGS 0
101
#define BOUNCE_HEADERS 1
104
* The choice of sender address depends on the recipient address. For a
105
* single bounce (a non-delivery notification to the message originator),
106
* the sender address is the empty string. For a double bounce (typically
107
* a failed single bounce, or a postmaster notification that was produced
108
* by any of the mail processes) the sender address is defined by the
109
* var_double_bounce_sender configuration variable. When a double bounce
110
* cannot be delivered, the queue manager blackholes the resulting triple
115
* Double bounce failed. Never send a triple bounce.
117
* However, this does not prevent double bounces from bouncing on other
118
* systems. In order to cope with this, either the queue manager must
119
* recognize the double-bounce recipient address and discard mail, or
120
* every delivery agent must recognize the double-bounce sender address
121
* and substitute something else so mail does not come back at us.
123
if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) {
124
msg_warn("%s: undeliverable postmaster notification discarded",
130
* Single bounce failed. Optionally send a double bounce to postmaster.
132
#define ANY_BOUNCE (MAIL_ERROR_2BOUNCE | MAIL_ERROR_BOUNCE)
133
#define SKIP_IF_DELAY ((notify_mask & MAIL_ERROR_DELAY) == 0)
135
else if (*recipient == 0) {
139
postmaster = var_delay_rcpt;
140
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
142
CLEANUP_FLAG_MASK_INTERNAL,
143
NULL_TRACE_FLAGS)) != 0) {
146
* Double bounce to Postmaster. This is the last opportunity
147
* for this message to be delivered. Send the text with
148
* reason for the bounce, and the headers of the original
149
* message. Don't bother sending the boiler-plate text.
151
if (!bounce_header(bounce, bounce_info, postmaster)
152
&& bounce_diagnostic_log(bounce, bounce_info) == 0
153
&& bounce_header_dsn(bounce, bounce_info) == 0
154
&& bounce_diagnostic_dsn(bounce, bounce_info) == 0)
155
bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
156
bounce_status = post_mail_fclose(bounce);
162
* Non-bounce failed. Send a single bounce.
165
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
166
CLEANUP_FLAG_MASK_INTERNAL,
167
NULL_TRACE_FLAGS)) != 0) {
170
* Send the bounce message header, some boilerplate text that
171
* pretends that we are a polite mail system, the text with
172
* reason for the bounce, and a copy of the original message.
174
if (bounce_header(bounce, bounce_info, recipient) == 0
175
&& bounce_boilerplate(bounce, bounce_info) == 0
176
&& bounce_diagnostic_log(bounce, bounce_info) == 0
177
&& bounce_header_dsn(bounce, bounce_info) == 0
178
&& bounce_diagnostic_dsn(bounce, bounce_info) == 0)
179
bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
180
bounce_status = post_mail_fclose(bounce);
184
* Optionally, send a postmaster notice.
186
* This postmaster notice is not critical, so if it fails don't
187
* retransmit the bounce that we just generated, just log a warning.
189
#define WANT_IF_DELAY ((notify_mask & MAIL_ERROR_DELAY))
191
if (bounce_status == 0 && WANT_IF_DELAY
192
&& strcasecmp(recipient, mail_addr_double_bounce()) != 0) {
195
* Send the text with reason for the bounce, and the headers of
196
* the original message. Don't bother sending the boiler-plate
197
* text. This postmaster notice is not critical, so if it fails
198
* don't retransmit the bounce that we just generated, just log a
201
postmaster = var_delay_rcpt;
202
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
204
CLEANUP_FLAG_MASK_INTERNAL,
205
NULL_TRACE_FLAGS)) != 0) {
206
if (bounce_header(bounce, bounce_info, postmaster) == 0
207
&& bounce_diagnostic_log(bounce, bounce_info) == 0
208
&& bounce_header_dsn(bounce, bounce_info) == 0
209
&& bounce_diagnostic_dsn(bounce, bounce_info) == 0)
210
bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
211
postmaster_status = post_mail_fclose(bounce);
213
if (postmaster_status)
214
msg_warn("postmaster notice failed while bouncing to %s",
222
bounce_mail_free(bounce_info);
224
return (bounce_status);