]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.11-20251218
authorWietse Z Venema <wietse@porcupine.org>
Thu, 18 Dec 2025 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Fri, 19 Dec 2025 01:22:16 +0000 (12:22 +1100)
postfix/HISTORY
postfix/html/postqueue.1.html
postfix/man/man1/postqueue.1
postfix/src/global/abounce.c
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/postqueue/postqueue.c
postfix/src/postqueue/showq_compat.c
postfix/src/postqueue/showq_json.c
postfix/src/showq/showq.c

index 5ebd2dac78a0effcb3a6c44ce172fe52f0ed2bcc..4f1d8f8d9f9c06075f5e32cab8ad302695ad9050 100644 (file)
@@ -30179,3 +30179,19 @@ Apologies for any names omitted.
        bounce/bounce_warn_service.c.
 
        TODO: unit test coverage.
+
+20211218
+
+       Feature: the postqueue command now also lists recipients
+       in bounce logfiles (in JSON output, this uses a new object
+       member 'bounce_reason' instead of the existing 'delay_reason').
+       Such recipients have already been deleted from the message
+       queue file, but they are still pending the creation of a
+       non-delivery status notification message that will be
+       returned to the sender. Files: showq/showq.c,
+       postqueue/showq_compat.c, postqueue/showq_json.c.
+
+       Wordsmiting: after a queue manager request failure to
+       generate a verp-style delivery status notification, log
+       "verp-bounce failed" instead of "verp failed". File:
+       global/abounce.c.
index a33319808a54e1c5e879584cb8417d132b3cce1f..60574395826463c44bbd0ba2c31f73384f6d4915 100644 (file)
@@ -69,38 +69,42 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
               Each  queue entry shows the queue file ID, message size, arrival
               time, sender, and the recipients that still need  to  be  deliv-
               ered.  If mail could not be delivered upon the last attempt, the
-              reason for failure is shown. The queue ID string is followed  by
-              an optional status character:
+              reason for failure is shown. With Postfix &gt;=  3.11,  the  output
+              may  also  show bounced recipients that are pending the creation
+              of a non-delivery  status  notification  message  that  will  be
+              returned to the sender.
 
-              <b>*</b>      The  message  is in the <b>active</b> queue, i.e. the message is
+              The queue ID string is followed by an optional status character:
+
+              <b>*</b>      The message is in the <b>active</b> queue, i.e. the  message  is
                      selected for delivery.
 
-              <b>!</b>      The message is in the <b>hold</b> queue, i.e. no further  deliv-
-                     ery  attempt  will  be  made  until the mail is taken off
+              <b>!</b>      The  message is in the <b>hold</b> queue, i.e. no further deliv-
+                     ery attempt will be made until  the  mail  is  taken  off
                      hold.
 
-              <b>#</b>      The message is forced to  expire.  See  the  <a href="postsuper.1.html"><b>postsuper</b>(1)</a>
+              <b>#</b>      The  message  is  forced  to expire. See the <a href="postsuper.1.html"><b>postsuper</b>(1)</a>
                      options <b>-e</b> or <b>-f</b>.
 
                      This feature is available in Postfix 3.5 and later.
 
        <b>-s</b> <i>site</i>
-              Schedule  immediate  delivery of all mail that is queued for the
-              named <i>site</i>. A numerical site must be specified as  a  valid  <a href="https://tools.ietf.org/html/rfc5321">RFC</a>
+              Schedule immediate delivery of all mail that is queued  for  the
+              named  <i>site</i>.  A  numerical site must be specified as a valid <a href="https://tools.ietf.org/html/rfc5321">RFC</a>
               <a href="https://tools.ietf.org/html/rfc5321">5321</a>  address  literal  enclosed  in  [],  just  like  in  email
-              addresses.  The site must be eligible for the "fast flush"  ser-
-              vice.   See <a href="flush.8.html"><b>flush</b>(8)</a> for more information about the "fast flush"
+              addresses.   The site must be eligible for the "fast flush" ser-
+              vice.  See <a href="flush.8.html"><b>flush</b>(8)</a> for more information about the "fast  flush"
               service.
 
