diff --git a/Changelog b/Changelog
index ebe5e735..25fb4c22 100644
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,48 @@
 Version Changes for Hypermail
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+============================
+HYPERMAIL VERSION 2.4.1:
+============================
+
+2022-11-04 Jose Kahan
+	* src/Makefile.in
+	Some C linkers require libraries to be declared after functions in that
+	library are called, and not before. This was notably with -lm and
+	-ltrio, where -lm had to be declared after -ltrio.
+        (closes # 84)
+
+2021-11-17 David Hughes
+	* docs/hmrc.html src/parse.c
+	Added support for strftime (3) formatting in the append_filename configuration
+	option to allow for archived messages to be split over multiple directories
+	(monthly or yearly for example)
+
+2021-06-04 Baptiste Daroussin
+	* src/uudecode.c src/parse.c
+	Fixes for memory issues detected by libasan
+
+2020-06-19 Jose Kahan
+	* src/domains.c
+	valid_root_domains() was validating a domain name against the
+	historical DNS domains such as .org, .com. DNS has evolved and allows a
+	bigger variety of domains than those this function verified. That part
+	of the function has been invalidated and will be either eventually
+	removed or evolve to a user-configurable option.
+
+2020-06-12 Jose Kahan
+	* configure.ac
+	configure didn't signal an error if yacc was not installed
+
+	* src/string.c
+	parseurl(): URLs were not detected and converted when they were
+	preceeded by a : that was not attached to a valid URL like
+	foo: https://example.com or : https://example.com
+
+2020-02-23 @cacsar
+	* Makefile.in
+	make install wasn't working
+
 ============================
 HYPERMAIL VERSION 2.4.0:
 ============================
diff --git a/Makefile.in b/Makefile.in
index caeb383a..c679d37d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -47,14 +47,14 @@ support:
 	@cd archive; $(MAKE) all CC="$(CC)" CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" 
 
 install: 
-	@cd src; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS) \
-		"CPPFLAGS="$(CPPFLAGS)"  \
+	@cd src; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS)" \
+		CPPFLAGS="$(CPPFLAGS)"  \
 		cgidir="$(cgidir)" bindir="$(bindir)" LIBS="$(LIBS)"
 	@cd docs; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS)" \
-		"CPPFLAGS="$(CPPFLAGS)"  \
+		CPPFLAGS="$(CPPFLAGS)"  \
 		$(MAKEFLAGS) mandir="$(mandir)" htmldir="$(htmldir)"
 	@cd archive; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS)" \
-		"CPPFLAGS="$(CPPFLAGS)"  \
+		CPPFLAGS="$(CPPFLAGS)"  \
 		bindir="$(bindir)"
 
 uninstall: 
diff --git a/configure b/configure
index a9feaaad..7858d04e 100755
--- a/configure
+++ b/configure
@@ -709,6 +709,7 @@ LN_S
 INSTALL_DATA
 INSTALL_SCRIPT
 INSTALL_PROGRAM
+YACC_CHECK
 YFLAGS
 YACC
 CPP
@@ -3444,6 +3445,46 @@ fi
 done
 test -n "$YACC" || YACC="yacc"
 
+# Extract the first word of "$YACC", so it can be a program name with args.
+set dummy $YACC; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_YACC_CHECK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$YACC_CHECK"; then
+  ac_cv_prog_YACC_CHECK="$YACC_CHECK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC_CHECK="yes"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC_CHECK=$ac_cv_prog_YACC_CHECK
+if test -n "$YACC_CHECK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC_CHECK" >&5
+$as_echo "$YACC_CHECK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test x"$YACC_CHECK" != x"yes"; then :
+  as_fn_error $? "Please install either bison or yacc and run configure again" "$LINENO" 5
+fi
 # Find a good install program.  We prefer a C program (faster),
 # so one script is as good as another.  But avoid the broken or
 # incompatible versions:
diff --git a/configure.ac b/configure.ac
index 2a3b7fa9..79714bfd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,8 @@ dnl ===========================================================================
 AC_PROG_CC
 AC_PROG_CPP
 AC_PROG_YACC
