This patch changes mutt_gen_msgid (and related) to allow use of the
fqdn of the From address when generating the @ portion of the
Message-ID.

I use mutt to send email from more than one mail domain. I found that
some MTAs reject emails where fqdn of the Message-ID does not have a
reverse look-up, returning the error:

<user>@*sbcglobal.net*: 550 5.7.1 Connections not accepted from
servers without a valid sender domain.alph758 Fix reverse DNS for <ip
address>

So far, I've only run across it with ATT-related domains.
Unfortunately the only solution is to change the `hostname` variable
in muttrc(5) and resend. (And yes, checking reverse look-up on the
Message-ID fqdn is nutty.)

With this change, and the addition of the "%F" sequence, the user can
choose between the node `hostname` (%f), or the fqdn of the from
address (%F) when generating the Message-ID.

The heart of the change is in mutt_gen_msgid. It now accepts a "From"
parameter which it parses to extract the fqdn.

Lastly, the patch updates the documentation and changes the default
message_id_format from "<%z@%f>", to "<%z@%F>" so that Message-IDs are
always generated using the fqdn of the From address.

That last change makes a certain sense to me, as it ensures that all
outbound messages will have a Message-ID associated with the sending
domain rather than the MUA host, but I wouldn't complain if were
rejected since users can still set it in muttrc(5).

The patch was developed and tested on OpenBSD against the port of
version 2.1.3. The patch was then applied and tested against commit
543e115132b32571ff98d2e89a82cc0a5e3110d4 (2021-11-15).

Thanks,

--Aaron

diff --git a/init.h b/init.h
index 0d920fcd..5e6cedee 100644
--- a/init.h
+++ b/init.h
@@ -2185,7 +2185,7 @@ struct option_t MuttVars[] = {
   { "msg_format",      DT_SYN,  R_NONE, {.p="message_format"}, {.p=0} },
   /*
   */
-  { "message_id_format", DT_STR, R_NONE, {.p=&MessageIdFormat}, {.p="<%z@%f>"} 
},
+  { "message_id_format", DT_STR, R_NONE, {.p=&MessageIdFormat}, {.p="<%z@%F>"} 
},
   /*
   ** .pp
   ** This variable describes the format of the Message-ID generated
@@ -2210,6 +2210,7 @@ struct option_t MuttVars[] = {
   ** .dt %c .dd step counter looping from ``A'' to ``Z''
   ** .dt %d .dd current day of the month (GMT)
   ** .dt %f .dd $$hostname
+  ** .dt %F .dd From hostname (after @ in from address)
   ** .dt %H .dd current hour using a 24-hour clock (GMT)
   ** .dt %m .dd current month number (GMT)
   ** .dt %M .dd current minute of the hour (GMT)
diff --git a/messageid.c b/messageid.c
index e4ac4410..2ab63288 100644
--- a/messageid.c
+++ b/messageid.c
@@ -30,6 +30,7 @@ typedef struct msg_id_data
   time_t now;
   struct tm tm;
   const char *fqdn;
+  const char *from_fqdn;
 } MSG_ID_DATA;
 
 static const char *id_format_str (char *dest, size_t destlen, size_t col,
@@ -107,12 +108,16 @@ static const char *id_format_str (char *dest, size_t 
destlen, size_t col,
     case 'f':
       mutt_format_s (dest, destlen, fmt, id_data->fqdn);
       break;
+
+    case 'F':
+      mutt_format_s (dest, destlen, fmt, id_data->from_fqdn);
+      break;
   }
 
   return (src);
 }
 
-char *mutt_gen_msgid (void)
+char *mutt_gen_msgid (const char *from)
 {
   MSG_ID_DATA id_data;
   BUFFER *buf, *tmp;
@@ -124,9 +129,17 @@ char *mutt_gen_msgid (void)
   if (!(id_data.fqdn = mutt_fqdn(0)))
     id_data.fqdn = NONULL(Hostname);
 
+  /* from should be a fully-formatted email address,
+   * nevertheless, handle cases where the caller
+   * sends just the fqdn or NULL. */
+  if (!from)
+    id_data.from_fqdn = id_data.fqdn;
+  else if (!(id_data.from_fqdn = strchr (from, '@') + 1))
+    id_data.from_fqdn = from;
+
   fmt = MessageIdFormat;
   if (!fmt)
-    fmt = "<%z@%f>";
+    fmt = "<%z@%F>";
 
   buf = mutt_buffer_pool_get ();
   mutt_FormatString (buf->data, buf->dsize, 0, buf->dsize,
diff --git a/protos.h b/protos.h
index fae28c99..f85e1862 100644
--- a/protos.h
+++ b/protos.h
@@ -151,7 +151,7 @@ void mutt_buffer_expand_multi_path_norel (BUFFER *src, 
const char *delimiter);
 void mutt_buffer_remove_path_password (BUFFER *dest, const char *src);
 char *mutt_find_hook (int, const char *);
 char *mutt_gecos_name (char *, size_t, struct passwd *);
-char *mutt_gen_msgid (void);
+char *mutt_gen_msgid (const char *);
 char *mutt_get_body_charset (char *, size_t, BODY *);
 const char *mutt_get_name (ADDRESS *);
 char *mutt_get_parameter (const char *, PARAMETER *);
diff --git a/sendlib.c b/sendlib.c
index 72f86e68..6334a3aa 100644
--- a/sendlib.c
+++ b/sendlib.c
@@ -2845,7 +2845,7 @@ void mutt_prepare_envelope (ENVELOPE *env, int final)
     mutt_set_followup_to (env);
 
     if (!env->message_id)
-      env->message_id = mutt_gen_msgid ();
+      env->message_id = mutt_gen_msgid (env->from->mailbox);
   }
 
   /* Take care of 8-bit => 7-bit conversion. */
@@ -2908,7 +2908,7 @@ static int _mutt_bounce_message (FILE *fp, HEADER *h, 
ADDRESS *to, const char *r
     fprintf (f, "Resent-Date: %s\n", mutt_b2s (date));
     mutt_buffer_pool_release (&date);
 
-    msgid_str = mutt_gen_msgid();
+    msgid_str = mutt_gen_msgid(resent_from);
     fprintf (f, "Resent-Message-ID: %s\n", msgid_str);
     fputs ("Resent-To: ", f);
     mutt_write_address_list (to, f, 11, 0);

Reply via email to