-              This option implements the traditional "<b>sendmail  -qR</b><i>site</i>"  com-
+              This  option  implements the traditional "<b>sendmail -qR</b><i>site</i>" com-
               mand, by contacting the Postfix <a href="flush.8.html"><b>flush</b>(8)</a> daemon.
 
-       <b>-v</b>     Enable  verbose  logging  for  debugging  purposes.  Multiple <b>-v</b>
-              options make the software increasingly verbose.  As  of  Postfix
+       <b>-v</b>     Enable verbose  logging  for  debugging  purposes.  Multiple  <b>-v</b>
+              options  make  the  software increasingly verbose. As of Postfix
               2.3, this option is available for the super-user only.
 
 <b><a name="json_object_format">JSON OBJECT FORMAT</a></b>
-       Each  JSON  object represents one queue file; it is emitted as a single
+       Each JSON object represents one queue file; it is emitted as  a  single
        text line followed by a newline character.
 
        Object members have string values unless indicated otherwise.  Programs
@@ -108,30 +112,30 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
        bers is expected to grow over time.
 
        <b>queue_name</b>
-              The name of the queue where the message was  found.   Note  that
-              the  contents  of  the  mail  queue may change while it is being
-              listed; some messages may appear more than once, and  some  mes-
+              The  name  of  the queue where the message was found.  Note that
+              the contents of the mail queue may  change  while  it  is  being
+              listed;  some  messages may appear more than once, and some mes-
               sages may be missed.
 
        <b>queue_id</b>
               The queue file name. The queue_id may be reused within a Postfix
               instance unless "<a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a> = true" and time is mono-
-              tonic.   Even  then,  the  queue_id is not expected to be unique
-              between different  Postfix  instances.   Management  tools  that
-              require  a  unique  name  should  combine  the queue_id with the
+              tonic.  Even then, the queue_id is not  expected  to  be  unique
+              between  different  Postfix  instances.   Management  tools that
+              require a unique name  should  combine  the  queue_id  with  the
               <a href="postconf.5.html#myhostname">myhostname</a> setting of the Postfix instance.
 
        <b>arrival_time</b>
               The number of seconds since the start of the UNIX epoch.
 
        <b>message_size</b>
-              The number of bytes in the message header and body. This  number
-              does  not  include  message envelope information. It is approxi-
-              mately equal to the number of bytes that  would  be  transmitted
+              The  number of bytes in the message header and body. This number
+              does not include message envelope information.  It  is  approxi-
+              mately  equal  to  the number of bytes that would be transmitted
               via SMTP including the &lt;CR&gt;&lt;LF&gt; line endings.
 
        <b>forced_expire</b> (Postfix &gt;= 3.5)
-              The  message is forced to expire (<b>true</b> or <b>false</b>).  See the <a href="postsuper.1.html"><b>post-</b></a>
+              The message is forced to expire (<b>true</b> or <b>false</b>).  See the  <a href="postsuper.1.html"><b>post-</b></a>
               <a href="postsuper.1.html"><b>super</b>(1)</a> options <b>-e</b> or <b>-f</b>.
 
        <b>sender</b> The envelope sender address.
@@ -146,11 +150,17 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
                      One original recipient address.
 
               <b>delay_reason</b>
-                     If present, the reason  for  delayed  delivery.   Delayed
-                     recipients  may  have no delay reason, for example, while
-                     delivery is in progress, or after the system was  stopped
+                     If  present,  the  reason  for delayed delivery.  Delayed
+                     recipients may have no delay reason, for  example,  while
+                     delivery  is in progress, or after the system was stopped
                      before it could record the reason.
 
+              <b>bounce_reason</b> (Postfix &gt;= 3.11)
+                     If present, the reason why this  recipient  was  bounced.
+                     The   recipient  is  still  pending  the  creation  of  a
+                     non-delivery status notification  message  that  will  be
+                     returned to the sender.
+
 <b><a name="security">SECURITY</a></b>
        This  program  is designed to run with set-group ID privileges, so that
        it can connect to Postfix daemon processes.