+AC_CHECK_PROG(YACC_CHECK,$YACC,yes)
+AS_IF([test x"$YACC_CHECK" != x"yes"], [AC_MSG_ERROR([Please install either bison or yacc and run configure again])])
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_MAKE_SET
diff --git a/docs/hmrc.html b/docs/hmrc.html
index 399be3ed..4953123b 100644
--- a/docs/hmrc.html
+++ b/docs/hmrc.html
@@ -1301,9 +1301,11 @@ <h3><a name="sysmisc" id="sysmisc">System miscellaneous</a></h3>
 <i>append = 1</i></dd>
 <dd><a name="append_filename" id="append_filename"></a></dd>
 <dt><strong>append_filename = [ string ]</strong></dt>
-<dd>Specifies the filename to be used by the append option. $DIR
-may be used to specify a name relative to the directory specified
-in the -d or dir option.<br>
+<dd>Specifies the filename to be used by the append option. $DIR may
+be used to specify a name relative to the directory specified in the
+-d or dir option.  The string will be passed to strftime(3) to allow
+splitting the mailbox into yearly or monthy files, such as
+"%Y-%m.mbox". <br>
 <br>
 <i>append_filename = $DIR/INBOX</i></dd>
 <dd><a name="txtsuffix" id="txtsuffix"></a></dd>
diff --git a/src/Makefile.in b/src/Makefile.in
index 7f54bad0..2838fa4b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -40,7 +40,7 @@ CPPFLAGS=@CPPFLAGS@ @INCLUDES@
 YACC=@YACC@
 NETLIBS=@LIBS@
 LDFLAGS=@LDFLAGS@
-MISC_LIBS= -lm -lpcre -ltrio
+MISC_LIBS= -lpcre -ltrio -lm
 OPT_LIBS=@EXTRA_LIBS@
 
 INCS=		domains.h hypermail.h lang.h proto.h \
diff --git a/src/domains.c b/src/domains.c
index be4ed92d..324a1322 100644
--- a/src/domains.c
+++ b/src/domains.c
@@ -18,6 +18,13 @@ int valid_root_domain(char *eaddr)
     if (!*name_to_check)
         return (0);
 
