Hi,
I had a few users explain that the bounces they sometimes get are so
hard to understand...
To make life easier for them I added some messages to the templates so
that they can read their errors in their native language. That helped,
but users were still not always clear, which specific message a bounce
related to. It seems reading error messages is hard...
Thus I had a quick look at the postfix/src/bounce and see how I could
improve matters.
Attached is a small patch against postfix-3.6-20200830 that parses the
Message-Id header from bounce_info->orig_fp, stores it in
bounce_info->orig_msgid and then later adds a Reply-To and a References
header with this Message-Id to the generated DSN message.
This allows MUAs to clearer show which original message a bounce is
referring to and hopefully make life even easier for users.
Would this seem like a sensible feature for inclusion in postfix?
My code was only a quick change and it's been a while since I last wrote
C-code, so if you got any pointers how to improve matters or if there's
an easier way to extract a Message-Id header, I'd be happy to try to
improve the code.
Cheers,
andreas
diff --git a/postfix/src/bounce/bounce_notify_util.c
b/postfix/src/bounce/bounce_notify_util.c
index 7c79ca0..6668cb3 100644
--- a/postfix/src/bounce/bounce_notify_util.c
+++ b/postfix/src/bounce/bounce_notify_util.c
@@ -206,6 +206,7 @@
#include <deliver_completed.h>
#include <dsn_mask.h>
#include <smtputf8.h>
+#include <header_opts.h>
/* Application-specific. */
@@ -266,6 +267,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;
@@ -351,20 +353,44 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
mail_addr_mail_daemon(), 0);
}
+ /*
+ * Extract Message-ID from original mail
+ */
+ else if (rec_type == REC_TYPE_NORM || rec_type == REC_TYPE_CONT) {
+
+ const HEADER_OPTS *hdr;
+ char *cp;
+
+ /* We've reached the body */
+ if (VSTRING_LEN(bounce_info->buf) == 0)
+ break;
+
+ /* Discard input that does not look like a key-value header */
+ if (vstring_memchr(bounce_info->buf, ':') == 0)
+ continue;
+
+ if ((hdr = header_opts_find(vstring_str(bounce_info->buf))) != 0
+ && hdr->type == HDR_MESSAGE_ID) {
+ cp = STR(bounce_info->buf) + strlen(hdr->name) + 1;
+ while (ISSPACE(*cp))
+ cp++;
+ vstring_strcpy(bounce_info->orig_msgid, cp);
+ }
+ }
/*
* Backwards compatibility: no data offset in SIZE record.
*/
- else if (rec_type == REC_TYPE_MESG) {
+ else if (rec_type == REC_TYPE_MESG && bounce_info->orig_offs == 0) {
/* XXX Future: sender+recipient after message content. */
if (VSTRING_LEN(bounce_info->sender) == 0)
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 (bounce_info->orig_offs > 0
&& bounce_info->arrival_time > 0
- && VSTRING_LEN(bounce_info->sender) > 0)
+ && VSTRING_LEN(bounce_info->sender) > 0
+ && VSTRING_LEN(bounce_info->orig_msgid) > 0)
break;
}
}
@@ -474,6 +500,16 @@ 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_service.h
b/postfix/src/bounce/bounce_service.h
index f8cc4d6..40793f2 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 */