index 4d2b6d4b57ee0fc34e968e2f7cb15f98689ce505..d3c4341b0a363cca1d6ebddb41dd92a91421ffd7 100644 (file)
@@ -68,8 +68,12 @@ by contacting the Postfix \fBshowq\fR(8) daemon.
 Each queue entry shows the queue file ID, message
 size, arrival time, sender, and the recipients that still need to
 be delivered.  If mail could not be delivered upon the last attempt,
-the reason for failure is shown. The queue ID string
-is followed by an optional status character:
+the reason for failure is shown. With Postfix >= 3.11, the output
+may also show bounced recipients that are pending the creation
+of a non\-delivery status notification message that will be
+returned to the sender.
+
+The queue ID string is followed by an optional status character:
 .RS
 .IP \fB*\fR
 The message is in the \fBactive\fR queue, i.e. the message is
@@ -137,13 +141,17 @@ An array containing zero or more objects with members:
 .RS
 .IP \fBaddress\fR
 One recipient address.
-.IP "\fBorig_address\fR (Postfix >= 3.11)
+.IP "\fBorig_address\fR (Postfix >= 3.11)"
 One original recipient address.
 .IP \fBdelay_reason\fR
 If present, the reason for delayed delivery.  Delayed
 recipients may have no delay reason, for example, while
 delivery is in progress, or after the system was stopped
 before it could record the reason.
+.IP "\fBbounce_reason\fR (Postfix >= 3.11)"
+If present, the reason why this recipient was bounced. The
+recipient is still pending the creation of a non\-delivery status
+notification message that will be returned to the sender.
 .RE
 .SH "SECURITY"
 .na
index eff4e79fcb022864d8b5afec18f3a0eab29b5594..b8cac649c8c96b83759a083300a308eb80cee60e 100644 (file)
@@ -260,7 +260,7 @@ static void abounce_done(ABOUNCE_STATE *ap, int status)
        msg_info("%s: status=deferred (%s failed)", ap->id,
                 ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
                 ap->command == BOUNCE_CMD_WARN ? "delay warning" :
-                ap->command == BOUNCE_CMD_VERP ? "bounce" :
+                ap->command == BOUNCE_CMD_VERP ? "verp-bounce" :
                 ap->command == BOUNCE_CMD_TRACE ? "trace" :
                 "whatever");
     ap->callback(status, ap->context);
index d784ce42dc46556d0519d6ffc20f62e58975842d..010bc05bfbb136e19cbe5931de50b016ab7b2393 100644 (file)
@@ -264,6 +264,8 @@ extern char *mail_pathname(const char *, const char *);
 
 #define MAIL_ATTR_MESSAGE_ID   "message_id"    /* Used for threaded bounce */
 
+#define MAIL_ATTR_LOG_CLASS    "log_class"     /* bounce/defer/trace */
+
  /*
   * XCLIENT/XFORWARD in SMTP.
   */
index 2143a1cf281f0e470fd619bcf755a43fc292dc81..3bb6755a02e5333217f498abc7112be91f0d8527 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20251217"
+#define MAIL_RELEASE_DATE      "20251218"
 #define MAIL_VERSION_NUMBER    "3.11"
 
 #ifdef SNAPSHOT