+    /* DNS has evolved and we have now a variety of new domains, hard
+       to track and that are not covered by this function. While temporary
+       waiting to see if we evolve this function to be user configurable,
+       we're going to return 1 (valid) all the time. 19/06/2020 -JK */
+      return (1);
+       
+
     for (ccptr = domain_codes; ccptr->domain != NULL; ccptr++) {
         if (strcasecmp(name_to_check, ccptr->domain) == 0)
             return (1);
diff --git a/src/file.c b/src/file.c
index cdfa67fe..5aafc834 100644
--- a/src/file.c
+++ b/src/file.c
@@ -53,9 +53,6 @@
 #endif
 #endif /* HAVE_LIBFNV */
 
-extern int snprintf(char *str, size_t size, const  char  *format, ...);
-
-
 /*
 ** Does a file exist?
 */
diff --git a/src/hypermail.h b/src/hypermail.h
index 6a63c102..38d71ac9 100644
--- a/src/hypermail.h
+++ b/src/hypermail.h
@@ -135,7 +135,7 @@
 #define NUMSTRLEN    10
 #define MAXLINE	     1024
 #define MAXFILELEN   256
-#define NAMESTRLEN   80
+#define NAMESTRLEN   320
 #define MAILSTRLEN   80
 #define DATESTRLEN   80
 #define MSGDSTRLEN   256
diff --git a/src/parse.c b/src/parse.c
index 36da5dfb..aad1740e 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -924,7 +924,7 @@ static char *mdecodeRFC2047(char *string, int length, char *charsetsave)
     char charset[129];
     char encoding[33];
     char dummy[129];
-    char *ptr;
+    char *ptr, *endptr;
     char *old_output;
 
 #ifdef NOTUSED
@@ -959,6 +959,7 @@ static char *mdecodeRFC2047(char *string, int length, char *charsetsave)
 
 	    if (!strcasecmp("q", encoding)) {
 		/* quoted printable decoding */
+            endptr = ptr + strlen(ptr);
 
 #ifdef HAVE_ICONV
 	      char *orig2,*output2,*output3;
@@ -967,7 +968,7 @@ static char *mdecodeRFC2047(char *string, int length, char *charsetsave)
 	      memset(output2,0,strlen(string)+1);
 	      old_output=output;
 
-		for (; *ptr; ptr++) {
+		for (; ptr < endptr; ptr++) {
 		    switch (*ptr) {
 		    case '=':
 			sscanf(ptr + 1, "%02X", &value);
@@ -991,7 +992,7 @@ static char *mdecodeRFC2047(char *string, int length, char *charsetsave)
 		memcpy(charsetsave,charset,charsetlen);
 		charsetsave[charsetlen] = '\0';
 #else
-		for (; *ptr; ptr++) {
+		for (; ptr < endptr; ptr++) {
 		    switch (*ptr) {
 		    case '=':
 			sscanf(ptr + 1, "%02X", &value);
@@ -1086,6 +1087,11 @@ static char *mdecodeRFC2047(char *string, int length, char *charsetsave)
     }
     else {
 	free(storage);
+#ifdef HAVE_ICONV
+        /* make sure there are only ascii chars in the string
+        ** for messages that don't respect rfc2047 */
+        i18n_replace_non_ascii_chars(string);
+#endif
 	return string;
     }
 }
@@ -1540,6 +1546,8 @@ int parsemail(char *mbox,	/* file name */
     int require_filter_len, require_filter_full_len;
     struct hmlist *tlist;
     char filename[MAXFILELEN];
+    char directory[MAXFILELEN];
+    char pathname[MAXFILELEN];
     struct emailinfo *emp;
     char *att_dir = NULL;	/* directory name to store attachments in */
     char *meta_dir = NULL;	/* directory name where we're storing the meta data
@@ -1654,21 +1662,36 @@ int parsemail(char *mbox,	/* file name */
     if(set_append) {
     
 	/* add to an mbox as we read */
-
-	if(set_append_filename && strncmp(set_append_filename, "$DIR/", 5)) {
-	    if(strlen(set_append_filename) >= sizeof(filename))
-	        progerr("append_filename too long");
-	    strcpy(filename, set_append_filename);
+	*directory = 0;
+	*filename = 0;
+	*pathname = 0;
+	if (set_append_filename) {
+            time_t curtime;
+            const struct tm *local_curtime;
+            
+	    time(&curtime);
+            local_curtime = localtime(&curtime);
+            
+	    if(strncmp(set_append_filename, "$DIR/", 5) == 0) {
+	        strncpy(directory, dir, MAXFILELEN - 1);
+                strftime(filename, MAXFILELEN - 1, set_append_filename+5, 
+                         local_curtime);
+            } else {
+                strftime(filename, MAXFILELEN - 1, set_append_filename, 
+                         local_curtime);
+	    }
+	} else {
+	    strncpy(directory, dir, MAXFILELEN - 1);
+	    strncpy(filename, "mbox", MAXFILELEN - 1);
 	}
-	else if(trio_snprintf(filename, sizeof(filename), "%s%s", dir,
-			      set_append_filename ? set_append_filename + 5
-			      : "mbox") 
-	   == sizeof(filename)) {
+
+	if(trio_snprintf(pathname, sizeof(pathname), "%s%s", directory,
+			filename) == sizeof(pathname)) {
 	    progerr("Can't build mbox filename");
 	}
-	if(!(fpo = fopen(filename, "a"))) {
+	if(!(fpo = fopen(pathname, "a"))) {
 	    trio_snprintf(errmsg, sizeof(errmsg), "%s \"%s\".",
-			  lang[MSG_CANNOT_OPEN_MAIL_ARCHIVE], filename);
+			  lang[MSG_CANNOT_OPEN_MAIL_ARCHIVE], pathname);
 	    progerr(errmsg);
 	}
     }
@@ -1809,6 +1832,7 @@ int parsemail(char *mbox,	/* file name */
 		    if (head->header && !head->demimed) {
 		      head->line =
 			mdecodeRFC2047(head->line, strlen(head->line),charsetsave);
+		      head->demimed = TRUE;
 		    }
 
 		    if (head->parsedheader || head->attached ||
@@ -2378,6 +2402,7 @@ int parsemail(char *mbox,	/* file name */
 #endif
                                     if (charset) {
                                         free(charset);
+					charset = NULL;
                                     }
                                     charsetsave[0] = '\0';
 
diff --git a/src/proto.h b/src/proto.h
index 9fe9fc3e..affe20de 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -99,6 +99,7 @@ char *unobfuscate_email_address (char *);
 char *i18n_convstring(char *, char *, char *, size_t *);
 char *i18n_utf2numref(char *, int);
 unsigned char *i18n_numref2utf(char *);
+int i18n_replace_non_ascii_chars(char *);
 
 char *PushByte(struct Push *, char);
 char *PushString(struct Push *, const char *);
diff --git a/src/setup.c b/src/setup.c
index 3735391f..008d4b91 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -412,7 +412,9 @@ struct Config cfg[] = {
     {"append_filename", &set_append_filename, NULL, CFG_STRING,
      "# Specifies the filename to be used by the append option.\n"
      "# $DIR may be used to specify a name relative to the directory\n"
-     "# specified in the -d or dir option.\n", FALSE},
+     "# specified in the -d or dir option.\n"
+     "# The string will be passed to strftime(3) to allow splitting the\n"
+     "# mailbox into yearly or monthy files, such as \"%Y-%m.mbox\".\n" , FALSE},
 
     {"nonsequential",  &set_nonsequential,  BFALSE,    CFG_SWITCH,
      "# Set this to On to generate filenames that are not sequential, but\n"
diff --git a/src/string.c b/src/string.c
index 6d7003b4..78ca1336 100644
--- a/src/string.c
+++ b/src/string.c
@@ -452,6 +452,26 @@ unsigned char *i18n_numref2utf(char *string){
   return headofutfstr;
 }
 
+/* replaces all non 7-bit ascii chars in string by a ? 
+** returns the number of replaced chars
+*/
+int i18n_replace_non_ascii_chars(char *string)
+{
+    char *ptr = string;
+    int count = 0;
+  
+    while (*ptr) {
+        if (!isascii(*ptr) ||
+            (*ptr < 0x20 && *ptr != 0x0a && *ptr != 0x0d && *ptr != 0x09)) {
+            *ptr = '?';
+            count++;
+        }
+        ptr++;
+    }
+    
+    return count;
+}
+
 #endif
 /* end of I18N hack */
 
@@ -1802,22 +1822,40 @@ char *parseurl(char *input, char *charset)
     if (!input || !*input)
 	return NULL;
 
-    c = strstr(input, ":");
+    /*
+     * All our protocol prefixes have this ":" substring in them. Most
+     * of the lines we process don't have any URL. Let's not spend any
+     * time looking for URLs in lines that we can prove cheaply don't
+     * have any; it will be a big win for average input if we follow
+     * this trivial heuristic. 
+     */
     
-    if (!c  /* not found */
-	|| c == input     /* first char in line */
-	|| *(c+1) == '\0'  /* last char in line */
-	|| !isalpha(*(c-1))  /* not between alpha/graph */
-        || !isgraph(*(c+1)))  {
-	/*
-	 * All our protocol prefixes have this ":" substring in them. Most
-	 * of the lines we process don't have any URL. Let's not spend any
-	 * time looking for URLs in lines that we can prove cheaply don't
-	 * have any; it will be a big win for average input if we follow
-	 * this trivial heuristic. 
-	 */
+    first = FALSE;
+    
+    c = strstr(input, ":");
+    if (c == input) { /* first char in line */
+        c++;
+        c = strstr(c, ":");
+    }
+
+    /* !c === not found */
+    while (c) {
+        if (*(c+1) == '\0')  /* last char in line */
+            break;
+        else if ( !isalpha(*(c-1))  /* not between alpha/graph */
+                  || !isgraph(*(c+1)))  {
+            c++;
+            c = strstr(c, ":");
+        } else {
+            first = TRUE;
+            break;
+        }
+    }
+
+    if (!first) {
 	return convchars(input, charset);
     }
+
     INIT_PUSH(buff);
 
     /*
diff --git a/src/uudecode.c b/src/uudecode.c
index 4b4310d2..c0c978a0 100644
--- a/src/uudecode.c
+++ b/src/uudecode.c
@@ -75,7 +75,7 @@ int uudecode(FILE *input,	/* get file data from (if needed) */
     if (init) {
 	/* search for header line */
 	/* AUDIT biege: BOF in buf! */
-	sprintf(scanfstring, "begin %%o %%%us", sizeof(buf));
+	sprintf(scanfstring, "begin %%o %%%us", sizeof(buf) - 1);
 	while (2 != sscanf(iptr, scanfstring, &mode, buf)) {
 	    if (!fgets(buf, MAXPATHLEN, input)) {
 		return 2;
