Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
qmgr_active.c
[詳解]
1 /*++
2 /* NAME
3 /* qmgr_active 3
4 /* SUMMARY
5 /* active queue management
6 /* SYNOPSIS
7 /* #include "qmgr.h"
8 /*
9 /* void qmgr_active_feed(scan_info, queue_id)
10 /* QMGR_SCAN *scan_info;
11 /* const char *queue_id;
12 /*
13 /* void qmgr_active_drain()
14 /*
15 /* int qmgr_active_done(message)
16 /* QMGR_MESSAGE *message;
17 /* DESCRIPTION
18 /* These functions maintain the active message queue: the set
19 /* of messages that the queue manager is actually working on.
20 /* The active queue is limited in size. Messages are drained
21 /* from the active queue by allocating a delivery process and
22 /* by delivering mail via that process. Messages leak into the
23 /* active queue only when the active queue is small enough.
24 /* Damaged message files are saved to the "corrupt" directory.
25 /*
26 /* qmgr_active_feed() inserts the named message file into
27 /* the active queue. Message files with the wrong name or
28 /* with other wrong properties are skipped but not removed.
29 /* The following queue flags are recognized, other flags being
30 /* ignored:
31 /* .IP QMGR_SCAN_ALL
32 /* Examine all queue files. Normally, deferred queue files with
33 /* future time stamps are ignored, and incoming queue files with
34 /* future time stamps are frowned upon.
35 /* .PP
36 /* qmgr_active_drain() allocates one delivery process.
37 /* Process allocation is asynchronous. Once the delivery
38 /* process is available, an attempt is made to deliver
39 /* a message via it. Message delivery is asynchronous, too.
40 /*
41 /* qmgr_active_done() deals with a message after delivery
42 /* has been tried for all in-core recipients. If the message
43 /* was bounced, a bounce message is sent to the sender, or
44 /* to the Errors-To: address if one was specified.
45 /* If there are more on-file recipients, a new batch of
46 /* in-core recipients is read from the queue file. Otherwise,
47 /* if a delivery agent marked the queue file as corrupt,
48 /* the queue file is moved to the "corrupt" queue (surprise);
49 /* if at least one delivery failed, the message is moved
50 /* to the deferred queue. The time stamps of a deferred queue
51 /* file are set to the nearest wakeup time of its recipient
52 /* sites (if delivery failed due to a problem with a next-hop
53 /* host), are set into the future by the amount of time the
54 /* message was queued (per-message exponential backoff), or are set
55 /* into the future by a minimal backoff time, whichever is more.
56 /* The minimal_backoff_time parameter specifies the minimal
57 /* amount of time between delivery attempts; maximal_backoff_time
58 /* specifies an upper limit.
59 /* DIAGNOSTICS
60 /* Fatal: queue file access failures, out of memory.
61 /* Panic: interface violations, internal consistency errors.
62 /* Warnings: corrupt message file. A corrupt message is saved
63 /* to the "corrupt" queue for further inspection.
64 /* LICENSE
65 /* .ad
66 /* .fi
67 /* The Secure Mailer license must be distributed with this software.
68 /* AUTHOR(S)
69 /* Wietse Venema
70 /* IBM T.J. Watson Research
71 /* P.O. Box 704
72 /* Yorktown Heights, NY 10598, USA
73 /*--*/
74 
75 /* System library. */
76 
77 #include <sys_defs.h>
78 #include <sys/stat.h>
79 #include <dirent.h>
80 #include <stdlib.h>
81 #include <unistd.h>
82 #include <string.h>
83 #include <utime.h>
84 #include <errno.h>
85 
86 #ifndef S_IRWXU /* What? no POSIX system? */
87 #define S_IRWXU 0700
88 #endif
89 
90 /* Utility library. */
91 
92 #include <msg.h>
93 #include <events.h>
94 #include <mymalloc.h>
95 #include <vstream.h>
96 #include <warn_stat.h>
97 
98 /* Global library. */
99 
100 #include <mail_params.h>
101 #include <mail_open_ok.h>
102 #include <mail_queue.h>
103 #include <recipient_list.h>
104 #include <bounce.h>
105 #include <defer.h>
106 #include <trace.h>
107 #include <abounce.h>
108 #include <rec_type.h>
109 #include <qmgr_user.h>
110 
111 /* Application-specific. */
112 
113 #include "qmgr.h"
114 
115  /*
116  * A bunch of call-back routines.
117  */
118 static void qmgr_active_done_2_bounce_flush(int, void *);
119 static void qmgr_active_done_2_generic(QMGR_MESSAGE *);
120 static void qmgr_active_done_25_trace_flush(int, void *);
121 static void qmgr_active_done_25_generic(QMGR_MESSAGE *);
122 static void qmgr_active_done_3_defer_flush(int, void *);
123 static void qmgr_active_done_3_defer_warn(int, void *);
124 static void qmgr_active_done_3_generic(QMGR_MESSAGE *);
125 
126 /* qmgr_active_corrupt - move corrupted file out of the way */
127 
128 static void qmgr_active_corrupt(const char *queue_id)
129 {
130  const char *myname = "qmgr_active_corrupt";
131 
133  if (errno != ENOENT)
134  msg_fatal("%s: save corrupt file queue %s id %s: %m",
135  myname, MAIL_QUEUE_ACTIVE, queue_id);
136  } else {
137  msg_warn("saving corrupt file \"%s\" from queue \"%s\" to queue \"%s\"",
139  }
140 }
141 
142 /* qmgr_active_defer - defer queue file */
143 
144 static void qmgr_active_defer(const char *queue_name, const char *queue_id,
145  const char *dest_queue, int delay)
146 {
147  const char *myname = "qmgr_active_defer";
148  const char *path;
149  struct utimbuf tbuf;
150 
151  if (msg_verbose)
152  msg_info("wakeup %s after %ld secs", queue_id, (long) delay);
153 
154  tbuf.actime = tbuf.modtime = event_time() + delay;
155  path = mail_queue_path((VSTRING *) 0, queue_name, queue_id);
156  if (utime(path, &tbuf) < 0 && errno != ENOENT)
157  msg_fatal("%s: update %s time stamps: %m", myname, path);
158  if (mail_queue_rename(queue_id, queue_name, dest_queue)) {
159  if (errno != ENOENT)
160  msg_fatal("%s: rename %s from %s to %s: %m", myname,
161  queue_id, queue_name, dest_queue);
162  msg_warn("%s: rename %s from %s to %s: %m", myname,
163  queue_id, queue_name, dest_queue);
164  } else if (msg_verbose) {
165  msg_info("%s: defer %s", myname, queue_id);
166  }
167 }
168 
169 /* qmgr_active_feed - feed one message into active queue */
170 
171 int qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
172 {
173  const char *myname = "qmgr_active_feed";
174  QMGR_MESSAGE *message;
175  struct stat st;
176  const char *path;
177 
178  if (strcmp(scan_info->queue, MAIL_QUEUE_ACTIVE) == 0)
179  msg_panic("%s: bad queue %s", myname, scan_info->queue);
180  if (msg_verbose)
181  msg_info("%s: queue %s", myname, scan_info->queue);
182 
183  /*
184  * Make sure this is something we are willing to open.
185  */
186  if (mail_open_ok(scan_info->queue, queue_id, &st, &path) == MAIL_OPEN_NO)
187  return (0);
188 
189  if (msg_verbose)
190  msg_info("%s: %s", myname, path);
191 
192  /*
193  * Skip files that have time stamps into the future. They need to cool
194  * down. Incoming and deferred files can have future time stamps.
195  */
196  if ((scan_info->flags & QMGR_SCAN_ALL) == 0
197  && st.st_mtime > time((time_t *) 0) + 1) {
198  if (msg_verbose)
199  msg_info("%s: skip %s (%ld seconds)", myname, queue_id,
200  (long) (st.st_mtime - event_time()));
201  return (0);
202  }
203 
204  /*
205  * Move the message to the active queue. File access errors are fatal.
206  */
207  if (mail_queue_rename(queue_id, scan_info->queue, MAIL_QUEUE_ACTIVE)) {
208  if (errno != ENOENT)
209  msg_fatal("%s: %s: rename from %s to %s: %m", myname,
210  queue_id, scan_info->queue, MAIL_QUEUE_ACTIVE);
211  msg_warn("%s: %s: rename from %s to %s: %m", myname,
212  queue_id, scan_info->queue, MAIL_QUEUE_ACTIVE);
213  return (0);
214  }
215 
216  /*
217  * Extract envelope information: sender and recipients. At this point,
218  * mail addresses have been processed by the cleanup service so they
219  * should be in canonical form. Generate requests to deliver this
220  * message.
221  *
222  * Throwing away queue files seems bad, especially when they made it this
223  * far into the mail system. Therefore we save bad files to a separate
224  * directory for further inspection.
225  *
226  * After queue manager restart it is possible that a queue file is still
227  * being delivered. In that case (the file is locked), defer delivery by
228  * a minimal amount of time.
229  */
230 #define QMGR_FLUSH_AFTER (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP)
231 
232  if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id,
233  (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
234  scan_info->flags | QMGR_FLUSH_AFTER :
235  scan_info->flags,
236  (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
237  st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE :
238  0)) == 0) {
239  qmgr_active_corrupt(queue_id);
240  return (0);
241  } else if (message == QMGR_MESSAGE_LOCKED) {
242  qmgr_active_defer(MAIL_QUEUE_ACTIVE, queue_id, MAIL_QUEUE_INCOMING, 60);
243  return (0);
244  } else {
245 
246  /*
247  * Special case if all recipients were already delivered. Send any
248  * bounces and clean up.
249  */
250  if (message->refcount == 0)
251  qmgr_active_done(message);
252  return (1);
253  }
254 }
255 
256 /* qmgr_active_done - dispose of message after recipients have been tried */
257 
259 {
260  const char *myname = "qmgr_active_done";
261  struct stat st;
262 
263  if (msg_verbose)
264  msg_info("%s: %s", myname, message->queue_id);
265 
266  /*
267  * During a previous iteration, an attempt to bounce this message may
268  * have failed, so there may still be a bounce log lying around. XXX By
269  * groping around in the bounce queue, we're trespassing on the bounce
270  * service's territory. But doing so is more robust than depending on the
271  * bounce daemon to do the lookup for us, and for us to do the deleting
272  * after we have received a successful status from the bounce service.
273  * The bounce queue directory blocks are most likely in memory anyway. If
274  * these lookups become a performance problem we will have to build an
275  * in-core cache into the bounce daemon.
276  *
277  * Don't bounce when the bounce log is empty. The bounce process obviously
278  * failed, and the delivery agent will have requested that the message be
279  * deferred.
280  *
281  * Bounces are sent asynchronously to avoid stalling while the cleanup
282  * daemon waits for the qmgr to accept the "new mail" trigger.
283  *
284  * See also code in cleanup_bounce.c.
285  */
286  if (stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_BOUNCE, message->queue_id), &st) == 0) {
287  if (st.st_size == 0) {
289  msg_fatal("remove %s %s: %m",
290  MAIL_QUEUE_BOUNCE, message->queue_id);
291  } else {
292  if (msg_verbose)
293  msg_info("%s: bounce %s", myname, message->queue_id);
294  if (message->verp_delims == 0 || var_verp_bounce_off)
296  message->queue_name,
297  message->queue_id,
298  message->encoding,
299  message->smtputf8,
300  message->sender,
301  message->dsn_envid,
302  message->dsn_ret,
303  qmgr_active_done_2_bounce_flush,
304  (void *) message);
305  else
307  message->queue_name,
308  message->queue_id,
309  message->encoding,
310  message->smtputf8,
311  message->sender,
312  message->dsn_envid,
313  message->dsn_ret,
314  message->verp_delims,
315  qmgr_active_done_2_bounce_flush,
316  (void *) message);
317  return;
318  }
319  }
320 
321  /*
322  * Asynchronous processing does not reach this point.
323  */
324  qmgr_active_done_2_generic(message);
325 }
326 
327 /* qmgr_active_done_2_bounce_flush - process abounce_flush() status */
328 
329 static void qmgr_active_done_2_bounce_flush(int status, void *context)
330 {
331  QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
332 
333  /*
334  * Process abounce_flush() status and continue processing.
335  */
336  message->flags |= status;
337  qmgr_active_done_2_generic(message);
338 }
339 
340 /* qmgr_active_done_2_generic - continue processing */
341 
342 static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
343 {
344  const char *path;
345  struct stat st;
346 
347  /*
348  * A delivery agent marks a queue file as corrupt by changing its
349  * attributes, and by pretending that delivery was deferred.
350  */
351  if (message->flags
352  && mail_open_ok(MAIL_QUEUE_ACTIVE, message->queue_id, &st, &path) == MAIL_OPEN_NO) {
353  qmgr_active_corrupt(message->queue_id);
354  qmgr_message_free(message);
355  return;
356  }
357 
358  /*
359  * If we did not read all recipients from this file, go read some more,
360  * but remember whether some recipients have to be tried again.
361  *
362  * Throwing away queue files seems bad, especially when they made it this
363  * far into the mail system. Therefore we save bad files to a separate
364  * directory for further inspection by a human being.
365  */
366  if (message->rcpt_offset > 0) {
367  if (qmgr_message_realloc(message) == 0) {
368  qmgr_active_corrupt(message->queue_id);
369  qmgr_message_free(message);
370  } else {
371  if (message->refcount == 0)
372  qmgr_active_done(message); /* recurse for consistency */
373  }
374  return;
375  }
376 
377  /*
378  * XXX With multi-recipient mail, some recipients may have NOTIFY=SUCCESS
379  * and others not. Depending on what subset of recipients are delivered,
380  * a trace file may or may not be created. Even when the last partial
381  * delivery attempt had no NOTIFY=SUCCESS recipients, a trace file may
382  * still exist from a previous partial delivery attempt. So as long as
383  * any recipient has NOTIFY=SUCCESS we have to always look for the trace
384  * file and be prepared for the file not to exist.
385  *
386  * See also comments in bounce/bounce_notify_util.c.
387  */
390  || (message->rflags & QMGR_READ_FLAG_NOTIFY_SUCCESS)) {
391  atrace_flush(message->tflags,
392  message->queue_name,
393  message->queue_id,
394  message->encoding,
395  message->smtputf8,
396  message->sender,
397  message->dsn_envid,
398  message->dsn_ret,
399  qmgr_active_done_25_trace_flush,
400  (void *) message);
401  return;
402  }
403 
404  /*
405  * Asynchronous processing does not reach this point.
406  */
407  qmgr_active_done_25_generic(message);
408 }
409 
410 /* qmgr_active_done_25_trace_flush - continue after atrace_flush() completion */
411 
412 static void qmgr_active_done_25_trace_flush(int status, void *context)
413 {
414  QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
415 
416  /*
417  * Process atrace_flush() status and continue processing.
418  */
419  if (status == 0 && message->tflags_offset)
420  qmgr_message_kill_record(message, message->tflags_offset);
421  message->flags |= status;
422  qmgr_active_done_25_generic(message);
423 }
424 
425 /* qmgr_active_done_25_generic - continue processing */
426 
427 static void qmgr_active_done_25_generic(QMGR_MESSAGE *message)
428 {
429  const char *myname = "qmgr_active_done_25_generic";
430 
431  /*
432  * If we get to this point we have tried all recipients for this message.
433  * If the message is too old, try to bounce it.
434  *
435  * Bounces are sent asynchronously to avoid stalling while the cleanup
436  * daemon waits for the qmgr to accept the "new mail" trigger.
437  */
438  if (message->flags) {
439  if (event_time() >= message->create_time +
440  (*message->sender ? var_max_queue_time : var_dsn_queue_time)) {
441  msg_info("%s: from=<%s>, status=expired, returned to sender",
442  message->queue_id, message->sender);
443  if (message->verp_delims == 0 || var_verp_bounce_off)
445  message->queue_name,
446  message->queue_id,
447  message->encoding,
448  message->smtputf8,
449  message->sender,
450  message->dsn_envid,
451  message->dsn_ret,
452  qmgr_active_done_3_defer_flush,
453  (void *) message);
454  else
456  message->queue_name,
457  message->queue_id,
458  message->encoding,
459  message->smtputf8,
460  message->sender,
461  message->dsn_envid,
462  message->dsn_ret,
463  message->verp_delims,
464  qmgr_active_done_3_defer_flush,
465  (void *) message);
466  return;
467  } else if (message->warn_time > 0
468  && event_time() >= message->warn_time - 1) {
469  if (msg_verbose)
470  msg_info("%s: sending defer warning for %s", myname, message->queue_id);
472  message->queue_name,
473  message->queue_id,
474  message->encoding,
475  message->smtputf8,
476  message->sender,
477  message->dsn_envid,
478  message->dsn_ret,
479  qmgr_active_done_3_defer_warn,
480  (void *) message);
481  return;
482  }
483  }
484 
485  /*
486  * Asynchronous processing does not reach this point.
487  */
488  qmgr_active_done_3_generic(message);
489 }
490 
491 /* qmgr_active_done_3_defer_warn - continue after adefer_warn() completion */
492 
493 static void qmgr_active_done_3_defer_warn(int status, void *context)
494 {
495  QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
496 
497  /*
498  * Process adefer_warn() completion status and continue processing.
499  */
500  if (status == 0)
501  qmgr_message_update_warn(message);
502  qmgr_active_done_3_generic(message);
503 }
504 
505 /* qmgr_active_done_3_defer_flush - continue after adefer_flush() completion */
506 
507 static void qmgr_active_done_3_defer_flush(int status, void *context)
508 {
509  QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
510 
511  /*
512  * Process adefer_flush() status and continue processing.
513  */
514  message->flags = status;
515  qmgr_active_done_3_generic(message);
516 }
517 
518 /* qmgr_active_done_3_generic - continue processing */
519 
520 static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
521 {
522  const char *myname = "qmgr_active_done_3_generic";
523  int delay;
524 
525  /*
526  * Some recipients need to be tried again. Move the queue file time
527  * stamps into the future by the amount of time that the message is
528  * delayed, and move the message to the deferred queue. Impose minimal
529  * and maximal backoff times.
530  *
531  * Since we look at actual time in queue, not time since last delivery
532  * attempt, backoff times will be distributed. However, we can still see
533  * spikes in delivery activity because the interval between deferred
534  * queue scans is finite.
535  */
536  if (message->flags) {
537  if (message->create_time > 0) {
538  delay = event_time() - message->create_time;
539  if (delay > var_max_backoff_time)
540  delay = var_max_backoff_time;
541  if (delay < var_min_backoff_time)
542  delay = var_min_backoff_time;
543  } else {
544  delay = var_min_backoff_time;
545  }
546  qmgr_active_defer(message->queue_name, message->queue_id,
547  MAIL_QUEUE_DEFERRED, delay);
548  }
549 
550  /*
551  * All recipients done. Remove the queue file.
552  */
553  else {
554  if (mail_queue_remove(message->queue_name, message->queue_id)) {
555  if (errno != ENOENT)
556  msg_fatal("%s: remove %s from %s: %m", myname,
557  message->queue_id, message->queue_name);
558  msg_warn("%s: remove %s from %s: %m", myname,
559  message->queue_id, message->queue_name);
560  } else {
561  /* Same format as logged by postsuper. */
562  msg_info("%s: removed", message->queue_id);
563  }
564  }
565 
566  /*
567  * Finally, delete the in-core message structure.
568  */
569  qmgr_message_free(message);
570 }
571 
572 /* qmgr_active_drain - drain active queue by allocating a delivery process */
573 
575 {
576  QMGR_TRANSPORT *transport;
577 
578  /*
579  * Allocate one delivery process for every transport with pending mail.
580  * The process allocation completes asynchronously.
581  */
582  while ((transport = qmgr_transport_select()) != 0) {
583  if (msg_verbose)
584  msg_info("qmgr_active_drain: allocate %s", transport->name);
586  }
587 }
int msg_verbose
Definition: msg.c:177
void abounce_flush_verp(int flags, const char *queue, const char *id, const char *encoding, int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, const char *verp, ABOUNCE_FN callback, void *context)
Definition: abounce.c:312
#define BOUNCE_FLAG_KEEP
Definition: bounce.h:67
#define QMGR_FLUSH_AFTER
void abounce_flush(int flags, const char *queue, const char *id, const char *encoding, int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, void *context)
Definition: abounce.c:383
void qmgr_message_free(QMGR_MESSAGE *)
#define QMGR_READ_FLAG_NOTIFY_SUCCESS
Definition: qmgr_user.h:29
#define MAIL_QUEUE_BOUNCE
Definition: mail_queue.h:35
char * queue_id
Definition: qmgr.h:298
int smtputf8
Definition: qmgr.h:303
void qmgr_message_kill_record(QMGR_MESSAGE *, long)
Definition: qmgr_message.c:868
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define MAIL_QUEUE_ACTIVE
Definition: mail_queue.h:31
#define stat(p, s)
Definition: warn_stat.h:18
#define QMGR_SCAN_ALL
Definition: qmgr.h:398
int var_max_backoff_time
Definition: qmgr.c:412
void atrace_flush(int flags, const char *queue, const char *id, const char *encoding, int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, void *context)
Definition: abounce.c:421
#define DEL_REQ_FLAG_USR_VRFY
#define MAIL_QUEUE_STAT_UNTHROTTLE
Definition: mail_queue.h:51
void qmgr_message_update_warn(QMGR_MESSAGE *)
Definition: qmgr_message.c:850
const char * mail_queue_path(VSTRING *buf, const char *queue_name, const char *queue_id)
Definition: mail_queue.c:204
int rflags
Definition: qmgr.h:287
long tflags_offset
Definition: qmgr.h:286
int flags
Definition: qmgr.h:283
QMGR_MESSAGE * qmgr_message_alloc(const char *, const char *, int, mode_t)
char * queue_name
Definition: qmgr.h:297
QMGR_MESSAGE * qmgr_message_realloc(QMGR_MESSAGE *)
void qmgr_active_done(QMGR_MESSAGE *message)
Definition: qmgr_active.c:258
void qmgr_active_drain(void)
Definition: qmgr_active.c:574
int qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
Definition: qmgr_active.c:171
int mail_queue_rename(const char *queue_id, const char *old_queue, const char *new_queue)
Definition: mail_queue.c:247
#define MAIL_QUEUE_INCOMING
Definition: mail_queue.h:30
int mail_open_ok(const char *queue_name, const char *queue_id, struct stat *statp, const char **path)
Definition: mail_open_ok.c:77
void msg_warn(const char *fmt,...)
Definition: msg.c:215
char * sender
Definition: qmgr.h:300
time_t warn_time
Definition: qmgr.h:295
long rcpt_offset
Definition: qmgr.h:310
#define MAIL_OPEN_NO
Definition: mail_open_ok.h:20
char * name
Definition: qmgr.h:155
void qmgr_deliver(QMGR_TRANSPORT *, VSTREAM *)
Definition: qmgr_deliver.c:374
char * dsn_envid
Definition: qmgr.h:301
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
int var_min_backoff_time
Definition: qmgr.c:411
int flags
Definition: qmgr.h:388
#define MAIL_QUEUE_DEFERRED
Definition: mail_queue.h:32
time_t event_time(void)
Definition: events.c:647
int mail_queue_remove(const char *queue_name, const char *queue_id)
Definition: mail_queue.c:274
char * queue
Definition: qmgr.h:387
void adefer_flush(int flags, const char *queue, const char *id, const char *encoding, int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, void *context)
Definition: abounce.c:396
void qmgr_transport_alloc(QMGR_TRANSPORT *, QMGR_TRANSPORT_ALLOC_NOTIFY)
QMGR_TRANSPORT * qmgr_transport_select(void)
#define MAIL_QUEUE_CORRUPT
Definition: mail_queue.h:36
time_t create_time
Definition: qmgr.h:292
void adefer_flush_verp(int flags, const char *queue, const char *id, const char *encoding, int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, const char *verp, ABOUNCE_FN callback, void *context)
Definition: abounce.c:326
int tflags
Definition: qmgr.h:285
#define QMGR_MESSAGE_LOCKED
Definition: qmgr.h:329
int var_dsn_queue_time
Definition: qmgr.c:414
char * verp_delims
Definition: qmgr.h:304
int var_verp_bounce_off
Definition: cleanup_init.c:152
#define DEL_REQ_FLAG_REC_DLY_SENT
void adefer_warn(int flags, const char *queue, const char *id, const char *encoding, int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, void *context)
Definition: abounce.c:409
int dsn_ret
Definition: qmgr.h:302
int var_max_queue_time
Definition: bounce.c:191
int refcount
Definition: qmgr.h:289
char * encoding
Definition: qmgr.h:299
#define DEL_REQ_FLAG_RECORD
void msg_info(const char *fmt,...)
Definition: msg.c:199