index 7f20a98666f516cbae173bd8306da0681d23dd88..2f1ee88f21e93ad5eb2ac5df1d7cc310a4a040d2 100644 (file)
 /*     Each queue entry shows the queue file ID, message
 /*     size, arrival time, sender, and the recipients that still need to
 /*     be delivered.  If mail could not be delivered upon the last attempt,
-/*     the reason for failure is shown. The queue ID string
-/*     is followed by an optional status character:
+/*     the reason for failure is shown. With Postfix >= 3.11, the output
+/*     may also show bounced recipients that are pending the creation
+/*     of a non-delivery status notification message that will be
+/*     returned to the sender.
+/*
+/*     The queue ID string is followed by an optional status character:
 /* .RS
 /* .IP \fB*\fR
 /*     The message is in the \fBactive\fR queue, i.e. the message is
 /* .RS
 /* .IP \fBaddress\fR
 /*     One recipient address.
-/* .IP "\fBorig_address\fR (Postfix >= 3.11)
+/* .IP "\fBorig_address\fR (Postfix >= 3.11)"
 /*     One original recipient address.
 /* .IP \fBdelay_reason\fR
 /*     If present, the reason for delayed delivery.  Delayed
 /*     recipients may have no delay reason, for example, while
 /*     delivery is in progress, or after the system was stopped
 /*     before it could record the reason.
+/* .IP "\fBbounce_reason\fR (Postfix >= 3.11)"
+/*     If present, the reason why this recipient was bounced. The
+/*     recipient is still pending the creation of a non-delivery status
+/*     notification message that will be returned to the sender.
 /* .RE
 /* SECURITY
 /* .ad
index 8647034ca2efc70346b31fcc8dfc7b19939e7e30..6d3f2fae6b8f869e78a73a4292c872e6d23c5620 100644 (file)
@@ -86,6 +86,7 @@ static unsigned long showq_message(VSTREAM *showq_stream)
     static VSTRING *id_status = 0;
     static VSTRING *oaddr = 0;
     static VSTRING *addr = 0;
+    static VSTRING *log_class = 0;
     static VSTRING *why = 0;
     long    arrival_time;
     long    message_size;
@@ -105,6 +106,7 @@ static unsigned long showq_message(VSTREAM *showq_stream)
        id_status = vstring_alloc(100);
        oaddr = vstring_alloc(100);
        addr = vstring_alloc(100);
+       log_class = vstring_alloc(100);
        why = vstring_alloc(100);
     }
 
@@ -150,8 +152,9 @@ static unsigned long showq_message(VSTREAM *showq_stream)
                      | ATTR_FLAG_PRINTABLE,
                      RECV_ATTR_STR(MAIL_ATTR_ORCPT, oaddr),
                      RECV_ATTR_STR(MAIL_ATTR_RECIP, addr),
+                     RECV_ATTR_STR(MAIL_ATTR_LOG_CLASS, log_class),
                      RECV_ATTR_STR(MAIL_ATTR_WHY, why),
-                     ATTR_TYPE_END) != 3)
+                     ATTR_TYPE_END) != 4)
            msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
 
        /*
index bf55e97d6d75441a243abcd48af25b881997b0da..7bad7167911bde3a74f8da435a344b3476d88b86 100644 (file)
@@ -66,6 +66,7 @@ static void format_json(VSTREAM *showq_stream)
     static VSTRING *queue_id = 0;
     static VSTRING *oaddr = 0;
     static VSTRING *addr = 0;
+    static VSTRING *log_class = 0;
     static VSTRING *why = 0;
     static VSTRING *quote_buf = 0;
     long    arrival_time;
@@ -82,6 +83,7 @@ static void format_json(VSTREAM *showq_stream)
        queue_id = vstring_alloc(100);
        oaddr = vstring_alloc(100);
        addr = vstring_alloc(100);
+       log_class = vstring_alloc(100);
        why = vstring_alloc(100);
        quote_buf = vstring_alloc(100);
     }
@@ -130,15 +132,19 @@ static void format_json(VSTREAM *showq_stream)
                      | ATTR_FLAG_PRINTABLE,
                      RECV_ATTR_STR(MAIL_ATTR_ORCPT, oaddr),
                      RECV_ATTR_STR(MAIL_ATTR_RECIP, addr),
+                     RECV_ATTR_STR(MAIL_ATTR_LOG_CLASS, log_class),
                      RECV_ATTR_STR(MAIL_ATTR_WHY, why),
-                     ATTR_TYPE_END) != 3)
+                     ATTR_TYPE_END) != 4)
            msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
        vstream_printf("\"orig_address\": \"%s\", ",
                       QUOTE_JSON(quote_buf, STR(oaddr)));
        vstream_printf("\"address\": \"%s\"",
                       QUOTE_JSON(quote_buf, STR(addr)));
        if (LEN(why) > 0)
-           vstream_printf(", \"delay_reason\": \"%s\"",
+           vstream_printf(", \"%s\": \"%s\"",
+           strcmp(STR(log_class), MAIL_QUEUE_DEFER) == 0 ? "delay_reason" :
+                          strcmp(STR(log_class), MAIL_QUEUE_BOUNCE) == 0 ? "bounce_reason" :
+                          "other_reason",
                           QUOTE_JSON(quote_buf, STR(why)));
        vstream_printf("}");
     }
index bb9cefdf5a43fd549fa33953aa05f318ab3695e4..9c2755493c932a94409beb993e38e1a8bf5fa034 100644 (file)
 int     var_dup_filter_limit;
 char   *var_empty_addr;
 
-static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *,
-                                 HTABLE *);
+static void showq_reasons(VSTREAM *, const char *, BOUNCE_LOG *, RCPT_BUF *,
+                                 DSN_BUF *, HTABLE *);
 
 #define STR(x) vstring_str(x)
 
@@ -306,31 +306,44 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
         * interrupted (postfix stop or reload) before all recipients have
         * been tried.
         * 
-        * Therefore we keep a record of recipients found in the defer logfile,
-        * and try to avoid listing those recipients again when processing
-        * recipients from the queue file.
+        * With Postfix 3.11 also list recipients in a bounce logfile. Such
+        * recipients were already deleted from the message file, but they
+        * haven't yet been persisted to a non-delivery status notification
+        * message.
+        * 
+        * We remember recipients found in a defer or bounce logfile, and try to
+        * avoid listing those recipients again when processing recipients
+        * from the queue file.
         */
