Andreas Krennmair:
authorak1 <ak1@e385b8ad-14ed-0310-8656-cc95a2468c6d>
Sat, 5 Feb 2005 13:43:59 +0000 (13:43 +0000)
committerak1 <ak1@e385b8ad-14ed-0310-8656-cc95a2468c6d>
Sat, 5 Feb 2005 13:43:59 +0000 (13:43 +0000)
make localpart of message ID configurable.

git-svn-id: svn://svn.berlios.de/mutt-ng/trunk@50 e385b8ad-14ed-0310-8656-cc95a2468c6d

globals.h
init.h
sendlib.c

index 6d3571d..b781d87 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -75,6 +75,7 @@ WHERE char *MhFlagged;
 WHERE char *MhReplied;
 WHERE char *MhUnseen;
 WHERE char *MsgFmt;
 WHERE char *MhReplied;
 WHERE char *MhUnseen;
 WHERE char *MsgFmt;
+WHERE char *MsgIdFormat;
 
 #ifdef USE_SOCKET
 WHERE char *Preconnect INITVAL (NULL);
 
 #ifdef USE_SOCKET
 WHERE char *Preconnect INITVAL (NULL);
diff --git a/init.h b/init.h
index 0ab2405..6082311 100644 (file)
--- a/init.h
+++ b/init.h
@@ -927,8 +927,8 @@ struct option_t MuttVars[] = {
   { "imap_reconnect",  DT_QUAD, R_NONE, OPT_IMAPRECONNECT, M_ASKYES },
   /*
   ** .pp
   { "imap_reconnect",  DT_QUAD, R_NONE, OPT_IMAPRECONNECT, M_ASKYES },
   /*
   ** .pp
-  ** Controls whether or not Mutt will try to reconnect to IMAP server when
-  ** connection lost.
+  ** Controls whether or not Mutt-ng will try to reconnect to IMAP server when
+  ** the connection is lost.
   */
   { "imap_servernoise",                DT_BOOL, R_NONE, OPTIMAPSERVERNOISE, 1 },
   /*
   */
   { "imap_servernoise",                DT_BOOL, R_NONE, OPTIMAPSERVERNOISE, 1 },
   /*
@@ -1328,6 +1328,32 @@ struct option_t MuttVars[] = {
   { "msg_format",      DT_SYN,  R_NONE, UL "message_format", 0 },
   /*
   */
   { "msg_format",      DT_SYN,  R_NONE, UL "message_format", 0 },
   /*
   */
+  { "msgid_format",    DT_STR, R_NONE, UL &MsgIdFormat, UL "%Y%m%d%h%M%s.G%P%p" },
+  /*
+  ** .pp
+  ** This is the format for the ``local part'' of the message-IDs generated
+  ** by Mutt-ng. The format string contains of one or more characters. The '%'
+  ** character marks that certain data will be added to the string, similar to
+  ** printf(). The following characters are allowed:
+  ** .pp
+  ** .dl
+  ** .dt %d .dd the current day of month
+  ** .dt %h .dd the current hour
+  ** .dt %m .dd the current month
+  ** .dt %M .dd the current minute
+  ** .dt %O .dd the current UNIX timestamp (octal)
+  ** .dt %p .dd the process ID
+  ** .dt %P .dd the current message-ID prefix (a character rotating with 
+  **            every message-ID being generated)
+  ** .dt %r .dd a random integer value (decimal)
+  ** .dt %R .dd a random integer value (hexadecimal)
+  ** .dt %s .dd the current second
+  ** .dt %T .dd the current UNIX timestamp (decimal)
+  ** .dt %X .dd the current UNIX timestamp (hexadecimal)
+  ** .dt %Y .dd the current year (Y2K compliant)
+  ** .dt %% .dd the '%' character
+  ** .de
+  */
   { "narrow_tree",     DT_BOOL, R_TREE|R_INDEX, OPTNARROWTREE, 0 },
   /*
   ** .pp
   { "narrow_tree",     DT_BOOL, R_TREE|R_INDEX, OPTNARROWTREE, 0 },
   /*
   ** .pp
index a77b6d0..61b8a39 100644 (file)
--- a/sendlib.c
+++ b/sendlib.c
@@ -1810,9 +1810,102 @@ const char *mutt_fqdn(short may_hide_host)
   return p;
 }
 
   return p;
 }
 
+static char mutt_normalized_char(char c) {
+  if (isalnum(c))
+    return c;
+  if (strchr(".!#$%&'*+-/=?^_`{|}~",c))
+    return c;
+  return '.'; /* normalized character (we're stricter than RFC2822, 3.6.4) */
+}
+
+static void mutt_gen_localpart(char * buf, unsigned int len, char * fmt) {
+  time_t now;
+  struct tm *tm;
+  char tmp[SHORT_STRING];
+
+  *buf = '\0';
+
+  now = time (NULL);
+  tm = gmtime (&now);
+
+  for (;*fmt;++fmt) {
+    if (*fmt == '%') {
+      switch (fmt[1]) {
+      case 0:
+        return;
+      case 'd':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_mday);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'h':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_hour);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'm':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_mon+1);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'M':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_min);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'O':
+        snprintf(tmp,sizeof(tmp),"%lo",(unsigned long)now);
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'p':
+        snprintf(tmp,sizeof(tmp),"%u",(unsigned int)getpid());
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'P':
+        snprintf(tmp,sizeof(tmp),"%c",MsgIdPfx);
+        MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+        safe_strncat(buf,len,tmp,1);
+        break;
+      case 'r':
+        snprintf(tmp,sizeof(tmp),"%u",(unsigned int)rand());
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'R':
+        snprintf(tmp,sizeof(tmp),"%x",(unsigned int)rand());
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 's':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_sec);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'T':
+        snprintf(tmp,sizeof(tmp),"%u",(unsigned int)now);
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'X':
+        snprintf(tmp,sizeof(tmp),"%x",(unsigned int)now);
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'Y':
+        snprintf(tmp,sizeof(tmp),"%04d",tm->tm_year+1900); /* this will break in the year 10000 ;-) */
+        safe_strncat(buf,len,tmp,4);
+        break;
+      case '%':
+        safe_strncat(buf,len,"%",1);
+        break;
+      default:
+        safe_strncat(buf,len,".",1); /* invalid formats are replaced by '.' */
+      } /* switch */
+      ++fmt;
+    } else {
+      char c;
+      c = mutt_normalized_char(*fmt); /* @todo: filter out invalid characters */
+      safe_strncat(buf,len,&c,1);
+    }
+  }
+}
+
 char *mutt_gen_msgid (void)
 {
   char buf[SHORT_STRING];
 char *mutt_gen_msgid (void)
 {
   char buf[SHORT_STRING];
+  char localpart[SHORT_STRING];
+  unsigned int localpart_length;
   time_t now;
   struct tm *tm;
   const char *fqdn;
   time_t now;
   struct tm *tm;
   const char *fqdn;
@@ -1822,10 +1915,11 @@ char *mutt_gen_msgid (void)
   if(!(fqdn = mutt_fqdn(0)))
     fqdn = NONULL(Hostname);
 
   if(!(fqdn = mutt_fqdn(0)))
     fqdn = NONULL(Hostname);
 
-  snprintf (buf, sizeof (buf), "<%d%02d%02d%02d%02d%02d.G%c%u@%s>",
-           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
-           tm->tm_min, tm->tm_sec, MsgIdPfx, (unsigned int)getpid (), fqdn);
-  MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+  localpart_length = sizeof(buf) - strlen(fqdn) - 4; /* the 4 characters are '<', '@', '>' and '\0' */
+
+  mutt_gen_localpart(localpart,localpart_length,MsgIdFormat);
+
+  snprintf(buf,sizeof(buf),"<%s@%s>",localpart,fqdn);
   return (safe_strdup (buf));
 }
 
   return (safe_strdup (buf));
 }