From 51005335d41a148e9b013d5757a7fe8aa32a987d Mon Sep 17 00:00:00 2001
From: Wietse Venema
Date: Sat, 12 Dec 2020 00:00:00 -0500
Subject: [PATCH] postfix-3.6-20201212
---
postfix/HISTORY | 43 ++-
postfix/RELEASE_NOTES | 13 +
postfix/WISHLIST | 27 +-
postfix/html/bounce.8.html | 7 +
postfix/html/cleanup.8.html | 200 +++++++------
postfix/html/defer.8.html | 7 +
postfix/html/postconf.5.html | 47 ++-
postfix/html/trace.8.html | 7 +
postfix/man/man5/postconf.5 | 40 ++-
postfix/man/man8/bounce.8 | 6 +
postfix/man/man8/cleanup.8 | 29 +-
postfix/mantools/postlink | 1 +
postfix/proto/postconf.proto | 43 ++-
postfix/src/bounce/Makefile.in | 270 +++++++++++++++++-
postfix/src/bounce/bounce.c | 12 +
postfix/src/bounce/bounce_notify_util.c | 115 +++++++-
.../src/bounce/bounce_notify_util_tester.c | 159 +++++++++++
postfix/src/bounce/bounce_service.h | 1 +
.../src/bounce/logfile-no-msgid-no-eoh-event | 13 +
.../bounce/logfile-no-msgid-with-eoh-event | 13 +
.../bounce/logfile-with-msgid-no-eoh-event | 13 +
.../bounce/logfile-with-msgid-with-eoh-event | 13 +
.../src/bounce/logfile-with-msgid-with-filter | 13 +
.../bounce/logfile-with-msgid-with-long-line | 13 +
.../src/bounce/msgfile-no-msgid-no-eoh-event | Bin 0 -> 522 bytes
.../bounce/msgfile-no-msgid-with-eoh-event | Bin 0 -> 536 bytes
.../bounce/msgfile-with-msgid-no-eoh-event | Bin 0 -> 606 bytes
.../bounce/msgfile-with-msgid-with-eoh-event | Bin 0 -> 621 bytes
.../src/bounce/msgfile-with-msgid-with-filter | Bin 0 -> 581 bytes
.../bounce/msgfile-with-msgid-with-long-line | Bin 0 -> 4624 bytes
.../no-msgid-no-eoh-event-no-thread.ref | 47 +++
.../no-msgid-no-eoh-event-with-thread.ref | 47 +++
.../no-msgid-with-eoh-event-no-thread.ref | 49 ++++
.../no-msgid-with-eoh-event-with-thread.ref | 49 ++++
.../with-msgid-no-eoh-event-no-thread.ref | 49 ++++
.../with-msgid-no-eoh-event-with-thread.ref | 51 ++++
.../with-msgid-with-eoh-event-no-thread.ref | 51 ++++
.../with-msgid-with-eoh-event-with-thread.ref | 53 ++++
.../with-msgid-with-filter-no-thread.ref | 48 ++++
.../with-msgid-with-filter-with-thread.ref | 50 ++++
.../with-msgid-with-long-line-no-thread.ref | 50 ++++
.../with-msgid-with-long-line-with-thread.ref | 52 ++++
postfix/src/cleanup/cleanup.c | 29 +-
postfix/src/global/Makefile.in | 28 +-
postfix/src/global/debug_peer.c | 2 +-
postfix/src/global/delivered_hdr.c | 2 +-
postfix/src/global/mail_params.h | 8 +
postfix/src/global/mail_version.h | 2 +-
postfix/src/global/test_main.c | 224 +++++++++++++++
postfix/src/global/test_main.h | 64 +++++
postfix/src/qmqpd/qmqpd_peer.c | 1 -
postfix/src/smtpd/smtpd_peer.c | 1 -
postfix/src/util/Makefile.in | 2 -
postfix/src/util/vbuf_print.c | 3 +-
54 files changed, 1898 insertions(+), 169 deletions(-)
create mode 100644 postfix/src/bounce/bounce_notify_util_tester.c
create mode 100644 postfix/src/bounce/logfile-no-msgid-no-eoh-event
create mode 100644 postfix/src/bounce/logfile-no-msgid-with-eoh-event
create mode 100644 postfix/src/bounce/logfile-with-msgid-no-eoh-event
create mode 100644 postfix/src/bounce/logfile-with-msgid-with-eoh-event
create mode 100644 postfix/src/bounce/logfile-with-msgid-with-filter
create mode 100644 postfix/src/bounce/logfile-with-msgid-with-long-line
create mode 100755 postfix/src/bounce/msgfile-no-msgid-no-eoh-event
create mode 100755 postfix/src/bounce/msgfile-no-msgid-with-eoh-event
create mode 100755 postfix/src/bounce/msgfile-with-msgid-no-eoh-event
create mode 100755 postfix/src/bounce/msgfile-with-msgid-with-eoh-event
create mode 100755 postfix/src/bounce/msgfile-with-msgid-with-filter
create mode 100755 postfix/src/bounce/msgfile-with-msgid-with-long-line
create mode 100644 postfix/src/bounce/no-msgid-no-eoh-event-no-thread.ref
create mode 100644 postfix/src/bounce/no-msgid-no-eoh-event-with-thread.ref
create mode 100644 postfix/src/bounce/no-msgid-with-eoh-event-no-thread.ref
create mode 100644 postfix/src/bounce/no-msgid-with-eoh-event-with-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-no-eoh-event-no-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-no-eoh-event-with-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-with-eoh-event-no-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-with-eoh-event-with-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-with-filter-no-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-with-filter-with-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-with-long-line-no-thread.ref
create mode 100644 postfix/src/bounce/with-msgid-with-long-line-with-thread.ref
create mode 100644 postfix/src/global/test_main.c
create mode 100644 postfix/src/global/test_main.h
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 611d162cc..1edb0d0e9 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -25228,7 +25228,7 @@ Apologies for any names omitted.
20201022
Bugfix (introduced: Postfix 2.2): after processing an
- XCCLIENT command, the smtps service was waiting for a TLS
+ XCLIENT command, the smtps service was waiting for a TLS
handshake. Found by Aki Tuomi. File: smtpd/smtpd.c.
20201025
@@ -25274,3 +25274,44 @@ Apologies for any names omitted.
smtp/smtp_proto.c.
Added missing employer attributions to .c and .h files.
+
+20201116
+
+ Documentation: document that check_mumble_mx_access will
+ look up A or AAAA records when a domain name has no MX
+ record, just like the Postfix SMTP client would. File:
+ proto/postconf.proto.
+
+20201122
+
+ Cleanup: log "Application error" instead of "Success" or
+ "Unknown error: 0" when an operation fails with errno ==
+ 0. File: util/vbuf_print.c.
+
+20201125
+
+ Documentation: in the cleanup(8) description of message
+ transformations, mention how some transformations are
+ controlled with the local_header_rewrite_clients,
+ always_add_missing_headers, and message_drop_headers parameter
+ settings. File: cleanup/cleanup.c.
+
+20201129
+
+ Cleanup: future-proofing a condition in delivered_hdr_init().
+ The code was not wrong, but the new code is more consistent
+ with new code in the bounce daemon where the difference does
+ matter. File: global/delivered_hdr.c
+
+20201205
+
+ Testing: generic test_main() routine to initialize configuration
+ parameters before running a test routine. Files:
+ global/test_main.[hc].
+
+ Feature: specify "enable_threaded_bounces = yes" to enable
+ bounce messages that link to the original message with a
+ References: and In-Reply_to: header. Based on code by Andreas
+ Thienemann. See RELEASE_NOTES for caveats. Files:
+ proto/postconf.proto, bounce/bounce_notify_tester.c, many
+ test data files to exercise corner cases.
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index 8b902330e..606df671f 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -25,6 +25,19 @@ more recent Eclipse Public License 2.0. Recipients can choose to take
the software under the license of their choice. Those who are more
comfortable with the IPL can continue with that license.
+Major changes with snapshot 20201205
+====================================
+
+Support for threaded bounces. This allows mail readers to present
+a non-delivery notification in the same email thread as the original
+message.
+
+Unfortunately, this also makes it easy for users to mistakenly delete
+the whole email thread (all related messages), instead of deleting
+only the non-delivery notification.
+
+To enable, specify "enable_threaded_bounces = yes".
+
Major changes with snapshot 20201025
====================================
diff --git a/postfix/WISHLIST b/postfix/WISHLIST
index 98295cc7e..0ea098331 100644
--- a/postfix/WISHLIST
+++ b/postfix/WISHLIST
@@ -1,15 +1,14 @@
Wish list:
- Does tlsproxy terminate to soon after 'postfix reload'?
- like, while a session is still im progress? Does it depend
- on the server or client role?
-
Eliminate duplicate user_acl check from sendmail, and pass
the result through the postdrop-to-sendmail protocol. This
requires that postdrop reads all inputs before responding.
Then we can also consider to save input to dead.letter (drop
setgid privilege, use safe_open() to avoid clobbering files).
+ Allow '}' at the beginning of a line. This would make
+ multi-line configuration settings easier to enter.
+
Understand what happens with DNSSEC related status fields
in posttls-finger when resolv.conf points to a host that
runs no DNS server.
@@ -19,26 +18,18 @@ Wish list:
parameter. For example:
http://postfix.1071664.n5.nabble.com/Relay-attempt-questions-td103646.html
- Document that check_mumble_mx_access generates synthetic
- MX records i.e. A/AAAA where no MX exists.
-
- Someone suggested adding References: and In-Reply-To: headers
- in bounce messages. Downside: that will make it harder to
- delete a bounce without deleting other mail. Therefore do
- not enable by default.
-
Hardening the half-dane behavior: some sites may rely on
current behavior which allows original MX domain name for
certificate matches. Requires a new (compatibility) parameter
setting?
Code deduplication: migrate multi_server applications to
- event_server. In addition to the default event_server
- accept() handler, also register a read event callback for
- handling post_accept events. But the currrent multi_server
- API foits typical usage better.
-
- Maybe expand %m to "application error" when errno == 0.
+ event_server, because the multi_server and event_server
+ skeletons are much more similar than other skeletons. In
+ addition to the default event_server accept() handler, also
+ register a read event callback for handling post_accept
+ events. But the currrent multi_server API fits typical usage
+ better.
smtp_sasl_tls_security_options = noanonymous, and make
smtp_sasl_security_options default dependent on the
diff --git a/postfix/html/bounce.8.html b/postfix/html/bounce.8.html
index 9ad2abb03..31f12cb85 100644
--- a/postfix/html/bounce.8.html
+++ b/postfix/html/bounce.8.html
@@ -153,6 +153,13 @@ BOUNCE(8) BOUNCE(8)
service_name (read-only)
The master.cf service name of a Postfix daemon process.
+ Available in Postfix 3.6 and later:
+
+ enable_threaded_bounces (no)
+ Enable non-delivery notifications (bounce messages) that link to
+ the original message by including a References: and In-Reply_to:
+ header with the original Message-ID value.
+
FILES
/var/spool/postfix/bounce/* non-delivery records
/var/spool/postfix/defer/* non-delivery records
diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html
index da24764f3..38c0f2baa 100644
--- a/postfix/html/cleanup.8.html
+++ b/postfix/html/cleanup.8.html
@@ -16,40 +16,50 @@ CLEANUP(8) CLEANUP(8)
The cleanup(8) daemon processes inbound mail, inserts it into the
incoming mail queue, and informs the queue manager of its arrival.
- The cleanup(8) daemon always performs the following transformations:
+ The cleanup(8) daemon performs the following transformations:
o Insert missing message headers: (Resent-) From:, To:, Mes-
sage-Id:, and Date:.
+ This is enabled with the local_header_rewrite_clients and
+ always_add_missing_headers parameter settings.
- o Transform envelope and header addresses to the standard
+ o Transform envelope and header addresses to the standard
user@fully-qualified-domain form that is expected by other Post-
- fix programs. This task is delegated to the trivial-rewrite(8)
- daemon.
+ fix programs. This task depends on the trivial-rewrite(8) dae-
+ mon.
+ The header transformation is enabled with the local_header_re-
+ write_clients parameter setting.
o Eliminate duplicate envelope recipient addresses.
+ This is enabled with the duplicate_filter_limit parameter set-
+ ting.
- o Remove message headers: Bcc, Content-Length, Resent-Bcc,
+ o Remove message headers: Bcc, Content-Length, Resent-Bcc,
Return-Path.
-
- The following address transformations are optional:
+ This is enabled with the message_drop_headers parameter setting.
o Optionally, rewrite all envelope and header addresses according
to the mappings specified in the canonical(5) lookup tables.
+ The header transformation is enabled with the local_header_re-
+ write_clients parameter setting.
- o Optionally, masquerade envelope sender addresses and message
- header addresses (i.e. strip host or domain information below
- all domains listed in the masquerade_domains parameter, except
- for user names listed in masquerade_exceptions). By default,
+ o Optionally, masquerade envelope sender addresses and message
+ header addresses (i.e. strip host or domain information below
+ all domains listed in the masquerade_domains parameter, except
+ for user names listed in masquerade_exceptions). By default,
address masquerading does not affect envelope recipients.
+ The header transformation is enabled with the local_header_re-
+ write_clients parameter setting.
o Optionally, expand envelope recipients according to information
- found in the virtual(5) lookup tables.
+ found in the virtual_alias_maps lookup tables.
The cleanup(8) daemon performs sanity checks on the content of each
message. When it finds a problem, by default it returns a diagnostic
- status to the client, and leaves it up to the client to deal with the
- problem. Alternatively, the client can request the cleanup(8) daemon to
- bounce the message back to the sender in case of trouble.
+ status to the cleanup service client, and leaves it up to the client to
+ deal with the problem. Alternatively, the client can request the
+ cleanup(8) daemon to bounce the message back to the sender in case of
+ trouble.
STANDARDS
RFC 822 (ARPA Internet Text Messages)
@@ -64,7 +74,7 @@ CLEANUP(8) CLEANUP(8)
Problems and transactions are logged to syslogd(8) or postlogd(8).
BUGS
- Table-driven rewriting rules make it hard to express if then else and
+ Table-driven rewriting rules make it hard to express if then else and
other logical relationships.
CONFIGURATION PARAMETERS
@@ -72,7 +82,7 @@ CLEANUP(8) CLEANUP(8)
run for only a limited amount of time. Use the command "postfix reload"
to speed up a change.
- The text below provides only a parameter summary. See postconf(5) for
+ The text below provides only a parameter summary. See postconf(5) for
more details including examples.
COMPATIBILITY CONTROLS
@@ -83,16 +93,16 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 2.1 only:
enable_errors_to (no)
- Report mail delivery errors to the address specified with the
- non-standard Errors-To: message header, instead of the envelope
- sender address (this feature is removed with Postfix version
- 2.2, is turned off by default with Postfix version 2.1, and is
+ Report mail delivery errors to the address specified with the
+ non-standard Errors-To: message header, instead of the envelope
+ sender address (this feature is removed with Postfix version
+ 2.2, is turned off by default with Postfix version 2.1, and is
always turned on with older Postfix versions).
Available in Postfix version 2.6 and later:
always_add_missing_headers (no)
- Always add (Resent-) From:, To:, Date: or Message-ID: headers
+ Always add (Resent-) From:, To:, Date: or Message-ID: headers
when not present.
Available in Postfix version 2.9 and later:
@@ -103,7 +113,7 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.0 and later:
message_drop_headers (bcc, content-length, resent-bcc, return-path)
- Names of message headers that the cleanup(8) daemon will remove
+ Names of message headers that the cleanup(8) daemon will remove
after applying header_checks(5) and before invoking Milter
applications.
@@ -112,34 +122,34 @@ CLEANUP(8) CLEANUP(8)
viruses. It is not a general content filter.
body_checks (empty)
- Optional lookup tables for content inspection as specified in
+ Optional lookup tables for content inspection as specified in
the body_checks(5) manual page.
header_checks (empty)
- Optional lookup tables for content inspection of primary
- non-MIME message headers, as specified in the header_checks(5)
+ Optional lookup tables for content inspection of primary
+ non-MIME message headers, as specified in the header_checks(5)
manual page.
Available in Postfix version 2.0 and later:
body_checks_size_limit (51200)
- How much text in a message body segment (or attachment, if you
+ How much text in a message body segment (or attachment, if you
prefer to use that term) is subjected to body_checks inspection.
mime_header_checks ($header_checks)
- Optional lookup tables for content inspection of MIME related
- message headers, as described in the header_checks(5) manual
+ Optional lookup tables for content inspection of MIME related
+ message headers, as described in the header_checks(5) manual
page.
nested_header_checks ($header_checks)
- Optional lookup tables for content inspection of non-MIME mes-
- sage headers in attached messages, as described in the
+ Optional lookup tables for content inspection of non-MIME mes-
+ sage headers in attached messages, as described in the
header_checks(5) manual page.
Available in Postfix version 2.3 and later:
message_reject_characters (empty)
- The set of characters that Postfix will reject in message con-
+ The set of characters that Postfix will reject in message con-
tent.
message_strip_characters (empty)
@@ -148,26 +158,26 @@ CLEANUP(8) CLEANUP(8)
BEFORE QUEUE MILTER CONTROLS
As of version 2.3, Postfix supports the Sendmail version 8 Milter (mail
- filter) protocol. When mail is not received via the smtpd(8) server,
+ filter) protocol. When mail is not received via the smtpd(8) server,
the cleanup(8) server will simulate SMTP events to the extent that this
is possible. For details see the MILTER_README document.
non_smtpd_milters (empty)
- A list of Milter (mail filter) applications for new mail that
+ A list of Milter (mail filter) applications for new mail that
does not arrive via the Postfix smtpd(8) server.
milter_protocol (6)
- The mail filter protocol version and optional protocol exten-
- sions for communication with a Milter application; prior to
+ The mail filter protocol version and optional protocol exten-
+ sions for communication with a Milter application; prior to
Postfix 2.6 the default protocol is 2.
milter_default_action (tempfail)
- The default action when a Milter (mail filter) response is
- unavailable (for example, bad Postfix configuration or Milter
+ The default action when a Milter (mail filter) response is
+ unavailable (for example, bad Postfix configuration or Milter
failure).
milter_macro_daemon_name ($myhostname)
- The {daemon_name} macro value for Milter (mail filter) applica-
+ The {daemon_name} macro value for Milter (mail filter) applica-
tions.
milter_macro_v ($mail_name $mail_version)
@@ -178,45 +188,45 @@ CLEANUP(8) CLEANUP(8)
tion, and for negotiating protocol options.
milter_command_timeout (30s)
- The time limit for sending an SMTP command to a Milter (mail
+ The time limit for sending an SMTP command to a Milter (mail
filter) application, and for receiving the response.
milter_content_timeout (300s)
- The time limit for sending message content to a Milter (mail
+ The time limit for sending message content to a Milter (mail
filter) application, and for receiving the response.
milter_connect_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after completion of an SMTP connection.
milter_helo_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the SMTP HELO or EHLO command.
milter_mail_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the SMTP MAIL FROM command.
milter_rcpt_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the SMTP RCPT TO command.
milter_data_macros (see 'postconf -d' output)
- The macros that are sent to version 4 or higher Milter (mail
+ The macros that are sent to version 4 or higher Milter (mail
filter) applications after the SMTP DATA command.
milter_unknown_command_macros (see 'postconf -d' output)
- The macros that are sent to version 3 or higher Milter (mail
+ The macros that are sent to version 3 or higher Milter (mail
filter) applications after an unknown SMTP command.
milter_end_of_data_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
Available in Postfix version 2.5 and later:
milter_end_of_header_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the end of the message header.
Available in Postfix version 2.7 and later:
@@ -228,8 +238,8 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.1 and later:
milter_macro_defaults (empty)
- Optional list of name=value pairs that specify default values
- for arbitrary macros that Postfix may send to Milter applica-
+ Optional list of name=value pairs that specify default values
+ for arbitrary macros that Postfix may send to Milter applica-
tions.
MIME PROCESSING CONTROLS
@@ -255,91 +265,91 @@ CLEANUP(8) CLEANUP(8)
ing information.
strict_mime_encoding_domain (no)
- Reject mail with invalid Content-Transfer-Encoding: information
+ Reject mail with invalid Content-Transfer-Encoding: information
for the message/* or multipart/* MIME content types.
Available in Postfix version 2.5 and later:
detect_8bit_encoding_header (yes)
- Automatically detect 8BITMIME body content by looking at Con-
- tent-Transfer-Encoding: message headers; historically, this
+ Automatically detect 8BITMIME body content by looking at Con-
+ tent-Transfer-Encoding: message headers; historically, this
behavior was hard-coded to be "always on".
AUTOMATIC BCC RECIPIENT CONTROLS
- Postfix can automatically add BCC (blind carbon copy) when mail enters
+ Postfix can automatically add BCC (blind carbon copy) when mail enters
the mail system:
always_bcc (empty)
- Optional address that receives a "blind carbon copy" of each
+ Optional address that receives a "blind carbon copy" of each
message that is received by the Postfix mail system.
Available in Postfix version 2.1 and later:
sender_bcc_maps (empty)
- Optional BCC (blind carbon-copy) address lookup tables, indexed
+ Optional BCC (blind carbon-copy) address lookup tables, indexed
by sender address.
recipient_bcc_maps (empty)
- Optional BCC (blind carbon-copy) address lookup tables, indexed
+ Optional BCC (blind carbon-copy) address lookup tables, indexed
by recipient address.
ADDRESS TRANSFORMATION CONTROLS
- Address rewriting is delegated to the trivial-rewrite(8) daemon. The
+ Address rewriting is delegated to the trivial-rewrite(8) daemon. The
cleanup(8) server implements table driven address mapping.
empty_address_recipient (MAILER-DAEMON)
The recipient of mail addressed to the null address.
canonical_maps (empty)
- Optional address mapping lookup tables for message headers and
+ Optional address mapping lookup tables for message headers and
envelopes.
recipient_canonical_maps (empty)
- Optional address mapping lookup tables for envelope and header
+ Optional address mapping lookup tables for envelope and header
recipient addresses.
sender_canonical_maps (empty)
- Optional address mapping lookup tables for envelope and header
+ Optional address mapping lookup tables for envelope and header
sender addresses.
masquerade_classes (envelope_sender, header_sender, header_recipient)
What addresses are subject to address masquerading.
masquerade_domains (empty)
- Optional list of domains whose subdomain structure will be
+ Optional list of domains whose subdomain structure will be
stripped off in email addresses.
masquerade_exceptions (empty)
- Optional list of user names that are not subjected to address
- masquerading, even when their addresses match $masquer-
+ Optional list of user names that are not subjected to address
+ masquerading, even when their addresses match $masquer-
ade_domains.
propagate_unmatched_extensions (canonical, virtual)
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
Available before Postfix version 2.0:
virtual_maps (empty)
- Optional lookup tables with a) names of domains for which all
- addresses are aliased to addresses in other local or remote
+ Optional lookup tables with a) names of domains for which all
+ addresses are aliased to addresses in other local or remote
domains, and b) addresses that are aliased to addresses in other
local or remote domains.
Available in Postfix version 2.0 and later:
virtual_alias_maps ($virtual_maps)
- Optional lookup tables that alias specific mail addresses or
+ Optional lookup tables that alias specific mail addresses or
domains to other local or remote address.
Available in Postfix version 2.2 and later:
- canonical_classes (envelope_sender, envelope_recipient, header_sender,
+ canonical_classes (envelope_sender, envelope_recipient, header_sender,
header_recipient)
What addresses are subject to canonical_maps address mapping.
recipient_canonical_classes (envelope_recipient, header_recipient)
- What addresses are subject to recipient_canonical_maps address
+ What addresses are subject to recipient_canonical_maps address
mapping.
sender_canonical_classes (envelope_sender, header_sender)
@@ -347,8 +357,8 @@ CLEANUP(8) CLEANUP(8)
ping.
remote_header_rewrite_domain (empty)
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
+ Don't rewrite message headers from remote clients at all when
+ this parameter is empty; otherwise, rewrite message headers and
append the specified domain name to incomplete addresses.
RESOURCE AND RATE CONTROLS
@@ -358,7 +368,7 @@ CLEANUP(8) CLEANUP(8)
showq(8) queue displays.
header_size_limit (102400)
- The maximal amount of memory in bytes for storing a message
+ The maximal amount of memory in bytes for storing a message
header.
hopcount_limit (50)
@@ -366,17 +376,17 @@ CLEANUP(8) CLEANUP(8)
in the primary message headers.
in_flow_delay (1s)
- Time to pause before accepting a new message, when the message
+ Time to pause before accepting a new message, when the message
arrival rate exceeds the message delivery rate.
message_size_limit (10240000)
- The maximal size in bytes of a message, including envelope
+ The maximal size in bytes of a message, including envelope
information.
Available in Postfix version 2.0 and later:
header_address_token_limit (10240)
- The maximal number of address tokens are allowed in an address
+ The maximal number of address tokens are allowed in an address
message header.
mime_boundary_length_limit (2048)
@@ -392,7 +402,7 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 2.1 and later:
virtual_alias_expansion_limit (1000)
- The maximal number of addresses that virtual alias expansion
+ The maximal number of addresses that virtual alias expansion
produces from each original recipient.
virtual_alias_recursion_limit (1000)
@@ -401,50 +411,50 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.0 and later:
virtual_alias_address_length_limit (1000)
- The maximal length of an email address after virtual alias
+ The maximal length of an email address after virtual alias
expansion.
SMTPUTF8 CONTROLS
Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
smtputf8_enable (yes)
- Enable preliminary SMTPUTF8 support for the protocols described
+ Enable preliminary SMTPUTF8 support for the protocols described
in RFC 6531..6533.
smtputf8_autodetect_classes (sendmail, verify)
- Detect that a message requires SMTPUTF8 support for the speci-
+ Detect that a message requires SMTPUTF8 support for the speci-
fied mail origin classes.
Available in Postfix version 3.2 and later:
enable_idna2003_compatibility (no)
- Enable 'transitional' compatibility between IDNA2003 and
- IDNA2008, when converting UTF-8 domain names to/from the ASCII
+ Enable 'transitional' compatibility between IDNA2003 and
+ IDNA2008, when converting UTF-8 domain names to/from the ASCII
form that is used for DNS lookups.
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and master.cf con-
+ The default location of the Postfix main.cf and master.cf con-
figuration files.
daemon_timeout (18000s)
- How much time a Postfix daemon process may take to handle a
+ How much time a Postfix daemon process may take to handle a
request before it is terminated by a built-in watchdog timer.
delay_logging_resolution_limit (2)
- The maximal number of digits after the decimal point when log-
+ The maximal number of digits after the decimal point when log-
ging sub-second delay values.
delay_warning_time (0h)
- The time after which the sender receives a copy of the message
+ The time after which the sender receives a copy of the message
headers of mail that is still queued.
ipc_timeout (3600s)
- The time limit for sending or receiving information over an
+ The time limit for sending or receiving information over an
internal communication channel.
max_idle (100s)
- The maximum amount of time that an idle Postfix daemon process
+ The maximum amount of time that an idle Postfix daemon process
waits for an incoming connection before terminating voluntarily.
max_use (100)
@@ -455,7 +465,7 @@ CLEANUP(8) CLEANUP(8)
The internet hostname of this mail system.
myorigin ($myhostname)
- The domain name that locally-posted mail appears to come from,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
process_id (read-only)
@@ -468,21 +478,21 @@ CLEANUP(8) CLEANUP(8)
The location of the Postfix top-level queue directory.
soft_bounce (no)
- Safety net to keep mail queued that would otherwise be returned
+ Safety net to keep mail queued that would otherwise be returned
to the sender.
syslog_facility (mail)
The syslog facility of Postfix logging.
syslog_name (see 'postconf -d' output)
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix version 2.1 and later:
enable_original_recipient (yes)
- Enable support for the original recipient address after an
- address is rewritten to a different address (for example with
+ Enable support for the original recipient address after an
+ address is rewritten to a different address (for example with
aliasing or with canonical mapping).
Available in Postfix 3.3 and later:
@@ -493,7 +503,7 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix 3.5 and later:
info_log_address_format (external)
- The email address form that will be used in non-debug logging
+ The email address form that will be used in non-debug logging
(info, warning, etc.).
FILES
diff --git a/postfix/html/defer.8.html b/postfix/html/defer.8.html
index 9ad2abb03..31f12cb85 100644
--- a/postfix/html/defer.8.html
+++ b/postfix/html/defer.8.html
@@ -153,6 +153,13 @@ BOUNCE(8) BOUNCE(8)
service_name (read-only)
The master.cf service name of a Postfix daemon process.
+ Available in Postfix 3.6 and later:
+
+ enable_threaded_bounces (no)
+ Enable non-delivery notifications (bounce messages) that link to
+ the original message by including a References: and In-Reply_to:
+ header with the original Message-ID value.
+
FILES
/var/spool/postfix/bounce/* non-delivery records
/var/spool/postfix/defer/* non-delivery records
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index d696afd0d..cf5ecf30c 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -3329,6 +3329,31 @@ Postfix versions before 2.0 have no support for the original recipient
address.
+
+
+enable_threaded_bounces
+(default: no)
+
+ Enable non-delivery notifications (bounce messages) that link
+to the original message by including a References: and In-Reply_to:
+header with the original Message-ID value. There are advantages and
+disadvantages to consider.
+
+
+
+- advantage
- This allows mail readers to present
+a non-delivery notification in the same email thread as the original
+message.
+
+- disadvantage
- This makes it easy for users to
+mistakenly delete the whole email thread (all related messages),
+instead of deleting only the non-delivery notification.
+
+
+
+ This feature is available in Postfix 3.6 and later.
+
+
error_notice_recipient
@@ -13863,8 +13888,8 @@ separator is the colon character.
- example.com
- Match the example.com domain,
-i.e. one of the names the server certificate must be example.com,
-upper and lower case distinctions are ignored.
+i.e. one of the names in the server certificate must be example.com.
+Upper and lower case distinctions are ignored.
- .example.com
- Match subdomains of the example.com domain, i.e. match
@@ -14464,7 +14489,9 @@ in Postfix 3.0 and later.
- check_client_mx_access type:table
- Search the specified access(5) database for the MX hosts for the
-client hostname, and execute the corresponding action. Note: a result
+client hostname, and execute the corresponding action. If no MX
+record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note: a result
of "OK" is not allowed for safety reasons. Instead, use DUNNO in order
to exclude specific hosts from blacklists. This feature is available
in Postfix 2.7 and later.
@@ -14499,7 +14526,9 @@ This feature is available in Postfix 3.0 and later.
- Search the specified access(5) database for the MX hosts for the
unverified reverse client hostname, and execute the corresponding
-action. Note: a result of "OK" is not allowed for safety reasons.
+action. If no MX record is found, look up A or AAAA records, just
+like the Postfix SMTP client would.
+Note: a result of "OK" is not allowed for safety reasons.
Instead, use DUNNO in order to exclude specific hosts from blacklists.
This feature is available in Postfix 2.7 and later.
@@ -15292,6 +15321,8 @@ feature is available in Postfix 3.0 and later.
- Search the specified access(5) database for the MX hosts for
the HELO or EHLO hostname, and execute the corresponding action.
+If no MX record is found, look up A or AAAA records, just like the
+Postfix SMTP client would.
Note 1: a result of "OK" is not allowed for safety reasons. Instead,
use DUNNO in order to exclude specific hosts from blacklists. Note
2: specify "smtpd_helo_required = yes" to fully enforce this
@@ -15879,7 +15910,9 @@ feature is available in Postfix 3.0 and later.
- check_recipient_mx_access type:table
- Search the specified access(5) database for the MX hosts for
-the RCPT TO domain, and execute the corresponding action. Note:
+the RCPT TO domain, and execute the corresponding action. If no
+MX record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note:
a result of "OK" is not allowed for safety reasons. Instead, use
DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
@@ -16737,7 +16770,9 @@ feature is available in Postfix 3.0 and later.
- check_sender_mx_access type:table
- Search the specified access(5) database for the MX hosts for
-the MAIL FROM domain, and execute the corresponding action. Note:
+the MAIL FROM domain, and execute the corresponding action. If no
+MX record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note:
a result of "OK" is not allowed for safety reasons. Instead, use
DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
diff --git a/postfix/html/trace.8.html b/postfix/html/trace.8.html
index 9ad2abb03..31f12cb85 100644
--- a/postfix/html/trace.8.html
+++ b/postfix/html/trace.8.html
@@ -153,6 +153,13 @@ BOUNCE(8) BOUNCE(8)
service_name (read-only)
The master.cf service name of a Postfix daemon process.
+ Available in Postfix 3.6 and later:
+
+ enable_threaded_bounces (no)
+ Enable non-delivery notifications (bounce messages) that link to
+ the original message by including a References: and In-Reply_to:
+ header with the original Message-ID value.
+
FILES
/var/spool/postfix/bounce/* non-delivery records
/var/spool/postfix/defer/* non-delivery records
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index a54362d19..c3223e98a 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -2112,6 +2112,24 @@ This feature is available in Postfix 2.1 and later. Postfix
version 2.0 behaves as if this parameter is always set to \fByes\fR.
Postfix versions before 2.0 have no support for the original recipient
address.
+.SH enable_threaded_bounces (default: no)
+Enable non\-delivery notifications (bounce messages) that link
+to the original message by including a References: and In\-Reply_to:
+header with the original Message\-ID value. There are advantages and
+disadvantages to consider.
+.IP "\fB advantage \fR"
+This allows mail readers to present
+a non\-delivery notification in the same email thread as the original
+message.
+.br
+.IP "\fB disadvantage \fR"
+This makes it easy for users to
+mistakenly delete the whole email thread (all related messages),
+instead of deleting only the non\-delivery notification.
+.br
+.br
+.PP
+This feature is available in Postfix 3.6 and later.
.SH error_notice_recipient (default: postmaster)
The recipient of postmaster notifications about mail delivery
problems that are caused by policy, resource, software or protocol
@@ -9318,8 +9336,8 @@ separator is the colon character.
Patterns specify domain names, or domain name suffixes:
.IP "\fIexample.com\fR"
Match the \fIexample.com\fR domain,
-i.e. one of the names the server certificate must be \fIexample.com\fR,
-upper and lower case distinctions are ignored.
+i.e. one of the names in the server certificate must be \fIexample.com\fR.
+Upper and lower case distinctions are ignored.
.br
.IP "\fI.example.com\fR"
Match subdomains of the \fIexample.com\fR domain, i.e. match
@@ -9735,7 +9753,9 @@ in Postfix 3.0 and later.
.br
.IP "\fBcheck_client_mx_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MX hosts for the
-client hostname, and execute the corresponding action. Note: a result
+client hostname, and execute the corresponding action. If no MX
+record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note: a result
of "OK" is not allowed for safety reasons. Instead, use DUNNO in order
to exclude specific hosts from blacklists. This feature is available
in Postfix 2.7 and later.
@@ -9766,7 +9786,9 @@ This feature is available in Postfix 3.0 and later.
.IP "\fBcheck_reverse_client_hostname_mx_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MX hosts for the
unverified reverse client hostname, and execute the corresponding
-action. Note: a result of "OK" is not allowed for safety reasons.
+action. If no MX record is found, look up A or AAAA records, just
+like the Postfix SMTP client would.
+Note: a result of "OK" is not allowed for safety reasons.
Instead, use DUNNO in order to exclude specific hosts from blacklists.
This feature is available in Postfix 2.7 and later.
.br
@@ -10403,6 +10425,8 @@ feature is available in Postfix 3.0 and later.
.IP "\fBcheck_helo_mx_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MX hosts for
the HELO or EHLO hostname, and execute the corresponding action.
+If no MX record is found, look up A or AAAA records, just like the
+Postfix SMTP client would.
Note 1: a result of "OK" is not allowed for safety reasons. Instead,
use DUNNO in order to exclude specific hosts from blacklists. Note
2: specify "smtpd_helo_required = yes" to fully enforce this
@@ -10803,7 +10827,9 @@ feature is available in Postfix 3.0 and later.
.br
.IP "\fBcheck_recipient_mx_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MX hosts for
-the RCPT TO domain, and execute the corresponding action. Note:
+the RCPT TO domain, and execute the corresponding action. If no
+MX record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note:
a result of "OK" is not allowed for safety reasons. Instead, use
DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
@@ -11472,7 +11498,9 @@ feature is available in Postfix 3.0 and later.
.br
.IP "\fBcheck_sender_mx_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MX hosts for
-the MAIL FROM domain, and execute the corresponding action. Note:
+the MAIL FROM domain, and execute the corresponding action. If no
+MX record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note:
a result of "OK" is not allowed for safety reasons. Instead, use
DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
diff --git a/postfix/man/man8/bounce.8 b/postfix/man/man8/bounce.8
index a91b8a71e..603271c5b 100644
--- a/postfix/man/man8/bounce.8
+++ b/postfix/man/man8/bounce.8
@@ -136,6 +136,12 @@ mail origin classes.
Available in Postfix 3.3 and later:
.IP "\fBservice_name (read\-only)\fR"
The master.cf service name of a Postfix daemon process.
+.PP
+Available in Postfix 3.6 and later:
+.IP "\fBenable_threaded_bounces (no)\fR"
+Enable non\-delivery notifications (bounce messages) that link
+to the original message by including a References: and In\-Reply_to:
+header with the original Message\-ID value.
.SH "FILES"
.na
.nf
diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8
index 69a2940d6..8c07ecac5 100644
--- a/postfix/man/man8/cleanup.8
+++ b/postfix/man/man8/cleanup.8
@@ -16,38 +16,55 @@ The \fBcleanup\fR(8) daemon processes inbound mail, inserts it
into the \fBincoming\fR mail queue, and informs the queue
manager of its arrival.
-The \fBcleanup\fR(8) daemon always performs the following transformations:
+The \fBcleanup\fR(8) daemon performs the following transformations:
.IP \(bu
Insert missing message headers: (\fBResent\-\fR) \fBFrom:\fR,
\fBTo:\fR, \fBMessage\-Id:\fR, and \fBDate:\fR.
+.br
+This is enabled with the \fBlocal_header_rewrite_clients\fR and
+\fBalways_add_missing_headers\fR parameter settings.
.IP \(bu
Transform envelope and header addresses to the standard
\fIuser@fully\-qualified\-domain\fR form that is expected by other
Postfix programs.
-This task is delegated to the \fBtrivial\-rewrite\fR(8) daemon.
+This task depends on the \fBtrivial\-rewrite\fR(8) daemon.
+.br
+The header transformation is enabled with the
+\fBlocal_header_rewrite_clients\fR parameter setting.
.IP \(bu
Eliminate duplicate envelope recipient addresses.
+.br
+This is enabled with the \fBduplicate_filter_limit\fR
+parameter setting.
.IP \(bu
Remove message headers: \fBBcc\fR, \fBContent\-Length\fR,
\fBResent\-Bcc\fR, \fBReturn\-Path\fR.
-.PP
-The following address transformations are optional:
+.br
+This is enabled with the message_drop_headers parameter
+setting.
.IP \(bu
Optionally, rewrite all envelope and header addresses according
to the mappings specified in the \fBcanonical\fR(5) lookup tables.
+.br
+The header transformation is enabled with the
+\fBlocal_header_rewrite_clients\fR parameter setting.
.IP \(bu
Optionally, masquerade envelope sender addresses and message
header addresses (i.e. strip host or domain information below
all domains listed in the \fBmasquerade_domains\fR parameter,
except for user names listed in \fBmasquerade_exceptions\fR).
By default, address masquerading does not affect envelope recipients.
+.br
+The header transformation is enabled with the
+\fBlocal_header_rewrite_clients\fR parameter setting.
.IP \(bu
Optionally, expand envelope recipients according to information
-found in the \fBvirtual\fR(5) lookup tables.
+found in the \fBvirtual_alias_maps\fR lookup tables.
.PP
The \fBcleanup\fR(8) daemon performs sanity checks on the content of
each message. When it finds a problem, by default it returns a
-diagnostic status to the client, and leaves it up to the client
+diagnostic status to the cleanup service client, and leaves
+it up to the client
to deal with the problem. Alternatively, the client can request
the \fBcleanup\fR(8) daemon to bounce the message back to the sender
in case of trouble.
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index 3eee53bd5..551fde9d8 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -773,6 +773,7 @@ while (<>) {
s;\bfrozen_delivered_to\b;$&;g;
s;\breset_owner_alias\b;$&;g;
s;\benable_long_queue_ids\b;$&;g;
+ s;\benable_threaded_bounces\b;$&;g;
# Transport-dependent magical parameters.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index d9cf51cdc..0fbe21134 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -5157,7 +5157,9 @@ in Postfix 3.0 and later.
- check_client_mx_access type:table
- Search the specified access(5) database for the MX hosts for the
-client hostname, and execute the corresponding action. Note: a result
+client hostname, and execute the corresponding action. If no MX
+record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note: a result
of "OK" is not allowed for safety reasons. Instead, use DUNNO in order
to exclude specific hosts from blacklists. This feature is available
in Postfix 2.7 and later.
@@ -5192,7 +5194,9 @@ This feature is available in Postfix 3.0 and later.
- Search the specified access(5) database for the MX hosts for the
unverified reverse client hostname, and execute the corresponding
-action. Note: a result of "OK" is not allowed for safety reasons.
+action. If no MX record is found, look up A or AAAA records, just
+like the Postfix SMTP client would.
+Note: a result of "OK" is not allowed for safety reasons.
Instead, use DUNNO in order to exclude specific hosts from blacklists.
This feature is available in Postfix 2.7 and later.
@@ -5761,6 +5765,8 @@ feature is available in Postfix 3.0 and later.
- Search the specified access(5) database for the MX hosts for
the HELO or EHLO hostname, and execute the corresponding action.
+If no MX record is found, look up A or AAAA records, just like the
+Postfix SMTP client would.
Note 1: a result of "OK" is not allowed for safety reasons. Instead,
use DUNNO in order to exclude specific hosts from blacklists. Note
2: specify "smtpd_helo_required = yes" to fully enforce this
@@ -6047,7 +6053,9 @@ feature is available in Postfix 3.0 and later.
- check_recipient_mx_access type:table
- Search the specified access(5) database for the MX hosts for
-the RCPT TO domain, and execute the corresponding action. Note:
+the RCPT TO domain, and execute the corresponding action. If no
+MX record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note:
a result of "OK" is not allowed for safety reasons. Instead, use
DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
@@ -6558,7 +6566,9 @@ feature is available in Postfix 3.0 and later.
- check_sender_mx_access type:table
- Search the specified access(5) database for the MX hosts for
-the MAIL FROM domain, and execute the corresponding action. Note:
+the MAIL FROM domain, and execute the corresponding action. If no
+MX record is found, look up A or AAAA records, just like the Postfix
+SMTP client would. Note:
a result of "OK" is not allowed for safety reasons. Instead, use
DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
@@ -11408,8 +11418,8 @@ separator is the colon character.
- example.com
- Match the example.com domain,
-i.e. one of the names the server certificate must be example.com,
-upper and lower case distinctions are ignored.
+i.e. one of the names in the server certificate must be example.com.
+Upper and lower case distinctions are ignored.
- .example.com
- Match subdomains of the example.com domain, i.e. match
@@ -17965,3 +17975,24 @@ of the null sender address.
This feature is available in Postfix 3.6 and later.
+
+%PARAM enable_threaded_bounces no
+
+ Enable non-delivery notifications (bounce messages) that link
+to the original message by including a References: and In-Reply_to:
+header with the original Message-ID value. There are advantages and
+disadvantages to consider.
+
+
+
+- advantage
- This allows mail readers to present
+a non-delivery notification in the same email thread as the original
+message.
+
+- disadvantage
- This makes it easy for users to
+mistakenly delete the whole email thread (all related messages),
+instead of deleting only the non-delivery notification.
+
+
+
+ This feature is available in Postfix 3.6 and later.
diff --git a/postfix/src/bounce/Makefile.in b/postfix/src/bounce/Makefile.in
index 80f038f98..cd5ed85fd 100644
--- a/postfix/src/bounce/Makefile.in
+++ b/postfix/src/bounce/Makefile.in
@@ -11,7 +11,7 @@ HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
-TESTPROG=
+TESTPROG= bounce_notify_util_tester
PROG = bounce
SAMPLES = ../../conf/bounce.cf.default
INC_DIR = ../../include
@@ -31,10 +31,6 @@ $(PROG): $(OBJS) $(LIBS)
rm -f $@
./annotate.sh $@
-main.cf:
- echo queue_directory=. >main.cf
- echo myhostname=example.com >>main.cf
-
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
@@ -42,7 +38,13 @@ Makefile: Makefile.in
test: $(TESTPROG)
-tests: update template_test 2template_test
+tests: update template_test 2template_test \
+ with-msgid-with-long-line_test \
+ with-msgid-with-eoh-event_test \
+ with-msgid-no-eoh-event_test \
+ no-msgid-with-eoh-event_test \
+ no-msgid-no-eoh-event_test \
+ with-msgid-with-filter_test
root_tests:
@@ -68,21 +70,244 @@ clean:
tidy: clean
+BOUNCE_NOTIFY_UTIL_TESTER_OBJS = bounce_notify_util_tester.o \
+ bounce_notify_util.o bounce_template.o bounce_templates.o
+
+bounce_notify_util_tester: $(BOUNCE_NOTIFY_UTIL_TESTER_OBJS) $(LIBS)
+ $(CC) -DTEST $(CFLAGS) -o $@ $(BOUNCE_NOTIFY_UTIL_TESTER_OBJS) \
+ $(LIBS) $(SYSLIBS)
+
# Avoid dependency on installed Postfix.
# XXX This still requires that default_privs, mail_owner etc. accounts exist.
-template_test: $(PROG) main.cf template_test.ref
+template_test: $(PROG) template_test.ref
+ echo queue_directory=. >main.cf
+ echo myhostname=example.com >>main.cf
+ touch -t 197101010000 main.cf
MAIL_CONFIG=. ./$(PROG) -SVzndump_templates >template_test.tmp
diff template_test.ref template_test.tmp
MAIL_CONFIG=. ./$(PROG) -SVzndump_templates \
-o bounce_template_file=template_test.ref > template_test.tmp
diff template_test.ref template_test.tmp
- rm -f template_test.tmp
+ rm -f template_test.tmp main.cf
-2template_test: $(PROG) main.cf template_test.ref 2template_test.in
+2template_test: $(PROG) template_test.ref 2template_test.in
+ echo queue_directory=. >main.cf
+ echo myhostname=example.com >>main.cf
+ touch -t 197101010000 main.cf
MAIL_CONFIG=. ./$(PROG) -SVzndump_templates \
-o bounce_template_file=2template_test.in > template_test.tmp
diff template_test.ref template_test.tmp
- rm -f template_test.tmp
+ rm -f template_test.tmp main.cf
+
+with-msgid-with-long-line_test: bounce_notify_util_tester \
+ msgfile-with-msgid-with-long-line logfile-with-msgid-with-long-line \
+ with-msgid-with-long-line-no-thread.ref \
+ with-msgid-with-long-line-with-thread.ref
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = no' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-with-long-line queue/bounce/msgid
+ cp msgfile-with-msgid-with-long-line queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-with-long-line-no-thread.tmp
+ diff with-msgid-with-long-line-no-thread.ref with-msgid-with-long-line-no-thread.tmp
+ rm -f with-msgid-with-long-line-no-thread.tmp
+ :
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = yes' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-with-long-line queue/bounce/msgid
+ cp msgfile-with-msgid-with-long-line queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-with-long-line-with-thread.tmp
+ diff with-msgid-with-long-line-with-thread.ref with-msgid-with-long-line-with-thread.tmp
+ rm -f with-msgid-with-long-line-with-thread.tmp
+ rm -rf queue main.cf
+
+with-msgid-with-eoh-event_test: bounce_notify_util_tester \
+ msgfile-with-msgid-with-eoh-event logfile-with-msgid-with-eoh-event \
+ with-msgid-with-eoh-event-no-thread.ref \
+ with-msgid-with-eoh-event-with-thread.ref
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = no' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-with-eoh-event queue/bounce/msgid
+ cp msgfile-with-msgid-with-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-with-eoh-event-no-thread.tmp
+ diff with-msgid-with-eoh-event-no-thread.ref with-msgid-with-eoh-event-no-thread.tmp
+ rm -f with-msgid-with-eoh-event-no-thread.tmp
+ :
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = yes' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-with-eoh-event queue/bounce/msgid
+ cp msgfile-with-msgid-with-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-with-eoh-event-with-thread.tmp
+ diff with-msgid-with-eoh-event-with-thread.ref with-msgid-with-eoh-event-with-thread.tmp
+ rm -f with-msgid-with-eoh-event-with-thread.tmp
+ rm -rf queue main.cf
+
+with-msgid-no-eoh-event_test: bounce_notify_util_tester \
+ msgfile-with-msgid-no-eoh-event logfile-with-msgid-no-eoh-event \
+ with-msgid-no-eoh-event-no-thread.ref \
+ with-msgid-no-eoh-event-with-thread.ref
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = no' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-no-eoh-event queue/bounce/msgid
+ cp msgfile-with-msgid-no-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-no-eoh-event-no-thread.tmp
+ diff with-msgid-no-eoh-event-no-thread.ref with-msgid-no-eoh-event-no-thread.tmp
+ rm -f with-msgid-no-eoh-event-no-thread.tmp
+ :
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = yes' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-no-eoh-event queue/bounce/msgid
+ cp msgfile-with-msgid-no-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-no-eoh-event-with-thread.tmp
+ diff with-msgid-no-eoh-event-with-thread.ref with-msgid-no-eoh-event-with-thread.tmp
+ rm -f with-msgid-no-eoh-event-with-thread.tmp
+ rm -rf queue main.cf
+
+no-msgid-with-eoh-event_test: bounce_notify_util_tester \
+ msgfile-no-msgid-with-eoh-event logfile-no-msgid-with-eoh-event \
+ no-msgid-with-eoh-event-no-thread.ref \
+ no-msgid-with-eoh-event-with-thread.ref
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = no' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-no-msgid-with-eoh-event queue/bounce/msgid
+ cp msgfile-no-msgid-with-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > no-msgid-with-eoh-event-no-thread.tmp
+ diff no-msgid-with-eoh-event-no-thread.ref no-msgid-with-eoh-event-no-thread.tmp
+ rm -f no-msgid-with-eoh-event-no-thread.tmp
+ :
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = yes' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-no-msgid-with-eoh-event queue/bounce/msgid
+ cp msgfile-no-msgid-with-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > no-msgid-with-eoh-event-with-thread.tmp
+ diff no-msgid-with-eoh-event-with-thread.ref no-msgid-with-eoh-event-with-thread.tmp
+ rm -f no-msgid-with-eoh-event-with-thread.tmp
+ rm -rf queue main.cf
+
+no-msgid-no-eoh-event_test: bounce_notify_util_tester \
+ msgfile-no-msgid-no-eoh-event logfile-no-msgid-no-eoh-event \
+ no-msgid-no-eoh-event-no-thread.ref \
+ no-msgid-no-eoh-event-with-thread.ref
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = no' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-no-msgid-no-eoh-event queue/bounce/msgid
+ cp msgfile-no-msgid-no-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > no-msgid-no-eoh-event-no-thread.tmp
+ diff no-msgid-no-eoh-event-no-thread.ref no-msgid-no-eoh-event-no-thread.tmp
+ rm -f no-msgid-no-eoh-event-no-thread.tmp
+ :
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = yes' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-no-msgid-no-eoh-event queue/bounce/msgid
+ cp msgfile-no-msgid-no-eoh-event queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > no-msgid-no-eoh-event-with-thread.tmp
+ diff no-msgid-no-eoh-event-with-thread.ref no-msgid-no-eoh-event-with-thread.tmp
+ rm -f no-msgid-no-eoh-event-with-thread.tmp
+ rm -rf queue main.cf
+
+with-msgid-with-filter_test: bounce_notify_util_tester \
+ msgfile-with-msgid-with-filter logfile-with-msgid-with-filter \
+ with-msgid-with-filter-no-thread.ref \
+ with-msgid-with-filter-with-thread.ref
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = no' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-with-filter queue/bounce/msgid
+ cp msgfile-with-msgid-with-filter queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-with-filter-no-thread.tmp
+ diff with-msgid-with-filter-no-thread.ref with-msgid-with-filter-no-thread.tmp
+ rm -f with-msgid-with-filter-no-thread.tmp
+ :
+ rm -rf queue main.cf
+ echo 'enable_threaded_bounces = yes' >main.cf
+ echo 'queue_directory = queue' >>main.cf
+ echo 'myhostname = mail.example' >>main.cf
+ touch -t 197101010000 main.cf
+ mkdir -p queue/active queue/bounce
+ cp logfile-with-msgid-with-filter queue/bounce/msgid
+ cp msgfile-with-msgid-with-filter queue/active/msgid
+ $(SHLIB_ENV) $(VALGRIND) ./bounce_notify_util_tester \
+ -c. bounce active msgid 2>&1 | \
+ sed 's;msgid.[0-9]*/mail.example;msgid.unix-time/mail.example;' \
+ > with-msgid-with-filter-with-thread.tmp
+ diff with-msgid-with-filter-with-thread.ref with-msgid-with-filter-with-thread.tmp
+ rm -f with-msgid-with-filter-with-thread.tmp
+ rm -rf queue main.cf
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
@@ -216,6 +441,7 @@ bounce_notify_util.o: ../../include/dsn.h
bounce_notify_util.o: ../../include/dsn_buf.h
bounce_notify_util.o: ../../include/dsn_mask.h
bounce_notify_util.o: ../../include/events.h
+bounce_notify_util.o: ../../include/header_opts.h
bounce_notify_util.o: ../../include/htable.h
bounce_notify_util.o: ../../include/int_filt.h
bounce_notify_util.o: ../../include/iostuff.h
@@ -249,6 +475,30 @@ bounce_notify_util.o: ../../include/vstring.h
bounce_notify_util.o: bounce_notify_util.c
bounce_notify_util.o: bounce_service.h
bounce_notify_util.o: bounce_template.h
+bounce_notify_util_tester.o: ../../include/attr.h
+bounce_notify_util_tester.o: ../../include/bounce_log.h
+bounce_notify_util_tester.o: ../../include/check_arg.h
+bounce_notify_util_tester.o: ../../include/dsn.h
+bounce_notify_util_tester.o: ../../include/dsn_buf.h
+bounce_notify_util_tester.o: ../../include/dsn_mask.h
+bounce_notify_util_tester.o: ../../include/htable.h
+bounce_notify_util_tester.o: ../../include/mail_conf.h
+bounce_notify_util_tester.o: ../../include/mail_params.h
+bounce_notify_util_tester.o: ../../include/msg.h
+bounce_notify_util_tester.o: ../../include/mymalloc.h
+bounce_notify_util_tester.o: ../../include/nvtable.h
+bounce_notify_util_tester.o: ../../include/rcpt_buf.h
+bounce_notify_util_tester.o: ../../include/rec_type.h
+bounce_notify_util_tester.o: ../../include/recipient_list.h
+bounce_notify_util_tester.o: ../../include/record.h
+bounce_notify_util_tester.o: ../../include/sys_defs.h
+bounce_notify_util_tester.o: ../../include/test_main.h
+bounce_notify_util_tester.o: ../../include/vbuf.h
+bounce_notify_util_tester.o: ../../include/vstream.h
+bounce_notify_util_tester.o: ../../include/vstring.h
+bounce_notify_util_tester.o: bounce_notify_util_tester.c
+bounce_notify_util_tester.o: bounce_service.h
+bounce_notify_util_tester.o: bounce_template.h
bounce_notify_verp.o: ../../include/attr.h
bounce_notify_verp.o: ../../include/bounce.h
bounce_notify_verp.o: ../../include/bounce_log.h
diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c
index c6c979033..1c3619c21 100644
--- a/postfix/src/bounce/bounce.c
+++ b/postfix/src/bounce/bounce.c
@@ -124,6 +124,12 @@
/* Available in Postfix 3.3 and later:
/* .IP "\fBservice_name (read-only)\fR"
/* The master.cf service name of a Postfix daemon process.
+/* .PP
+/* Available in Postfix 3.6 and later:
+/* .IP "\fBenable_threaded_bounces (no)\fR"
+/* Enable non-delivery notifications (bounce messages) that link
+/* to the original message by including a References: and In-Reply_to:
+/* header with the original Message-ID value.
/* FILES
/* /var/spool/postfix/bounce/* non-delivery records
/* /var/spool/postfix/defer/* non-delivery records
@@ -197,6 +203,7 @@ char *var_bounce_rcpt;
char *var_2bounce_rcpt;
char *var_delay_rcpt;
char *var_bounce_tmpl;
+bool var_threaded_bounce;
/*
* We're single threaded, so we can avoid some memory allocation overhead.
@@ -668,6 +675,10 @@ int main(int argc, char **argv)
VAR_BOUNCE_TMPL, DEF_BOUNCE_TMPL, &var_bounce_tmpl, 0, 0,
0,
};
+ static const CONFIG_NBOOL_TABLE nbool_table[] = {
+ VAR_THREADED_BOUNCE, DEF_THREADED_BOUNCE, &var_threaded_bounce,
+ 0,
+ };
/*
* Fingerprint executables and core dumps.
@@ -681,6 +692,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_INT_TABLE(int_table),
CA_MAIL_SERVER_STR_TABLE(str_table),
CA_MAIL_SERVER_TIME_TABLE(time_table),
+ CA_MAIL_SERVER_NBOOL_TABLE(nbool_table),
CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_UNLIMITED,
diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c
index 7c79ca0aa..a314729ab 100644
--- a/postfix/src/bounce/bounce_notify_util.c
+++ b/postfix/src/bounce/bounce_notify_util.c
@@ -206,12 +206,14 @@
#include
#include
#include
+#include
/* Application-specific. */
#include "bounce_service.h"
#define STR vstring_str
+#define LEN VSTRING_LEN
/* bounce_mail_alloc - initialize */
@@ -228,6 +230,10 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
{
BOUNCE_INFO *bounce_info;
int rec_type;
+ int prev_type;
+ int all_headers_seen = 0;
+ int skip_message_segment = 0;
+ int in_envelope = 1;
/*
* Bundle up a bunch of parameters and initialize information that will
@@ -266,6 +272,7 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
bounce_info->arrival_time = 0;
bounce_info->orig_offs = 0;
bounce_info->message_size = 0;
+ bounce_info->orig_msgid = vstring_alloc(100);
bounce_info->rcpt_buf = rcpt_buf;
bounce_info->dsn_buf = dsn_buf;
bounce_info->log_handle = log_handle;
@@ -315,8 +322,9 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
DELIVER_LOCK_MODE) < 0)
msg_fatal("cannot get shared lock on %s: %m",
VSTREAM_PATH(bounce_info->orig_fp));
- while ((rec_type = rec_get(bounce_info->orig_fp,
- bounce_info->buf, 0)) > 0) {
+ for (prev_type = 0;
+ (rec_type = rec_get(bounce_info->orig_fp, bounce_info->buf, 0)) > 0;
+ prev_type = rec_type) {
/*
* Postfix version dependent: data offset in SIZE record.
@@ -360,12 +368,101 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
msg_warn("%s: no sender before message content record",
bounce_info->queue_id);
bounce_info->orig_offs = vstream_ftell(bounce_info->orig_fp);
- break;
+ if (var_threaded_bounce == 0)
+ skip_message_segment = 1;
+ else
+ in_envelope = 0;
+ }
+
+ /*
+ * Extract Message-ID for threaded bounces.
+ */
+ else if (in_envelope == 0
+ && (rec_type == REC_TYPE_NORM || rec_type == REC_TYPE_CONT)) {
+ const HEADER_OPTS *hdr;
+ char *cp;
+
+ /*
+ * Skip records that we cannot use. Degrade if we could not
+ * skip over the message content.
+ */
+ if (var_threaded_bounce == 0 || all_headers_seen
+ || prev_type == REC_TYPE_CONT) {
+ /* void */ ;
+ }
+
+ /*
+ * Extract message-id header value.
+ */
+ else if (is_header(STR(bounce_info->buf))) {
+ if ((hdr = header_opts_find(
+ vstring_str(bounce_info->buf))) != 0
+ && hdr->type == HDR_MESSAGE_ID) {
+ vstring_truncate(bounce_info->buf,
+ trimblanks(STR(bounce_info->buf),
+ LEN(bounce_info->buf))
+ - STR(bounce_info->buf));
+ cp = STR(bounce_info->buf) + strlen(hdr->name) + 1;
+ while (ISSPACE(*cp))
+ cp++;
+ if (*cp == '<' && vstring_end(bounce_info->buf)[-1] == '>')
+ vstring_strcpy(bounce_info->orig_msgid, cp);
+ else
+ msg_warn("%s: ignoring malformed Message-ID",
+ bounce_info->queue_id);
+ }
+ }
+
+ /*
+ * Skip remainder of multiline header.
+ */
+ else if (ISSPACE(*STR(bounce_info->buf))) {
+ /* void */ ;
+ }
+
+ /*
+ * Start of body.
+ */
+ else {
+ all_headers_seen = 1;
+ skip_message_segment = 1;
+ }
}
+
+ /*
+ * In case we ever want to process records from the extracted
+ * segment, and in case there was no "start of body" event.
+ */
+ else if (rec_type == REC_TYPE_XTRA) {
+ if (VSTRING_LEN(bounce_info->orig_msgid) == 0)
+ if (var_threaded_bounce)
+ all_headers_seen = 1;
+ in_envelope = 1;
+ }
+
+ /*
+ * Are we done yet?
+ */
if (bounce_info->orig_offs > 0
&& bounce_info->arrival_time > 0
- && VSTRING_LEN(bounce_info->sender) > 0)
+ && VSTRING_LEN(bounce_info->sender) > 0
+ && (var_threaded_bounce == 0 || all_headers_seen
+ || VSTRING_LEN(bounce_info->orig_msgid) > 0)) {
break;
+ }
+
+ /*
+ * Skip over (the remainder of) the message segment. If that
+ * fails, degrade.
+ */
+ if (skip_message_segment) {
+ if (vstream_fseek(bounce_info->orig_fp,
+ bounce_info->orig_offs +
+ bounce_info->message_size,
+ SEEK_SET) < 0)
+ /* void */ ;
+ skip_message_segment = 0;
+ }
}
}
return (bounce_info);
@@ -439,6 +536,7 @@ void bounce_mail_free(BOUNCE_INFO *bounce_info)
if (bounce_log_close(bounce_info->log_handle))
msg_warn("%s: read bounce log %s: %m",
bounce_info->queue_id, bounce_info->queue_id);
+ vstring_free(bounce_info->orig_msgid);
rcpb_free(bounce_info->rcpt_buf);
dsb_free(bounce_info->dsn_buf);
}
@@ -474,6 +572,15 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
STR(quote_822_local(bounce_info->buf, dest)),
postmaster_copy);
+ /*
+ * References and Reply-To header that references the original message-id
+ * for better threading in MUAs.
+ */
+ if (VSTRING_LEN(bounce_info->orig_msgid) > 0) {
+ post_mail_fprintf(bounce, "References: %s", STR(bounce_info->orig_msgid));
+ post_mail_fprintf(bounce, "In-Reply-To: %s", STR(bounce_info->orig_msgid));
+ }
+
/*
* Auto-Submitted header, as per RFC 3834.
*/
diff --git a/postfix/src/bounce/bounce_notify_util_tester.c b/postfix/src/bounce/bounce_notify_util_tester.c
new file mode 100644
index 000000000..b8abdd730
--- /dev/null
+++ b/postfix/src/bounce/bounce_notify_util_tester.c
@@ -0,0 +1,159 @@
+ /*
+ * System library.
+ */
+#include
+#include
+#include
+
+ /*
+ * Utility library.
+ */
+#include
+#include
+#include
+
+ /*
+ * Global library.
+ */
+#include
+#include
+#include
+#include
+
+ /*
+ * Bounce service.
+ */
+#include
+#include
+
+ /*
+ * Testing library.
+ */
+#include
+
+#define TEST_ENCODING "7bit"
+#define NO_SMTPUTF8 (0)
+#define TEST_DSN_ENVID "TEST-ENVID"
+#define TEST_RECIPIENT "test-recipient"
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+/* test_driver - test driver */
+
+static void test_driver(int argc, char **argv)
+{
+ BOUNCE_TEMPLATES *bounce_templates;
+ BOUNCE_INFO *bounce_info;
+ VSTRING *message_buf;
+ VSTREAM *message_stream;
+ VSTRING *rec_buf;
+ int rec_type;
+
+ /*
+ * Sanity checks.
+ */
+ if (argc != 4)
+ msg_fatal("usage: %s [options] service queue_name queue_id", argv[0]);
+
+ if (chdir(var_queue_dir) < 0)
+ msg_fatal("chdir %s: %m", var_queue_dir);
+
+ /*
+ * Write one message to VSTRING.
+ */
+ message_buf = vstring_alloc(100);
+ if ((message_stream = vstream_memopen(message_buf, O_WRONLY)) == 0)
+ msg_fatal("vstream_memopen O_WRONLY: %m");
+ bounce_templates = bounce_templates_create();
+ bounce_info = bounce_mail_init(argv[1], argv[2], argv[3],
+ TEST_ENCODING, NO_SMTPUTF8, TEST_DSN_ENVID,
+ bounce_templates->failure);
+ if (bounce_header(message_stream, bounce_info, TEST_RECIPIENT,
+ NO_POSTMASTER_COPY) < 0)
+ msg_fatal("bounce_header: %m");
+ if (bounce_diagnostic_log(message_stream, bounce_info,
+ DSN_NOTIFY_OVERRIDE) <= 0)
+ msg_fatal("bounce_diagnostic_log: %m");
+ if (bounce_header_dsn(message_stream, bounce_info) != 0)
+ msg_fatal("bounce_header_dsn: %m");
+ if (bounce_diagnostic_dsn(message_stream, bounce_info,
+ DSN_NOTIFY_OVERRIDE) <= 0)
+ msg_fatal("bounce_diagnostic_dsn: %m");
+ bounce_original(message_stream, bounce_info, DSN_RET_FULL);
+ if (vstream_fclose(message_stream) != 0)
+ msg_fatal("vstream_fclose: %m");
+ bounce_mail_free(bounce_info);
+
+ /*
+ * Render the bounce message in human-readable form.
+ */
+ if ((message_stream = vstream_memopen(message_buf, O_RDONLY)) == 0)
+ msg_fatal("vstream_memopen O_RDONLY: %m");
+ rec_buf = vstring_alloc(100);
+ while ((rec_type = rec_get(message_stream, rec_buf, 0)) > 0) {
+ switch (rec_type) {
+ case REC_TYPE_CONT:
+ vstream_printf("%.*s", (int) LEN(rec_buf), STR(rec_buf));
+ break;
+ case REC_TYPE_NORM:
+ vstream_printf("%.*s\n", (int) LEN(rec_buf), STR(rec_buf));
+ break;
+ default:
+ msg_panic("unexpected message record type %d", rec_type);
+ }
+ vstream_fflush(VSTREAM_OUT);
+ }
+ if (vstream_fclose(message_stream) != 0)
+ msg_fatal("vstream_fclose: %m");
+ vstring_free(rec_buf);
+
+ /*
+ * Clean up.
+ */
+ exit(0);
+}
+
+int var_bounce_limit;
+int var_max_queue_time;
+int var_delay_warn_time;
+char *var_notify_classes;
+char *var_bounce_rcpt;
+char *var_2bounce_rcpt;
+char *var_delay_rcpt;
+char *var_bounce_tmpl;
+bool var_threaded_bounce;
+
+int main(int argc, char **argv)
+{
+ static const CONFIG_INT_TABLE int_table[] = {
+ VAR_BOUNCE_LIMIT, DEF_BOUNCE_LIMIT, &var_bounce_limit, 1, 0,
+ 0,
+ };
+ static const CONFIG_TIME_TABLE time_table[] = {
+ VAR_MAX_QUEUE_TIME, DEF_MAX_QUEUE_TIME, &var_max_queue_time, 0, 8640000,
+ VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0,
+ 0,
+ };
+ static const CONFIG_STR_TABLE str_table[] = {
+ VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
+ VAR_BOUNCE_RCPT, DEF_BOUNCE_RCPT, &var_bounce_rcpt, 1, 0,
+ VAR_2BOUNCE_RCPT, DEF_2BOUNCE_RCPT, &var_2bounce_rcpt, 1, 0,
+ VAR_DELAY_RCPT, DEF_DELAY_RCPT, &var_delay_rcpt, 1, 0,
+ VAR_BOUNCE_TMPL, DEF_BOUNCE_TMPL, &var_bounce_tmpl, 0, 0,
+ 0,
+ };
+ static const CONFIG_NBOOL_TABLE nbool_table[] = {
+ VAR_THREADED_BOUNCE, DEF_THREADED_BOUNCE, &var_threaded_bounce,
+ 0,
+ };
+
+ test_main(argc, argv, test_driver,
+ CA_TEST_MAIN_INT_TABLE(int_table),
+ CA_TEST_MAIN_STR_TABLE(str_table),
+ CA_TEST_MAIN_TIME_TABLE(time_table),
+ CA_TEST_MAIN_NBOOL_TABLE(nbool_table),
+ 0);
+
+ exit(0);
+}
diff --git a/postfix/src/bounce/bounce_service.h b/postfix/src/bounce/bounce_service.h
index f8cc4d6dc..40793f2ff 100644
--- a/postfix/src/bounce/bounce_service.h
+++ b/postfix/src/bounce/bounce_service.h
@@ -80,6 +80,7 @@ typedef struct {
long orig_offs; /* start of content */
time_t arrival_time; /* time of arrival */
long message_size; /* size of content */
+ VSTRING *orig_msgid; /* original message-id */
RCPT_BUF *rcpt_buf; /* recipient info */
DSN_BUF *dsn_buf; /* delivery status info */
BOUNCE_LOG *log_handle; /* open logfile */
diff --git a/postfix/src/bounce/logfile-no-msgid-no-eoh-event b/postfix/src/bounce/logfile-no-msgid-no-eoh-event
new file mode 100644
index 000000000..50233c817
--- /dev/null
+++ b/postfix/src/bounce/logfile-no-msgid-no-eoh-event
@@ -0,0 +1,13 @@
+
+recipient = rcpt-address
+original_recipient = rcpt-orig_addr
+offset = 272
+notify_flags = rcpt-dsn_notify
+status = dsn-status
+action = dsn-action
+diag_type = dsn-dtype
+diag_text = dsn-dtext
+mta_type = dsn-mtype
+mta_mname = dsn-mname
+reason = dsn-reason
+
diff --git a/postfix/src/bounce/logfile-no-msgid-with-eoh-event b/postfix/src/bounce/logfile-no-msgid-with-eoh-event
new file mode 100644
index 000000000..00473a8e2
--- /dev/null
+++ b/postfix/src/bounce/logfile-no-msgid-with-eoh-event
@@ -0,0 +1,13 @@
+
+recipient = rcpt-address
+original_recipient = rcpt-orig_addr
+offset = 271
+notify_flags = rcpt-dsn_notify
+status = dsn-status
+action = dsn-action
+diag_type = dsn-dtype
+diag_text = dsn-dtext
+mta_type = dsn-mtype
+mta_mname = dsn-mname
+reason = dsn-reason
+
diff --git a/postfix/src/bounce/logfile-with-msgid-no-eoh-event b/postfix/src/bounce/logfile-with-msgid-no-eoh-event
new file mode 100644
index 000000000..00473a8e2
--- /dev/null
+++ b/postfix/src/bounce/logfile-with-msgid-no-eoh-event
@@ -0,0 +1,13 @@
+
+recipient = rcpt-address
+original_recipient = rcpt-orig_addr
+offset = 271
+notify_flags = rcpt-dsn_notify
+status = dsn-status
+action = dsn-action
+diag_type = dsn-dtype
+diag_text = dsn-dtext
+mta_type = dsn-mtype
+mta_mname = dsn-mname
+reason = dsn-reason
+
diff --git a/postfix/src/bounce/logfile-with-msgid-with-eoh-event b/postfix/src/bounce/logfile-with-msgid-with-eoh-event
new file mode 100644
index 000000000..00473a8e2
--- /dev/null
+++ b/postfix/src/bounce/logfile-with-msgid-with-eoh-event
@@ -0,0 +1,13 @@
+
+recipient = rcpt-address
+original_recipient = rcpt-orig_addr
+offset = 271
+notify_flags = rcpt-dsn_notify
+status = dsn-status
+action = dsn-action
+diag_type = dsn-dtype
+diag_text = dsn-dtext
+mta_type = dsn-mtype
+mta_mname = dsn-mname
+reason = dsn-reason
+
diff --git a/postfix/src/bounce/logfile-with-msgid-with-filter b/postfix/src/bounce/logfile-with-msgid-with-filter
new file mode 100644
index 000000000..4d5621662
--- /dev/null
+++ b/postfix/src/bounce/logfile-with-msgid-with-filter
@@ -0,0 +1,13 @@
+
+recipient = rcpt-address
+original_recipient = rcpt-orig_addr
+offset = 291
+notify_flags = rcpt-dsn_notify
+status = dsn-status
+action = dsn-action
+diag_type = dsn-dtype
+diag_text = dsn-dtext
+mta_type = dsn-mtype
+mta_mname = dsn-mname
+reason = dsn-reason
+
diff --git a/postfix/src/bounce/logfile-with-msgid-with-long-line b/postfix/src/bounce/logfile-with-msgid-with-long-line
new file mode 100644
index 000000000..00473a8e2
--- /dev/null
+++ b/postfix/src/bounce/logfile-with-msgid-with-long-line
@@ -0,0 +1,13 @@
+
+recipient = rcpt-address
+original_recipient = rcpt-orig_addr
+offset = 271
+notify_flags = rcpt-dsn_notify
+status = dsn-status
+action = dsn-action
+diag_type = dsn-dtype
+diag_text = dsn-dtext
+mta_type = dsn-mtype
+mta_mname = dsn-mname
+reason = dsn-reason
+
diff --git a/postfix/src/bounce/msgfile-no-msgid-no-eoh-event b/postfix/src/bounce/msgfile-no-msgid-no-eoh-event
new file mode 100755
index 0000000000000000000000000000000000000000..694f5dbbf3a737ca310f79fd72f01a87bbe014ff
GIT binary patch
literal 522
zc-noCK~KU!5QRB-@#sM=1~c9u0@;>Yr3ir#IcTT^Ffm>l*bcZzcbe_eR(`#k7!{4_
zOD1n7-@MIch5;PNwyq9GXt5Ujmi1?5P?R@(eqy=Ib=!_9u#C6eL76LDXbiN7u=|4t
zWrdj%25^!ZbKO-Kk;c)HBGR+d1Z9Y-|7lIk7g4;$0SglukP_=a@z_LG{KmFB3b}{{
zO5OkNz7mgT1#nsf$0h%IiX26Xp$E%%$o6S7CdGHLkk}-(hU$b8y%KpHR*E9nC8$IQ
ztmb>i#+~8YHlA4bn}@xVIWHX;ldPL7gHI{g%x1ut#~jaY!zD9<>eGB!^D86smIt^0
o9-!x6%*nulfA{?J*>1T(u04>{h?2Dk8>T^eZD48^pG$Y8570556951J
literal 0
Hc-jL100001
diff --git a/postfix/src/bounce/msgfile-no-msgid-with-eoh-event b/postfix/src/bounce/msgfile-no-msgid-with-eoh-event
new file mode 100755
index 0000000000000000000000000000000000000000..b3b795e8646db52a5eaa28f0111c72e7710dbf98
GIT binary patch
literal 536
zc-noC-%A2P5XbMK7vFlxmk6deC6&GP{B@=%mIUDzY7o5~x;NUEw|nfZcj{l?MpP!@
z7lzs4Gv8(S4g%N{t&;r_s)WK{xd-##{X@Uy(^I!j>h)I5bt$-wX3Oj6xyG5nz=#Mt
zzqFs%m}y}FSJL3dbTmfF;P6B%WhQ3{$`Ez$t5t9_i{cgbNtnn$X|W76kF90Fo0PUS
zauExZruXyuc08OPf#YLvuz*Y#@@u80*Bo~DB$yBONP
ze7OEMfG)e7DhrR?-DNOY&)<+6AEYWr$x?*nOqka)DqE>tWe&^DRk(%E+@GCW=L4Iu
BqR#*T
literal 0
Hc-jL100001
diff --git a/postfix/src/bounce/msgfile-with-msgid-no-eoh-event b/postfix/src/bounce/msgfile-with-msgid-no-eoh-event
new file mode 100755
index 0000000000000000000000000000000000000000..cc16c666f15b6cd1c8d8ab6dec973c83fe9e93f7
GIT binary patch
literal 606
zc-oDTK~KU!5QRB-@#q0B#$-%9K%it>O2r}sf|7V(C4dQ@nz9|rD(yDgr3HSyn;1oi
zA->DZi%Tk6E9aM;P@0A7UaO*Aw>l1
z6eSOUl&O2Jquu|QjowJKr8_&f!xl`|aTTn4pdtf{SOm<5TPLo*RE20k>2=yK)9ZoW
z<-)_C2k6k7snGC*?+(2kVw(CP8qeDJgK5?6MmJKv5&IGDyR@D8J2K@$&ehV0(vSy6
XEDRJ&12eslRvz`+-2d606`l&8YCN@7
literal 0
Hc-jL100001
diff --git a/postfix/src/bounce/msgfile-with-msgid-with-eoh-event b/postfix/src/bounce/msgfile-with-msgid-with-eoh-event
new file mode 100755
index 0000000000000000000000000000000000000000..ffe30c46f83597e7af1d343ca8ff8a7f4ca451e5
GIT binary patch
literal 621
zc-oDT%TK~U5XO7(!qEd>jLB#`K%iv%;9+?Lf|7Wk62JscP1z20we2?B<@wjUY7{Ys
z_$8Z}$!}-!Wv1`J4_QVP4r*e;p^RTOfn)uOPfv{+snu#$!#2RM>NYWZXH=js(UUC3
z_8#~00@s2mKzSl@Bij+Del$1{oXbf*!z4h_{R|b{_;DIxj|5rbalt}Q&{Vd?f;LRE
zDUh<1VIsTV*;mKI`4Koi28WtkA0tJ!!oY#~7S_8}CFO!HQj(a)f3Lf#@aj%D%WqyeIy)xc1Ov|ozW9jROALIVl)nqw;K`I?sGx@B?
iS;zwYBSo&>N{w_&x9V`tKaFc{Zq9=(yx(%B-Dz*}N4ft1
literal 0
Hc-jL100001
diff --git a/postfix/src/bounce/msgfile-with-msgid-with-filter b/postfix/src/bounce/msgfile-with-msgid-with-filter
new file mode 100755
index 0000000000000000000000000000000000000000..d6e77c4a74ef7ce541c5952316d1e4004b89d0ca
GIT binary patch
literal 581
zc-noCO;5r=5QaH;@yJ0g#$-%9K%`{5ZK0HpKu{8mR0EjksVUn5*4W)SmmgA0;CcKrzX0C?7orKb*6Ui#(izUB-T{`4{neFC6s{e2aX-M
zK3o$cC_hgJmGEL{W(Cmx_W|ATaw-ixvUfMU8eyKt3$*Uc;%%EcuGdR-Y>7C&XQdw<#O4rcsA&=>XODX
zl^81QDVAbw8aIj($CBxQ3a)UXYKfp>axy1{Q0-!lJVIH2TS_jD5W`wO-;dvq0YavB8!pMjI1B@R>rA$aV%oxX#kTGmt
zid+rYWCsRPq%h1;vIxjl;Lq#TYu
z+9n!oUUiyV!Rm=V%ZGy>8*mt`b%YLQ-23qCY4Q42H++QBhlybrhG7{0MDV;|nqU})
zVHkh (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 19:04:29 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CklpP1JjKz4w4Z; Mon, 30 Nov 2020 00:04:29 +0000 (UTC)
+From:
+To:
+Subject: no-msgid-no-eoh-event
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/no-msgid-no-eoh-event-with-thread.ref b/postfix/src/bounce/no-msgid-no-eoh-event-with-thread.ref
new file mode 100644
index 000000000..0ec87a9aa
--- /dev/null
+++ b/postfix/src/bounce/no-msgid-no-eoh-event-with-thread.ref
@@ -0,0 +1,47 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 19:04:29 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CklpP1JjKz4w4Z; Mon, 30 Nov 2020 00:04:29 +0000 (UTC)
+From:
+To:
+Subject: no-msgid-no-eoh-event
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/no-msgid-with-eoh-event-no-thread.ref b/postfix/src/bounce/no-msgid-with-eoh-event-no-thread.ref
new file mode 100644
index 000000000..8741e085f
--- /dev/null
+++ b/postfix/src/bounce/no-msgid-with-eoh-event-no-thread.ref
@@ -0,0 +1,49 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 19:11:52 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4Cklyw0HDKz4w4Z; Mon, 30 Nov 2020 00:11:52 +0000 (UTC)
+From:
+To:
+Subject: no-msgid-with-eoh-event
+
+body text
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/no-msgid-with-eoh-event-with-thread.ref b/postfix/src/bounce/no-msgid-with-eoh-event-with-thread.ref
new file mode 100644
index 000000000..8741e085f
--- /dev/null
+++ b/postfix/src/bounce/no-msgid-with-eoh-event-with-thread.ref
@@ -0,0 +1,49 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 19:11:52 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4Cklyw0HDKz4w4Z; Mon, 30 Nov 2020 00:11:52 +0000 (UTC)
+From:
+To:
+Subject: no-msgid-with-eoh-event
+
+body text
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-no-eoh-event-no-thread.ref b/postfix/src/bounce/with-msgid-no-eoh-event-no-thread.ref
new file mode 100644
index 000000000..3798b6f16
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-no-eoh-event-no-thread.ref
@@ -0,0 +1,49 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 10:30:41 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CkXPY0myNz4w4g; Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+From:
+To:
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-no-eoh-event
+Date: Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-no-eoh-event-with-thread.ref b/postfix/src/bounce/with-msgid-no-eoh-event-with-thread.ref
new file mode 100644
index 000000000..30ee63a40
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-no-eoh-event-with-thread.ref
@@ -0,0 +1,51 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+References: <12345@mta-name.example>
+In-Reply-To: <12345@mta-name.example>
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 10:30:41 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CkXPY0myNz4w4g; Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+From:
+To:
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-no-eoh-event
+Date: Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-with-eoh-event-no-thread.ref b/postfix/src/bounce/with-msgid-with-eoh-event-no-thread.ref
new file mode 100644
index 000000000..67bc27d1e
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-with-eoh-event-no-thread.ref
@@ -0,0 +1,51 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 10:30:41 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CkXPY10M8z4w4l; Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+From:
+To:
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-with-eoh-event
+Date: Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+
+body text
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-with-eoh-event-with-thread.ref b/postfix/src/bounce/with-msgid-with-eoh-event-with-thread.ref
new file mode 100644
index 000000000..eb1e126fd
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-with-eoh-event-with-thread.ref
@@ -0,0 +1,53 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+References: <12345@mta-name.example>
+In-Reply-To: <12345@mta-name.example>
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 10:30:41 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CkXPY10M8z4w4l; Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+From:
+To:
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-with-eoh-event
+Date: Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+
+body text
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-with-filter-no-thread.ref b/postfix/src/bounce/with-msgid-with-filter-no-thread.ref
new file mode 100644
index 000000000..0666540af
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-with-filter-no-thread.ref
@@ -0,0 +1,48 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sat, 5 Dec 2020 13:31:48 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CpJ7m6tprz4w4Y; Sat, 5 Dec 2020 18:31:48 +0000 (UTC)
+From:
+To:
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-no-eoh-event
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-with-filter-with-thread.ref b/postfix/src/bounce/with-msgid-with-filter-with-thread.ref
new file mode 100644
index 000000000..520c3b832
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-with-filter-with-thread.ref
@@ -0,0 +1,50 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+References: <12345@mta-name.example>
+In-Reply-To: <12345@mta-name.example>
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sat, 5 Dec 2020 13:31:48 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CpJ7m6tprz4w4Y; Sat, 5 Dec 2020 18:31:48 +0000 (UTC)
+From:
+To:
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-no-eoh-event
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-with-long-line-no-thread.ref b/postfix/src/bounce/with-msgid-with-long-line-no-thread.ref
new file mode 100644
index 000000000..b26a05250
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-with-long-line-no-thread.ref
@@ -0,0 +1,50 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 10:30:41 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CkXPY194lz4w4n; Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+From:
+To:
+Whatever: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-with-long-line
+Date: Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/bounce/with-msgid-with-long-line-with-thread.ref b/postfix/src/bounce/with-msgid-with-long-line-with-thread.ref
new file mode 100644
index 000000000..c22838ad2
--- /dev/null
+++ b/postfix/src/bounce/with-msgid-with-long-line-with-thread.ref
@@ -0,0 +1,52 @@
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+To: test-recipient
+References: <12345@mta-name.example>
+In-Reply-To: <12345@mta-name.example>
+Auto-Submitted: auto-replied
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="msgid.unix-time/mail.example"
+Content-Transfer-Encoding: 7bit
+
+This is a MIME-encapsulated message.
+
+--msgid.unix-time/mail.example
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+
+ (expanded from ): dsn-reason
+
+--msgid.unix-time/mail.example
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mail.example
+Original-Envelope-Id: TEST-ENVID
+X-Postfix-Queue-ID: msgid
+X-Postfix-Sender: rfc822; sender@sender.example
+Arrival-Date: Sun, 29 Nov 2020 10:30:41 -0500 (EST)
+
+Final-Recipient: rfc822; rcpt-address
+Original-Recipient: rfc822; rcpt-orig_addr
+Action: failed
+Status: dsn-status
+Remote-MTA: dsn-mtype; dsn-mname
+Diagnostic-Code: dsn-dtype; dsn-dtext
+
+--msgid.unix-time/mail.example
+Content-Description: Undelivered Message
+Content-Type: message/rfc822
+
+Return-Path:
+Received: by wzv.porcupine.org (Postfix, from userid 0)
+ id 4CkXPY194lz4w4n; Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+From:
+To:
+Whatever: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Message-Id: <12345@mta-name.example>
+Subject: with-msgid-with-long-line
+Date: Sun, 29 Nov 2020 15:30:41 +0000 (UTC)
+
+--msgid.unix-time/mail.example--
diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c
index e47fae6e7..6ebe1b0ad 100644
--- a/postfix/src/cleanup/cleanup.c
+++ b/postfix/src/cleanup/cleanup.c
@@ -10,38 +10,55 @@
/* into the \fBincoming\fR mail queue, and informs the queue
/* manager of its arrival.
/*
-/* The \fBcleanup\fR(8) daemon always performs the following transformations:
+/* The \fBcleanup\fR(8) daemon performs the following transformations:
/* .IP \(bu
/* Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR,
/* \fBTo:\fR, \fBMessage-Id:\fR, and \fBDate:\fR.
+/* .br
+/* This is enabled with the \fBlocal_header_rewrite_clients\fR and
+/* \fBalways_add_missing_headers\fR parameter settings.
/* .IP \(bu
/* Transform envelope and header addresses to the standard
/* \fIuser@fully-qualified-domain\fR form that is expected by other
/* Postfix programs.
-/* This task is delegated to the \fBtrivial-rewrite\fR(8) daemon.
+/* This task depends on the \fBtrivial-rewrite\fR(8) daemon.
+/* .br
+/* The header transformation is enabled with the
+/* \fBlocal_header_rewrite_clients\fR parameter setting.
/* .IP \(bu
/* Eliminate duplicate envelope recipient addresses.
+/* .br
+/* This is enabled with the \fBduplicate_filter_limit\fR
+/* parameter setting.
/* .IP \(bu
/* Remove message headers: \fBBcc\fR, \fBContent-Length\fR,
/* \fBResent-Bcc\fR, \fBReturn-Path\fR.
-/* .PP
-/* The following address transformations are optional:
+/* .br
+/* This is enabled with the message_drop_headers parameter
+/* setting.
/* .IP \(bu
/* Optionally, rewrite all envelope and header addresses according
/* to the mappings specified in the \fBcanonical\fR(5) lookup tables.
+/* .br
+/* The header transformation is enabled with the
+/* \fBlocal_header_rewrite_clients\fR parameter setting.
/* .IP \(bu
/* Optionally, masquerade envelope sender addresses and message
/* header addresses (i.e. strip host or domain information below
/* all domains listed in the \fBmasquerade_domains\fR parameter,
/* except for user names listed in \fBmasquerade_exceptions\fR).
/* By default, address masquerading does not affect envelope recipients.
+/* .br
+/* The header transformation is enabled with the
+/* \fBlocal_header_rewrite_clients\fR parameter setting.
/* .IP \(bu
/* Optionally, expand envelope recipients according to information
-/* found in the \fBvirtual\fR(5) lookup tables.
+/* found in the \fBvirtual_alias_maps\fR lookup tables.
/* .PP
/* The \fBcleanup\fR(8) daemon performs sanity checks on the content of
/* each message. When it finds a problem, by default it returns a
-/* diagnostic status to the client, and leaves it up to the client
+/* diagnostic status to the cleanup service client, and leaves
+/* it up to the client
/* to deal with the problem. Alternatively, the client can request
/* the \fBcleanup\fR(8) daemon to bounce the message back to the sender
/* in case of trouble.
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index f84aa4f9b..80702b03a 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -36,7 +36,8 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
smtputf8.c mail_conf_over.c mail_parm_split.c midna_adomain.c \
mail_addr_form.c quote_flags.c maillog_client.c \
normalize_mailhost_addr.c map_search.c reject_deliver_request.c \
- info_log_addr_form.c sasl_mech_filter.c login_sender_match.c
+ info_log_addr_form.c sasl_mech_filter.c login_sender_match.c \
+ test_main.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
@@ -74,7 +75,8 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
smtputf8.o attr_override.o mail_parm_split.o midna_adomain.o \
$(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o maillog_client.o \
normalize_mailhost_addr.o map_search.o reject_deliver_request.o \
- info_log_addr_form.o sasl_mech_filter.o login_sender_match.o
+ info_log_addr_form.o sasl_mech_filter.o login_sender_match.o \
+ test_main.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
@@ -109,7 +111,8 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
haproxy_srvr.h dsn_filter.h dynamicmaps.h uxtext.h smtputf8.h \
attr_override.h mail_parm_split.h midna_adomain.h mail_addr_form.h \
maillog_client.h normalize_mailhost_addr.h map_search.h \
- info_log_addr_form.h sasl_mech_filter.h login_sender_match.h
+ info_log_addr_form.h sasl_mech_filter.h login_sender_match.h \
+ test_main.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
@@ -2790,6 +2793,25 @@ sys_exits.o: ../../include/vbuf.h
sys_exits.o: ../../include/vstring.h
sys_exits.o: sys_exits.c
sys_exits.o: sys_exits.h
+test_main.o: ../../include/argv.h
+test_main.o: ../../include/check_arg.h
+test_main.o: ../../include/dict.h
+test_main.o: ../../include/msg.h
+test_main.o: ../../include/msg_vstream.h
+test_main.o: ../../include/myflock.h
+test_main.o: ../../include/mymalloc.h
+test_main.o: ../../include/stringops.h
+test_main.o: ../../include/sys_defs.h
+test_main.o: ../../include/vbuf.h
+test_main.o: ../../include/vstream.h
+test_main.o: ../../include/vstring.h
+test_main.o: mail_conf.h
+test_main.o: mail_dict.h
+test_main.o: mail_params.h
+test_main.o: mail_task.h
+test_main.o: mail_version.h
+test_main.o: test_main.c
+test_main.o: test_main.h
timed_ipc.o: ../../include/check_arg.h
timed_ipc.o: ../../include/msg.h
timed_ipc.o: ../../include/sys_defs.h
diff --git a/postfix/src/global/debug_peer.c b/postfix/src/global/debug_peer.c
index 06fcfc863..ae57a8f51 100644
--- a/postfix/src/global/debug_peer.c
+++ b/postfix/src/global/debug_peer.c
@@ -8,7 +8,7 @@
/*
/* void debug_peer_init(void)
/*
-/* int peer_debug_check(peer_name, peer_addr)
+/* int debug_peer_check(peer_name, peer_addr)
/* const char *peer_name;
/* const char *peer_addr;
/*
diff --git a/postfix/src/global/delivered_hdr.c b/postfix/src/global/delivered_hdr.c
index f1fc05d56..0aea1cc1d 100644
--- a/postfix/src/global/delivered_hdr.c
+++ b/postfix/src/global/delivered_hdr.c
@@ -149,7 +149,7 @@ DELIVERED_HDR_INFO *delivered_hdr_init(VSTREAM *fp, off_t offset, int flags)
&& ((curr_type = rec_get(fp, info->buf, 0)) == REC_TYPE_NORM
|| curr_type == REC_TYPE_CONT);
prev_type = curr_type) {
- if (prev_type != REC_TYPE_NORM)
+ if (prev_type == REC_TYPE_CONT)
continue;
if (is_header(STR(info->buf))) {
if ((hdr = header_opts_find(STR(info->buf))) != 0
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 3ce52a7c0..b8a2269dc 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -2024,6 +2024,14 @@ extern int var_bounce_limit;
#define DEF_DOUBLE_BOUNCE "double-bounce"
extern char *var_double_bounce_sender;
+ /*
+ * Bounce service: enable threaded bounces, with References: and
+ * In-Reply-To:.
+ */
+#define VAR_THREADED_BOUNCE "enable_threaded_bounces"
+#define DEF_THREADED_BOUNCE CONFIG_BOOL_NO
+extern bool var_threaded_bounce;
+
/*
* When forking a process, how often to try and how long to wait.
*/
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index d5229e897..5435e2aad 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -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 "20201104"
+#define MAIL_RELEASE_DATE "20201212"
#define MAIL_VERSION_NUMBER "3.6"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/test_main.c b/postfix/src/global/test_main.c
new file mode 100644
index 000000000..b3adf5947
--- /dev/null
+++ b/postfix/src/global/test_main.c
@@ -0,0 +1,224 @@
+/*++
+/* NAME
+/* test_main 3
+/* SUMMARY
+/* test main program
+/* SYNOPSIS
+/* #include
+/*
+/* NORETURN test_main(argc, argv, test_driver, key, value, ...)
+/* int argc;
+/* char **argv;
+/* void (*test_driver)(int argc, char **argv);
+/* int key;
+/* DESCRIPTION
+/* This module implements a test main program for stand-alone
+/* module tests.
+/*
+/* test_main() should be called from a main program. It does
+/* generic command-line options processing, and initializes
+/* configurable parameters. After calling the test_driver()
+/* function, the test_main() function terminates.
+/*
+/* Arguments:
+/* .IP "void (*test_driver)(int argc, char **argv)"
+/* A pointer to a function that is called after processing
+/* command-line options and initializing configuration parameters.
+/* The argc and argv specify the process name and non-option
+/* command-line arguments.
+/* .PP
+/* Optional test_main() arguments are specified as a null-terminated
+/* list with macros that have zero or more arguments:
+/* .IP "CA_TEST_MAIN_INT_TABLE(CONFIG_INT_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_TEST_MAIN_LONG_TABLE(CONFIG_LONG_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_TEST_MAIN_STR_TABLE(CONFIG_STR_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_TEST_MAIN_BOOL_TABLE(CONFIG_BOOL_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_TEST_MAIN_TIME_TABLE(CONFIG_TIME_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_TEST_MAIN_RAW_TABLE(CONFIG_RAW_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed. Raw parameters are not subjected to $name
+/* evaluation.
+/* .IP "CA_TEST_MAIN_NINT_TABLE(CONFIG_NINT_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* .IP "CA_TEST_MAIN_NBOOL_TABLE(CONFIG_NBOOL_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
+/* DIAGNOSTICS
+/* Problems and transactions are logged stderr.
+/* BUGS
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include
+#include
+
+ /*
+ * Utility library.
+ */
+#include
+#include
+#include
+#include
+#include
+
+ /*
+ * Global library.
+ */
+#include
+#include
+#include
+#include
+#include
+
+ /*
+ * Test library.
+ */
+#include
+
+/* test_driver_main - the real main program */
+
+NORETURN test_main(int argc, char **argv, TEST_DRIVER_FN test_driver,...)
+{
+ const char *myname = "test_driver_main";
+ va_list ap;
+ int ch;
+ int key;
+ int test_driver_argc;
+ char **test_driver_argv;
+
+ /*
+ * Set up logging.
+ */
+ var_procname = mystrdup(basename(argv[0]));
+ msg_vstream_init(mail_task(var_procname), VSTREAM_ERR);
+
+ /*
+ * Check the Postfix library version as soon as we enable logging.
+ */
+ MAIL_VERSION_CHECK;
+
+ /*
+ * Parse JCL.
+ */
+ while ((ch = GETOPT(argc, argv, "c:v")) > 0) {
+ switch (ch) {
+ case 'c':
+ if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
+ msg_fatal("out of memory");
+ break;
+ case 'v':
+ msg_verbose++;
+ break;
+ default:
+ msg_fatal("invalid option: %c. Usage: %s [-c config_dir] [-v]",
+ optopt, argv[0]);
+ break;
+ }
+ }
+
+ /*
+ * Initialize generic parameters.
+ */
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+ set_mail_conf_str(VAR_SERVNAME, var_procname);
+ mail_conf_read();
+
+ /*
+ * Register higher-level dictionaries and initialize the support for
+ * dynamically-loaded dictionarles.
+ */
+ mail_dict_init();
+
+ /*
+ * Application-specific initialization.
+ */
+ va_start(ap, test_driver);
+ while ((key = va_arg(ap, int)) != 0) {
+ switch (key) {
+ case TEST_MAIN_INT_TABLE:
+ get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *));
+ break;
+ case TEST_MAIN_LONG_TABLE:
+ get_mail_conf_long_table(va_arg(ap, CONFIG_LONG_TABLE *));
+ break;
+ case TEST_MAIN_STR_TABLE:
+ get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *));
+ break;
+ case TEST_MAIN_BOOL_TABLE:
+ get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
+ break;
+ case TEST_MAIN_TIME_TABLE:
+ get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
+ break;
+ case TEST_MAIN_RAW_TABLE:
+ get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *));
+ break;
+ case TEST_MAIN_NINT_TABLE:
+ get_mail_conf_nint_table(va_arg(ap, CONFIG_NINT_TABLE *));
+ break;
+ case TEST_MAIN_NBOOL_TABLE:
+ get_mail_conf_nbool_table(va_arg(ap, CONFIG_NBOOL_TABLE *));
+ break;
+ default:
+ msg_panic("%s: unknown argument type: %d", myname, key);
+ }
+ }
+ va_end(ap);
+
+ /*
+ * Set up call-back info.
+ */
+ test_driver_argv = argv + optind - 1;
+ if (test_driver_argv != argv)
+ test_driver_argv[0] = argv[0];
+ test_driver_argc = argc - optind + 1;
+
+ /*
+ * Call the test driver and terminate (if they didn't terminate already).
+ */
+ test_driver(test_driver_argc, test_driver_argv);
+ exit(0);
+}
diff --git a/postfix/src/global/test_main.h b/postfix/src/global/test_main.h
new file mode 100644
index 000000000..aea605a1f
--- /dev/null
+++ b/postfix/src/global/test_main.h
@@ -0,0 +1,64 @@
+/*++
+/* NAME
+/* test_main 3h
+/* SUMMARY
+/* test main program
+/* SYNOPSIS
+/* #include
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Global library.
+ */
+#include
+
+ /*
+ * External interface. Copied from master/mail_server.h, but without
+ * introducing libmaster dependencies.
+ */
+#define TEST_MAIN_INT_TABLE 1
+#define TEST_MAIN_STR_TABLE 2
+#define TEST_MAIN_BOOL_TABLE 3
+#define TEST_MAIN_TIME_TABLE 4
+#define TEST_MAIN_RAW_TABLE 5
+#define TEST_MAIN_NINT_TABLE 6
+#define TEST_MAIN_NBOOL_TABLE 7
+#define TEST_MAIN_LONG_TABLE 8
+
+#define CA_TEST_MAIN_INT_TABLE(v) TEST_MAIN_INT_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_INT_TABLE, (v))
+#define CA_TEST_MAIN_STR_TABLE(v) TEST_MAIN_STR_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_STR_TABLE, (v))
+#define CA_TEST_MAIN_BOOL_TABLE(v) TEST_MAIN_BOOL_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_BOOL_TABLE, (v))
+#define CA_TEST_MAIN_TIME_TABLE(v) TEST_MAIN_TIME_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_TIME_TABLE, (v))
+#define CA_TEST_MAIN_RAW_TABLE(v) TEST_MAIN_RAW_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_RAW_TABLE, (v))
+#define CA_TEST_MAIN_NINT_TABLE(v) TEST_MAIN_NINT_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_NINT_TABLE, (v))
+#define CA_TEST_MAIN_NBOOL_TABLE(v) TEST_MAIN_NBOOL_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_NBOOL_TABLE, (v))
+#define CA_TEST_MAIN_LONG_TABLE(v) TEST_MAIN_LONG_TABLE, CHECK_CPTR(TEST_MAIN, CONFIG_LONG_TABLE, (v))
+
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_INT_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_STR_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_BOOL_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_TIME_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_RAW_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_NINT_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_NBOOL_TABLE);
+CHECK_CPTR_HELPER_DCL(TEST_MAIN, CONFIG_LONG_TABLE);
+
+typedef void (*TEST_DRIVER_FN) (int, char **);
+extern NORETURN test_main(int, char **, TEST_DRIVER_FN,...);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
diff --git a/postfix/src/qmqpd/qmqpd_peer.c b/postfix/src/qmqpd/qmqpd_peer.c
index 290b7f26f..14893ddb5 100644
--- a/postfix/src/qmqpd/qmqpd_peer.c
+++ b/postfix/src/qmqpd/qmqpd_peer.c
@@ -49,7 +49,6 @@
#include
#include
#include
-#include /* strerror() */
#include
#include
#include
diff --git a/postfix/src/smtpd/smtpd_peer.c b/postfix/src/smtpd/smtpd_peer.c
index b6708afc5..179e19d8f 100644
--- a/postfix/src/smtpd/smtpd_peer.c
+++ b/postfix/src/smtpd/smtpd_peer.c
@@ -125,7 +125,6 @@
#include
#include
#include
-#include /* strerror() */
#include
#include
#include
diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in
index b66a6e628..6eb41bbd1 100644
--- a/postfix/src/util/Makefile.in
+++ b/postfix/src/util/Makefile.in
@@ -1955,8 +1955,6 @@ load_file.o: vbuf.h
load_file.o: vstream.h
load_file.o: warn_stat.h
load_lib.o: load_lib.c
-load_lib.o: load_lib.h
-load_lib.o: msg.h
load_lib.o: sys_defs.h
logwriter.o: check_arg.h
logwriter.o: iostuff.h
diff --git a/postfix/src/util/vbuf_print.c b/postfix/src/util/vbuf_print.c
index bdb6fe944..d7a323f24 100644
--- a/postfix/src/util/vbuf_print.c
+++ b/postfix/src/util/vbuf_print.c
@@ -290,7 +290,8 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap)
break;
case 'm':
/* Ignore the 'l' modifier, width and precision. */
- VBUF_STRCAT(bp, strerror(saved_errno));
+ VBUF_STRCAT(bp, saved_errno ?
+ strerror(saved_errno) : "Application error");
break;
case 'p':
if (long_flag)
--
2.47.3