Postfix3.3.1
bounce_warn_service.c
[詳解]
1 /*++
2 /* NAME
3 /* bounce_warn_service 3
4 /* SUMMARY
5 /* send non-delivery report to sender, server side
6 /* SYNOPSIS
7 /* #include "bounce_service.h"
8 /*
9 /* int bounce_warn_service(flags, service, queue_name, queue_id,
10 /* encoding, smtputf8, sender, envid,
11 /* dsn_ret, templates)
12 /* int flags;
13 /* char *service;
14 /* char *queue_name;
15 /* char *queue_id;
16 /* char *encoding;
17 /* int smtputf8;
18 /* char *sender;
19 /* char *envid;
20 /* int dsn_ret;
21 /* BOUNCE_TEMPLATES *ts;
22 /* DESCRIPTION
23 /* This module implements the server side of the bounce_warn()
24 /* (send delay notice) request. The logfile
25 /* is not removed, and a warning is sent instead of a bounce.
26 /*
27 /* When a message bounces, a full copy is sent to the originator,
28 /* and an optional copy of the diagnostics with message headers is
29 /* sent to the postmaster. The result is non-zero when the operation
30 /* should be tried again.
31 /*
32 /* When a bounce is sent, the sender address is the empty
33 /* address. When a bounce bounces, an optional double bounce
34 /* with the entire undeliverable mail is sent to the postmaster,
35 /* with as sender address the double bounce address.
36 /* DIAGNOSTICS
37 /* Fatal error: error opening existing file.
38 /* BUGS
39 /* SEE ALSO
40 /* bounce(3) basic bounce service client interface
41 /* LICENSE
42 /* .ad
43 /* .fi
44 /* The Secure Mailer license must be distributed with this software.
45 /* AUTHOR(S)
46 /* Wietse Venema
47 /* IBM T.J. Watson Research
48 /* P.O. Box 704
49 /* Yorktown Heights, NY 10598, USA
50 /*--*/
51 
52 /* System library. */
53 
54 #include <sys_defs.h>
55 #include <fcntl.h>
56 #include <errno.h>
57 #include <string.h>
58 #include <ctype.h>
59 
60 /* Utility library. */
61 
62 #include <msg.h>
63 #include <vstream.h>
64 #include <name_mask.h>
65 #include <stringops.h>
66 
67 /* Global library. */
68 
69 #include <mail_params.h>
70 #include <mail_queue.h>
71 #include <post_mail.h>
72 #include <mail_addr.h>
73 #include <mail_error.h>
74 #include <dsn_mask.h>
75 #include <rec_type.h>
76 
77 /* Application-specific. */
78 
79 #include "bounce_service.h"
80 
81 #define STR vstring_str
82 
83 /* bounce_warn_service - send a delayed mail notice */
84 
85 int bounce_warn_service(int unused_flags, char *service, char *queue_name,
86  char *queue_id, char *encoding,
87  int smtputf8, char *recipient,
88  char *dsn_envid, int dsn_ret,
89  BOUNCE_TEMPLATES *ts)
90 {
91  BOUNCE_INFO *bounce_info;
92  int bounce_status = 1;
93  int postmaster_status = 1;
94  VSTREAM *bounce;
97  VSTRING *new_id = vstring_alloc(10);
98  char *postmaster;
99  int count;
100 
101  /*
102  * Initialize. Open queue file, bounce log, etc.
103  *
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:
107  *
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.
110  *
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.
116  *
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.
122  */
123  bounce_info = bounce_mail_init(service, queue_name, queue_id,
124  encoding, smtputf8, dsn_envid, ts->delay);
125 
126 #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
127 #define NULL_TRACE_FLAGS 0
128 
129  /*
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
137  * bounce message.
138  */
139 
140  /*
141  * Double bounce failed. Never send a triple bounce.
142  *
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.
148  */
149  if (strcasecmp_utf8(recipient, mail_addr_double_bounce()) == 0) {
150  msg_warn("%s: undeliverable postmaster notification discarded",
151  queue_id);
152  bounce_status = 0;
153  }
154 
155  /*
156  * Single bounce failed. Optionally send a double bounce to postmaster,
157  * subject to notify_classes restrictions.
158  */
159 #define ANY_BOUNCE (MAIL_ERROR_2BOUNCE | MAIL_ERROR_BOUNCE)
160 #define SEND_POSTMASTER_DELAY_NOTICE (notify_mask & MAIL_ERROR_DELAY)
161 
162  else if (*recipient == 0) {
164  bounce_status = 0;
165  } else {
166  postmaster = var_delay_rcpt;
168  postmaster,
171  smtputf8,
172  new_id)) != 0) {
173 
174  /*
175  * Double bounce to Postmaster. This is the last opportunity
176  * for this message to be delivered. Send the text with
177  * reason for the bounce, and the headers of the original
178  * message. Don't bother sending the boiler-plate text.
179  */
180  count = -1;
181  if (!bounce_header(bounce, bounce_info, postmaster,
183  && (count = bounce_diagnostic_log(bounce, bounce_info,
184  DSN_NOTIFY_OVERRIDE)) > 0
185  && bounce_header_dsn(bounce, bounce_info) == 0
186  && bounce_diagnostic_dsn(bounce, bounce_info,
187  DSN_NOTIFY_OVERRIDE) > 0) {
188  bounce_original(bounce, bounce_info, DSN_RET_FULL);
189  bounce_status = post_mail_fclose(bounce);
190  if (bounce_status == 0)
191  msg_info("%s: postmaster delay notification: %s",
192  queue_id, STR(new_id));
193  } else {
194  (void) vstream_fclose(bounce);
195  if (count == 0)
196  bounce_status = 0;
197  }
198  }
199  }
200  }
201 
202  /*
203  * Non-bounce failed. Send a single bounce, subject to DSN NOTIFY
204  * restrictions.
205  */
206  else {
207  if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
210  smtputf8,
211  new_id)) != 0) {
212 
213  /*
214  * Send the bounce message header, some boilerplate text that
215  * pretends that we are a polite mail system, the text with
216  * reason for the bounce, and a copy of the original message.
217  */
218  count = -1;
219  if (bounce_header(bounce, bounce_info, recipient,
220  NO_POSTMASTER_COPY) == 0
221  && bounce_boilerplate(bounce, bounce_info) == 0
222  && (count = bounce_diagnostic_log(bounce, bounce_info,
223  DSN_NOTIFY_DELAY)) > 0
224  && bounce_header_dsn(bounce, bounce_info) == 0
225  && bounce_diagnostic_dsn(bounce, bounce_info,
226  DSN_NOTIFY_DELAY) > 0) {
227  bounce_original(bounce, bounce_info, DSN_RET_HDRS);
228  bounce_status = post_mail_fclose(bounce);
229  if (bounce_status == 0)
230  msg_info("%s: sender delay notification: %s",
231  queue_id, STR(new_id));
232  } else {
233  (void) vstream_fclose(bounce);
234  if (count == 0)
235  bounce_status = 0;
236  }
237  }
238 
239  /*
240  * Optionally send a postmaster notice, subject to notify_classes
241  * restrictions.
242  *
243  * This postmaster notice is not critical, so if it fails don't
244  * retransmit the bounce that we just generated, just log a warning.
245  */
246  if (bounce_status == 0 && SEND_POSTMASTER_DELAY_NOTICE
247  && strcasecmp_utf8(recipient, mail_addr_double_bounce()) != 0) {
248 
249  /*
250  * Send the text with reason for the bounce, and the headers of
251  * the original message. Don't bother sending the boiler-plate
252  * text. This postmaster notice is not critical, so if it fails
253  * don't retransmit the bounce that we just generated, just log a
254  * warning.
255  */
256  postmaster = var_delay_rcpt;
258  postmaster,
261  smtputf8,
262  new_id)) != 0) {
263  count = -1;
264  if (bounce_header(bounce, bounce_info, postmaster,
265  POSTMASTER_COPY) == 0
266  && (count = bounce_diagnostic_log(bounce, bounce_info,
267  DSN_NOTIFY_OVERRIDE)) > 0
268  && bounce_header_dsn(bounce, bounce_info) == 0
269  && bounce_diagnostic_dsn(bounce, bounce_info,
270  DSN_NOTIFY_OVERRIDE) > 0) {
271  bounce_original(bounce, bounce_info, DSN_RET_HDRS);
272  postmaster_status = post_mail_fclose(bounce);
273  if (postmaster_status == 0)
274  msg_info("%s: postmaster delay notification: %s",
275  queue_id, STR(new_id));
276  } else {
277  (void) vstream_fclose(bounce);
278  if (count == 0)
279  postmaster_status = 0;
280  }
281  }
282  if (postmaster_status)
283  msg_warn("%s: postmaster notice failed while warning %s",
284  queue_id, recipient);
285  }
286  }
287 
288  /*
289  * Cleanup.
290  */
291  bounce_mail_free(bounce_info);
292  vstring_free(new_id);
293 
294  return (bounce_status);
295 }
int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info, int headers_only)
#define POSTMASTER_COPY
char * var_delay_rcpt
Definition: bounce.c:196
#define DSN_RET_HDRS
Definition: dsn_mask.h:18
#define DSN_NOTIFY_OVERRIDE
Definition: dsn_mask.h:58
int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info, const char *dest, int postmaster_copy)
const NAME_MASK mail_error_masks[]
Definition: mail_error.c:70
#define strcasecmp_utf8(s1, s2)
Definition: stringops.h:75
int bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info, int notify_filter)
VSTREAM * post_mail_fopen_nowait(const char *sender, const char *recipient, int source_class, int trace_flags, int utf8_flags, VSTRING *queue_id)
Definition: post_mail.c:293
char * var_notify_classes
Definition: bounce.c:193
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
#define MAIL_SRC_MASK_BOUNCE
Definition: mail_proto.h:81
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int post_mail_fclose(VSTREAM *cleanup)
Definition: post_mail.c:449
#define SEND_POSTMASTER_DELAY_NOTICE
#define name_mask(tag, table, str)
Definition: name_mask.h:49
#define DSN_RET_FULL
Definition: dsn_mask.h:17
int bounce_boilerplate(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
#define NULL_SENDER
int bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info, int notify_filter)
#define VAR_NOTIFY_CLASSES
Definition: mail_params.h:72
const char * mail_addr_double_bounce(void)
Definition: mail_addr.c:64
#define NO_POSTMASTER_COPY
BOUNCE_INFO * bounce_mail_init(const char *service, const char *queue_name, const char *queue_id, const char *encoding, int smtputf8, const char *dsn_envid, BOUNCE_TEMPLATE *template)
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
int bounce_warn_service(int unused_flags, char *service, char *queue_name, char *queue_id, char *encoding, int smtputf8, char *recipient, char *dsn_envid, int dsn_ret, BOUNCE_TEMPLATES *ts)
#define DSN_NOTIFY_DELAY
Definition: dsn_mask.h:46
#define NULL_TRACE_FLAGS
void bounce_mail_free(BOUNCE_INFO *bounce_info)
int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
#define STR
BOUNCE_TEMPLATE * delay
void msg_info(const char *fmt,...)
Definition: msg.c:199