-       if (rec_type == REC_TYPE_FROM
-           && (logfile = bounce_log_open(MAIL_QUEUE_DEFER, id, O_RDONLY, 0)) != 0) {
+       if (rec_type == REC_TYPE_FROM) {
+           const char *log_names[] = {MAIL_QUEUE_DEFER, MAIL_QUEUE_BOUNCE, 0};
+           const char **cpp;
+
            if (dup_filter != 0)
                msg_panic("showq_report: attempt to reuse duplicate filter");
-           dup_filter = htable_create(var_dup_filter_limit);
            if (rcpt_buf == 0)
                rcpt_buf = rcpb_create();
            if (dsn_buf == 0)
                dsn_buf = dsb_create();
-           showq_reasons(client, logfile, rcpt_buf, dsn_buf, dup_filter);
-           if (bounce_log_close(logfile))
-               msg_warn("close %s %s: %m", MAIL_QUEUE_DEFER, id);
+           dup_filter = htable_create(var_dup_filter_limit);
+           for (cpp = log_names; *cpp; cpp++) {
+               if ((logfile = bounce_log_open(*cpp, id, O_RDONLY, 0)) != 0) {
+                   showq_reasons(client, *cpp, logfile, rcpt_buf, dsn_buf,
+                                 dup_filter);
+                   if (bounce_log_close(logfile))
+                       msg_warn("close %s %s: %m", *cpp, id);
+               }
+           }
        }
     }
     SHOWQ_CLEANUP_AND_RETURN;
 }
 
-/* showq_reasons - show deferral reasons */
+/* showq_reasons - show defer or bounce reasons */
 
-static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
-                                 DSN_BUF *dsn_buf, HTABLE *dup_filter)
+static void showq_reasons(VSTREAM *client, const char *log_class, BOUNCE_LOG *bp,
+                                 RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf,
+                                 HTABLE *dup_filter)
 {
     RECIPIENT *rcpt = &rcpt_buf->rcpt;
     DSN    *dsn = &dsn_buf->dsn;
@@ -348,6 +361,7 @@ static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
        attr_print(client, ATTR_FLAG_MORE,
                   SEND_ATTR_STR(MAIL_ATTR_ORCPT, rcpt->orig_addr),
                   SEND_ATTR_STR(MAIL_ATTR_RECIP, rcpt->address),
+                  SEND_ATTR_STR(MAIL_ATTR_LOG_CLASS, log_class),
                   SEND_ATTR_STR(MAIL_ATTR_WHY, dsn->reason),
                   ATTR_TYPE_END);
     }