[PATCH v3 2/2] Add %F expando to $message_id_format to use From address.

"Kevin J. McCarthy" <[email protected]>
Newsgroups gmane.mail.mutt.devel
Message-ID <[email protected]>
Filter out characters, even stricter than RFC5322 requires, to allow
the message id to be used in a URL.

If, for whatever reason, the from address is not available, fall back
to "@%f".

Provide an example value in the manual:
  set message_id_format="%z_%F"
noting that %F includes a '@' and so one must not also be inside the
variable.
---
 init.h      |  5 +++++
 messageid.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 protos.h    |  2 +-
 sendlib.c   |  4 ++--
 4 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/init.h b/init.h
index 087ebfa8..d9fc0378 100644
--- a/init.h
+++ b/init.h
@@ -2223,11 +2223,16 @@ struct option_t MuttVars[] = {
   ** The old Message-ID format can be used by setting this to:
   ** ``\fC<%Y%02m%02d%02H%02M%02S.G%c%p@%f>\fP''
   ** .pp
+  ** An alternative to using %f is %F.  This expando includes a '@',
+  ** so when used there must not be a second '@' in the variable:
+  ** ``\fC<%z_%F>\fP''
+  ** .pp
   ** The following \fCprintf(3)\fP-style sequences are understood:
   ** .dl
   ** .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 address of the message, including an '@'
   ** .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 397ff31c..4bb1d839 100644
--- a/messageid.c
+++ b/messageid.c
@@ -22,6 +22,7 @@
 
 #include "mutt.h"
 #include "mutt_random.h"
+#include "mutt_idna.h"
 
 static char MsgIdPfx = 'A';
 
@@ -30,8 +31,30 @@ typedef struct msg_id_data
   time_t now;
   struct tm tm;
   const char *fqdn;
+  ENVELOPE *env;
 } MSG_ID_DATA;
 
+/* This function is much stricter than RFC5322 specifies, because we also want
+ * the message-id to be passed in a URL as a path segment or parameter without
+ * needing encoding.
+ */
+static void filter_from_addr(char *from)
+{
+  int has_at = 0;
+
+  if (!from)
+    return;
+
+  while (*from)
+  {
+    if (*from == '@' && !has_at)
+      has_at = 1;
+    else if (!strchr(CTYPE_PFCHAR_C, *from))
+      *from = '_';
+    from++;
+  }
+}
+
 static const char *id_format_str(char *dest, size_t destlen, size_t col,
                                  int cols, char op, const char *src,
                                  const char *fmt, const char *ifstring,
@@ -44,6 +67,7 @@ static const char *id_format_str(char *dest, size_t destlen, size_t col,
   unsigned char r_out[4 + 1];
   unsigned char z_raw[12]; /* 32 bit timestamp, plus 64 bit randomness */
   unsigned char z_out[16 + 1];
+  ADDRESS *from;
 
   switch (op)
   {
@@ -107,12 +131,26 @@ 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':
+      from = rfc822_cpy_adr(id_data->env->from, 1);
+      if (!from || !from->mailbox)
+      {
+        snprintf(tmp, sizeof(tmp), "@%s", id_data->fqdn);
+        mutt_format_s(dest, destlen, fmt, tmp);
+        break;
+      }
+      mutt_addrlist_to_intl(from, NULL);
+      filter_from_addr(from->mailbox);
+      mutt_format_s(dest, destlen, fmt, from->mailbox);
+      rfc822_free_address(&from);
+      break;
   }
 
   return (src);
 }
 
-char *mutt_gen_msgid(void)
+char *mutt_gen_msgid(ENVELOPE *env)
 {
   MSG_ID_DATA id_data;
   BUFFER *buf, *tmp;
@@ -123,6 +161,7 @@ char *mutt_gen_msgid(void)
   memcpy(&id_data.tm, gmtime(&id_data.now), sizeof(id_data.tm));
   if (!(id_data.fqdn = mutt_fqdn(0)))
     id_data.fqdn = NONULL(Hostname);
+  id_data.env = env;
 
   fmt = MessageIdFormat;
   if (!fmt)
diff --git a/protos.h b/protos.h
index 7ea95ae5..e03ca0eb 100644
--- a/protos.h
+++ b/protos.h
@@ -156,7 +156,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(ENVELOPE *);
 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 150bc72d..612b0503 100644
--- a/sendlib.c
+++ b/sendlib.c
@@ -2912,7 +2912,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);
   }
 
   /* Take care of 8-bit => 7-bit conversion. */
@@ -2975,7 +2975,7 @@ static int _mutt_bounce_message(FILE *fp, HEADER *h, ADDRESS *to, const char *re
     fprintf(f, "Resent-Date: %s\n", mutt_b2s(date));
     mutt_buffer_pool_release(&date);
 
-    msgid_str = mutt_gen_msgid();
+    msgid_str = mutt_gen_msgid(h->env);
     fprintf(f, "Resent-Message-ID: %s\n", msgid_str);
     fputs("Resent-To: ", f);
     mutt_write_address_list(to, f, 11, 0);
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.