changeset 520:734ce7aa42bb

1.2.9-RC1 with recipdelim patch
author mmj
date Mon, 10 Oct 2005 00:17:52 +1000
parents a0970041be37
children dd4dfda6487a
files ChangeLog Makefile.am TUNABLES VERSION aclocal.m4 depcomp include/getlistdelim.h include/mlmmj-send.h include/mlmmj-sub.h include/mlmmj-unsub.h include/mlmmj.h include/prepstdreply.h install-sh missing mkinstalldirs src/Makefile.in src/getlistdelim.c src/listcontrol.c src/mlmmj-bounce.c src/mlmmj-process.c src/mlmmj-send.c src/mlmmj-sub.c src/mlmmj-unsub.c src/prepstdreply.c src/send_digest.c src/send_help.c src/send_list.c
diffstat 27 files changed, 383 insertions(+), 180 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Oct 10 00:00:35 2005 +1000
+++ b/ChangeLog	Mon Oct 10 00:17:52 2005 +1000
@@ -1,3 +1,5 @@
+1.2.9
+ o Make recipient delimiter configurable per list. SIC! (Joel Aelwyn)
  o Use is_subbed_in instead of find_subscriber when subscribing people
    (Christian Laursen)
  o Make it possible to confirm subscription even though it's a closedlist.
--- a/Makefile.am	Mon Oct 10 00:00:35 2005 +1000
+++ b/Makefile.am	Mon Oct 10 00:17:52 2005 +1000
@@ -9,7 +9,7 @@
 dist-hook:
 	rm -rf `find $(distdir)/ -name CVS`
 
-man1_MANS = man/mlmmj-bounce.1 man/mlmmj-make-ml.1 man/mlmmj-recieve.1 \
+man1_MANS = man/mlmmj-bounce.1 man/mlmmj-make-ml.sh.1 man/mlmmj-recieve.1 \
 	    man/mlmmj-sub.1 man/mlmmj-maintd.1 man/mlmmj-process.1 \
 	    man/mlmmj-send.1 man/mlmmj-unsub.1 man/mlmmj-list.1
 
--- a/TUNABLES	Mon Oct 10 00:00:35 2005 +1000
+++ b/TUNABLES	Mon Oct 10 00:17:52 2005 +1000
@@ -146,3 +146,8 @@
 
    In this file a port other than port 25 for connecting to the relayhost
    can be specified.
+
+ · delimiter			(normal)
+
+   This specifies what to use as recipient delimiter for the list.
+   Default is "+".
--- a/VERSION	Mon Oct 10 00:00:35 2005 +1000
+++ b/VERSION	Mon Oct 10 00:17:52 2005 +1000
@@ -1,1 +1,1 @@
-1.2.9
+1.2.9-RC1
--- a/aclocal.m4	Mon Oct 10 00:00:35 2005 +1000
+++ b/aclocal.m4	Mon Oct 10 00:17:52 2005 +1000
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.9.5 -*- Autoconf -*-
+# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 # 2005  Free Software Foundation, Inc.
@@ -28,7 +28,7 @@
 # Call AM_AUTOMAKE_VERSION so it can be traced.
 # This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-	 [AM_AUTOMAKE_VERSION([1.9.5])])
+	 [AM_AUTOMAKE_VERSION([1.9.6])])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
--- a/depcomp	Mon Oct 10 00:00:35 2005 +1000
+++ b/depcomp	Mon Oct 10 00:17:52 2005 +1000
@@ -1,7 +1,7 @@
 #! /bin/sh
 # depcomp - compile a program generating dependencies as side-effects
 
-scriptversion=2005-02-09.22
+scriptversion=2005-07-09.11
 
 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
 
@@ -17,8 +17,8 @@
 
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
 
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -467,7 +467,8 @@
   done
 
   "$@" -E |
-    sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
     sed '$ s: \\$::' > "$tmpdepfile"
   rm -f "$depfile"
   echo "$object : \\" > "$depfile"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/getlistdelim.h	Mon Oct 10 00:17:52 2005 +1000
@@ -0,0 +1,29 @@
+/* Copyright 2005 Joel Aelwyn <joel@lightbearer.com>
+ *
+ * $Id$
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef GETLISTDELIM_H
+#define GETLISTDELIM_H
+
+char *getlistdelim(const char *listdir);
+
+#endif /* GETLISTDELIM_H */
--- a/include/mlmmj-send.h	Mon Oct 10 00:00:35 2005 +1000
+++ b/include/mlmmj-send.h	Mon Oct 10 00:17:52 2005 +1000
@@ -31,16 +31,16 @@
 	      size_t bodylen);
 int send_mail_many_fd(int sockfd, const char *from, const char *replyto,
 		   char *mailmap, size_t mailsize, int subfd,
-		   const char *listaddr, const char *archivefilename,
-		   const char *listdir, const char *mlmmjbounce,
-		   const char *hdrs, size_t hdrslen, const char *body,
-		   size_t bodylen);
+		   const char *listaddr, const char *listdelim,
+		   const char *archivefilename, const char *listdir,
+		   const char *mlmmjbounce, const char *hdrs, size_t hdrslen,
+		   const char *body, size_t bodylen);
 int send_mail_many_list(int sockfd, const char *from, const char *replyto,
 		   char *mailmap, size_t mailsize, struct strlist *addrs,
-		   const char *listaddr, const char *archivefilename,
-		   const char *listdir, const char *mlmmjbounce,
-		   const char *hdrs, size_t hdrslen, const char *body,
-		   size_t bodylen);
+		   const char *listaddr, const char *listdelim,
+		   const char *archivefilename, const char *listdir,
+		   const char *mlmmjbounce, const char *hdrs, size_t hdrslen,
+		   const char *body, size_t bodylen);
 int send_mail_verp(int sockfd, struct strlist *addrs, char *mailmap,
 		   size_t mailsize, const char *from, const char *listdir,
 		   const char *hdrs, size_t hdrslen, const char *body,
--- a/include/mlmmj-sub.h	Mon Oct 10 00:00:35 2005 +1000
+++ b/include/mlmmj-sub.h	Mon Oct 10 00:17:52 2005 +1000
@@ -27,10 +27,10 @@
 #include <mlmmj.h>
 
 void confirm_sub(const char *listdir, const char *listaddr,
-		 const char *subaddr, const char *mlmmjsend,
-		 enum subtype typesub);
+		 const char *listdelim, const char *subaddr,
+		 const char *mlmmjsend, enum subtype typesub);
 void generate_subconfirm(const char *listdir, const char *listadr,
-		const char *subaddr, const char *mlmmjsend,
-		enum subtype typesub);
+		const char *listdelim, const char *subaddr,
+		const char *mlmmjsend, enum subtype typesub);
 
 #endif /* MLMMJ_SUBSCRIBE_H */
--- a/include/mlmmj-unsub.h	Mon Oct 10 00:00:35 2005 +1000
+++ b/include/mlmmj-unsub.h	Mon Oct 10 00:17:52 2005 +1000
@@ -27,11 +27,11 @@
 #include <sys/types.h>
 
 void confirm_unsub(const char *listdir, const char *listaddr,
-		   const char *subaddr, const char *mlmmj,
-		   enum subtype typesub);
+		   const char *listdelim, const char *subaddr,
+		   const char *mlmmj, enum subtype typesub);
 ssize_t unsubscribe(int subreadfd, int subwritefd, const char *address);
 void generate_unsubconfirm(const char *listdir, const char *listaddr,
-			   const char *subaddr, const char *mlmmjsend,
-			   enum subtype typesub);
+			   const char *listdelim, const char *subaddr,
+			   const char *mlmmjsend, enum subtype typesub);
 
 #endif /* MLMMJ_UNSUBSCRIBE_H */
--- a/include/mlmmj.h	Mon Oct 10 00:00:35 2005 +1000
+++ b/include/mlmmj.h	Mon Oct 10 00:17:52 2005 +1000
@@ -28,7 +28,7 @@
 
 #define RELAYHOST "127.0.0.1"
 #define READ_BUFSIZE 2048
-#define RECIPDELIM '+'  /* XXX Warning: not changable at the moment */
+#define DEFAULT_RECIPDELIM "+"  /* Default recipient delimiter */
 #define MODREQLIFE 604800 /* How long time will moderation requests be kept?
 			   * 604800s is 7 days */
 #define DISCARDEDLIFE 604800 /* How long time will discarded mails be kept?
--- a/include/prepstdreply.h	Mon Oct 10 00:00:35 2005 +1000
+++ b/include/prepstdreply.h	Mon Oct 10 00:17:52 2005 +1000
@@ -24,10 +24,10 @@
 #ifndef PREPSTDREPLY_H
 #define PREPSTDREPLY_H
 
-char *substitute(const char *line, const char *listaddr, size_t datacount,
-		 char **data);
-char *substitute_one(const char *line, const char *listaddr, size_t datacount,
-		 char **data);
+char *substitute(const char *line, const char *listaddr, const char *listdelim,
+		 size_t datacount, char **data);
+char *substitute_one(const char *line, const char *listaddr,
+		 const char *listdelim, size_t datacount, char **data);
 char *prepstdreply(const char *listdir, const char *filename, const char *from,
 		   const char *to, const char *replyto, size_t tokencount,
 		   char **data);
--- a/install-sh	Mon Oct 10 00:00:35 2005 +1000
+++ b/install-sh	Mon Oct 10 00:17:52 2005 +1000
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2005-02-02.21
+scriptversion=2005-05-14.22
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
--- a/missing	Mon Oct 10 00:00:35 2005 +1000
+++ b/missing	Mon Oct 10 00:17:52 2005 +1000
@@ -1,7 +1,7 @@
 #! /bin/sh
 # Common stub for a few missing GNU programs while installing.
 
-scriptversion=2005-02-08.22
+scriptversion=2005-06-08.21
 
 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
 #   Free Software Foundation, Inc.
@@ -19,8 +19,8 @@
 
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
 
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -297,6 +297,9 @@
       # ... or it is derived from the source name (dir/f.texi becomes f.info)
       test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
     fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
     touch $file
     ;;
 
--- a/mkinstalldirs	Mon Oct 10 00:00:35 2005 +1000
+++ b/mkinstalldirs	Mon Oct 10 00:17:52 2005 +1000
@@ -1,7 +1,7 @@
 #! /bin/sh
 # mkinstalldirs --- make directory hierarchy
 
-scriptversion=2005-02-02.21
+scriptversion=2005-06-29.22
 
 # Original author: Noah Friedman <friedman@prep.ai.mit.edu>
 # Created: 1993-05-16
@@ -12,7 +12,7 @@
 # <automake-patches@gnu.org>.
 
 errstatus=0
-dirmode=""
+dirmode=
 
 usage="\
 Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
@@ -103,13 +103,21 @@
 
 for file
 do
-  set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+  case $file in
+    /*) pathcomp=/ ;;
+    *)  pathcomp= ;;
+  esac
+  oIFS=$IFS
+  IFS=/
+  set fnord $file
   shift
+  IFS=$oIFS
 
-  pathcomp=
   for d
   do
-    pathcomp="$pathcomp$d"
+    test "x$d" = x && continue
+
+    pathcomp=$pathcomp$d
     case $pathcomp in
       -*) pathcomp=./$pathcomp ;;
     esac
@@ -124,7 +132,7 @@
       else
 	if test ! -z "$dirmode"; then
 	  echo "chmod $dirmode $pathcomp"
-	  lasterr=""
+	  lasterr=
 	  chmod "$dirmode" "$pathcomp" || lasterr=$?
 
 	  if test ! -z "$lasterr"; then
@@ -134,7 +142,7 @@
       fi
     fi
 
-    pathcomp="$pathcomp/"
+    pathcomp=$pathcomp/
   done
 done
 
--- a/src/Makefile.in	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/Makefile.in	Mon Oct 10 00:17:52 2005 +1000
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -17,8 +17,6 @@
 #
 
 
-SOURCES = $(mlmmj_bounce_SOURCES) $(mlmmj_list_SOURCES) $(mlmmj_maintd_SOURCES) $(mlmmj_process_SOURCES) $(mlmmj_recieve_SOURCES) $(mlmmj_send_SOURCES) $(mlmmj_sub_SOURCES) $(mlmmj_unsub_SOURCES)
-
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 VPATH = @srcdir@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getlistdelim.c	Mon Oct 10 00:17:52 2005 +1000
@@ -0,0 +1,70 @@
+/* Copyright 2005 Joel Aelwyn <joel@lightbearer.com>
+ *
+ * $Id$
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "mlmmj.h"
+#include "getlistdelim.h"
+#include "chomp.h"
+#include "log_error.h"
+#include "mygetline.h"
+#include "strgen.h"
+#include "memory.h"
+
+char *getlistdelim(const char *listdir)
+{
+	char *delimfn, *delimstr;
+	int delimfd;
+
+	delimfn = concatstr(2, listdir, "/control/delimiter");
+	if(-1 != (delimfd = open(delimfn, O_RDONLY))){
+		delimstr = mygetline(delimfd);
+		close(delimfd);
+
+		if(NULL == delimstr){
+			log_error(LOG_ARGS,
+				  "FATAL. Could not get list delimiter from %s",
+				  delimfn);
+			myfree(delimfn);
+			exit(EXIT_FAILURE);
+		}
+	
+		chomp(delimstr);
+	
+		if(0 == strlen(delimstr)){
+			log_error(LOG_ARGS,
+				  "FATAL. Zero-length delimiter found from %s",
+				  delimfn);
+			myfree(delimfn);
+			exit(EXIT_FAILURE);
+		}
+	} else
+		delimstr = mystrdup(DEFAULT_RECIPDELIM);
+
+	myfree(delimfn);
+
+	return delimstr;
+}
--- a/src/listcontrol.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/listcontrol.c	Mon Oct 10 00:17:52 2005 +1000
@@ -34,6 +34,7 @@
 #include "mlmmj.h"
 #include "listcontrol.h"
 #include "find_email_adr.h"
+#include "getlistdelim.h"
 #include "strgen.h"
 #include "send_help.h"
 #include "send_list.h"
@@ -101,7 +102,7 @@
 		const char *mlmmjunsub, const char *mlmmjsend,
 		const char *mlmmjbounce, const char *mailname)
 {
-	char *atsign, *recipdelimsign, *bouncenr, *tmpstr;
+	char *atsign, *recipdelimsign, *listdelim, *bouncenr, *tmpstr;
 	char *controlstr, *param = NULL, *conffilename, *moderatefilename;
 	char *c, *archivefilename, *sendfilename;
 	const char *subswitch;
@@ -121,7 +122,8 @@
 	else
 		subswitch = "-C";
 	
-	recipdelimsign = index(controladdr, RECIPDELIM);
+	listdelim = getlistdelim(listdir);
+	recipdelimsign = strstr(controladdr, listdelim);
 	MY_ASSERT(recipdelimsign);
 	atsign = index(controladdr, '@');
 	MY_ASSERT(atsign);
@@ -129,7 +131,8 @@
 
 	controlstr = mymalloc(len);
 	MY_ASSERT(controlstr);
-	snprintf(controlstr, len, "%s", recipdelimsign + 1);
+	snprintf(controlstr, len, "%s", recipdelimsign + strlen(listdelim));
+	myfree(listdelim);
 
 #if 0
 	log_error(LOG_ARGS, "controlstr = [%s]\n", controlstr);
--- a/src/mlmmj-bounce.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/mlmmj-bounce.c	Mon Oct 10 00:17:52 2005 +1000
@@ -36,6 +36,7 @@
 #include <ctype.h>
 
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "mlmmj.h"
 #include "strgen.h"
 #include "wrappers.h"
@@ -101,7 +102,7 @@
 void do_probe(const char *listdir, const char *mlmmjsend, const char *addr)
 {
 	char *myaddr, *from, *a, *indexstr, *queuefilename, *listaddr;
-	char *listfqdn, *listname, *probefile;
+	char *listfqdn, *listname, *probefile, *listdelim=getlistdelim(listdir);
 	char *maildata[] = { "bouncenumbers", NULL };
 	int fd;
 	time_t t;
@@ -112,9 +113,11 @@
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 
-	from = concatstr(5, listname, "+bounces-probe-", myaddr, "@", listfqdn);
+	from = concatstr(6, listname, listdelim, "bounces-probe-", myaddr, "@",
+			 listfqdn);
 
 	myfree(listaddr);
+	myfree(listdelim);
 	myfree(listfqdn);
 	myfree(listname);
 
--- a/src/mlmmj-process.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/mlmmj-process.c	Mon Oct 10 00:17:52 2005 +1000
@@ -37,6 +37,7 @@
 #include "find_email_adr.h"
 #include "incindexfile.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "listcontrol.h"
 #include "strgen.h"
 #include "do_all_the_voodo_here.h"
@@ -71,7 +72,7 @@
 		  const char *mlmmjsend)
 {
 	char *from, *listfqdn, *listname, *moderators = NULL;
-	char *buf, *replyto, *listaddr = getlistaddr(listdir);
+	char *buf, *replyto, *listaddr = getlistaddr(listdir), *listdelim;
 	char *queuefilename = NULL, *moderatorsfilename;
 	char *mailbasename = mybasename(mailfilename), *tmp, *to;
 	int queuefd, moderatorsfd, mailfd;
@@ -106,15 +107,17 @@
 
 	close(moderatorsfd);
 
-	replyto = concatstr(5, listname, "+moderate-", mailbasename, "@",
-			    listfqdn);
+	listdelim = getlistdelim(listdir);
+	replyto = concatstr(6, listname, listdelim, "moderate-", mailbasename,
+			    "@", listfqdn);
 
 	maildata[1] = replyto;
 	maildata[3] = moderators;
 
-	from = concatstr(3, listname, "+owner@", listfqdn);
-	to = concatstr(3, listname, "-moderators@", listfqdn);
+	from = concatstr(4, listname, listdelim, "owner@", listfqdn);
+	to = concatstr(3, listname, "-moderators@", listfqdn); /* FIXME JFA: Should this be converted? Why, why not? */
 
+	myfree(listdelim);
 	myfree(listname);
 	myfree(listfqdn);
 
@@ -318,9 +321,9 @@
 	char *footerfilename = NULL, *donemailname = NULL;
 	char *randomstr = NULL, *mqueuename;
 	char *mlmmjsend, *mlmmjsub, *mlmmjunsub, *mlmmjbounce;
-	char *bindir, *subjectprefix, *discardname, *listaddr;
+	char *bindir, *subjectprefix, *discardname, *listaddr, *listdelim;
 	char *listfqdn, *listname, *fromaddr;
-	char *queuefilename, *recipdelim, *owner = NULL;
+	char *queuefilename, *recipextra, *owner = NULL;
 	char *maildata[2] = { "posteraddr", NULL };
 	struct stat st;
 	uid_t uid;
@@ -512,14 +515,18 @@
 	else
 		whichto = NULL;
 
-	if(whichto && whichto->emaillist && whichto->emaillist[0])
-		recipdelim = strchr(whichto->emaillist[0], RECIPDELIM);
-	else
-		recipdelim = NULL;
+	listdelim = getlistdelim(listdir);
+	if(whichto && whichto->emaillist && whichto->emaillist[0]){
+		recipextra = strstr(whichto->emaillist[0], listdelim);
+		if (recipextra)
+			recipextra += strlen(listdelim);
+	} else
+		recipextra = NULL;
+	myfree(listdelim);
 
-	if(recipdelim) {
+	if(recipextra) {
 		owner = concatstr(2, listdir, "/control/owner");
-		if(owner && strncmp(recipdelim, "+owner@", 7) == 0) {
+		if(owner && strncmp(recipextra, "owner@", 6) == 0) {
 			/* strip envelope from before resending */
 			delheaders->count = 0;
 			delheaders->strs = NULL;
@@ -643,13 +650,16 @@
 			myfree(donemailname);
 			exit(EXIT_SUCCESS);
 		}
+		listdelim = getlistdelim(listdir);
 		listname = genlistname(listaddr);
 		listfqdn = genlistfqdn(listaddr);
-		fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+		fromaddr = concatstr(4, listname, listdelim, "bounces-help@",
+				     listfqdn);
 		queuefilename = prepstdreply(listdir, "notintocc",
 					"$listowner$", fromemails.emaillist[0],
 					NULL, 0, NULL);
 		MY_ASSERT(queuefilename)
+		myfree(listdelim);
 		myfree(listname);
 		myfree(listfqdn);
 		unlink(donemailname);
@@ -683,16 +693,18 @@
 				myfree(donemailname);
 				exit(EXIT_SUCCESS);
 			}
+			listdelim = getlistdelim(listdir);
 			listname = genlistname(listaddr);
 			listfqdn = genlistfqdn(listaddr);
 			maildata[1] = fromemails.emaillist[0];
-			fromaddr = concatstr(3, listname, "+bounces-help@",
-					listfqdn);
+			fromaddr = concatstr(4, listname, listdelim,
+					"bounces-help@", listfqdn);
 			queuefilename = prepstdreply(listdir, "subonlypost",
 					"$listowner$", fromemails.emaillist[0],
 					NULL, 1, maildata);
 			MY_ASSERT(queuefilename)
 			myfree(listaddr);
+			myfree(listdelim);
 			myfree(listname);
 			myfree(listfqdn);
 			unlink(donemailname);
@@ -724,16 +736,18 @@
 				myfree(donemailname);
 				exit(EXIT_SUCCESS);
 			}
+			listdelim = getlistdelim(listdir);
 			listname = genlistname(listaddr);
 			listfqdn = genlistfqdn(listaddr);
-			fromaddr = concatstr(3, listname, "+bounces-help@",
-					listfqdn);
+			fromaddr = concatstr(4, listname, listdelim,
+					"bounces-help@", listfqdn);
 			queuefilename = prepstdreply(listdir, "access",
 							"$listowner$",
 							fromemails.emaillist[0],
 							NULL, 0, NULL);
 			MY_ASSERT(queuefilename)
 			myfree(listaddr);
+			myfree(listdelim);
 			myfree(listname);
 			myfree(listfqdn);
 			unlink(donemailname);
--- a/src/mlmmj-send.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/mlmmj-send.c	Mon Oct 10 00:17:52 2005 +1000
@@ -51,6 +51,7 @@
 #include "chomp.h"
 #include "checkwait_smtpreply.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "init_sockfd.h"
 #include "strgen.h"
 #include "log_error.h"
@@ -73,9 +74,9 @@
 }
 
 char *bounce_from_adr(const char *recipient, const char *listadr,
-		      const char *mailfilename)
+		      const char *listdelim, const char *mailfilename)
 {
-	char *bounceaddr, *myrecipient, *mylistadr;
+	char *bounceaddr, *myrecipient, *mylistadr, *mylistdelim;
 	char *indexstr, *listdomain, *a = NULL, *mymailfilename;
 	size_t len;
 
@@ -107,29 +108,40 @@
 		return NULL;
 	}
 
-	listdomain = strchr(mylistadr, '@');
-	if (!listdomain) {
+	mylistdelim = mystrdup(listdelim);
+	if (!mylistdelim) {
 		myfree(mymailfilename);
 		myfree(myrecipient);
 		myfree(mylistadr);
 		return NULL;
 	}
+
+	listdomain = strchr(mylistadr, '@');
+	if (!listdomain) {
+		myfree(mymailfilename);
+		myfree(myrecipient);
+		myfree(mylistadr);
+		myfree(mylistdelim);
+		return NULL;
+	}
 	*listdomain++ = '\0';
 
-	/* 12 = RECIPDELIM + "bounces-" + "-" + "@" + NUL */
-	len = strlen(mylistadr) + strlen(myrecipient) + strlen(indexstr)
-		 + strlen(listdomain) + 12;
+	/* 11 = "bounces-" + "-" + "@" + NUL */
+	len = strlen(mylistadr) + strlen(mylistdelim) + strlen(myrecipient)
+		 + strlen(indexstr) + strlen(listdomain) + 11;
 	bounceaddr = mymalloc(len);
 	if (!bounceaddr) {
 		myfree(myrecipient);
 		myfree(mylistadr);
+		myfree(mylistdelim);
 		return NULL;
 	}
-	snprintf(bounceaddr, len, "%s%cbounces-%s-%s@%s", mylistadr, RECIPDELIM,
+	snprintf(bounceaddr, len, "%s%sbounces-%s-%s@%s", mylistadr, listdelim,
 		 indexstr, myrecipient, listdomain);
 
 	myfree(myrecipient);
 	myfree(mylistadr);
+	myfree(mylistdelim);
 	myfree(mymailfilename);
 
 	return bounceaddr;
@@ -138,18 +150,20 @@
 int bouncemail(const char *listdir, const char *mlmmjbounce, const char *from)
 {
 	char *myfrom = mystrdup(from);
+	char *listdelim = getlistdelim(listdir);
 	char *addr, *num, *c;
 	size_t len;
 	pid_t pid = 0;
 
 	if((c = strchr(myfrom, '@')) == NULL) {
 		myfree(myfrom);
+		myfree(listdelim);
 		return 0; /* Success when malformed 'from' */
 	}
 	*c = '\0';
 	num = strrchr(myfrom, '-');
 	num++;
-	c = strchr(myfrom, RECIPDELIM);
+	c = strstr(myfrom, listdelim);
 	myfrom = strchr(c, '-');
 	myfrom++;
 	len = num - myfrom - 1;
@@ -157,6 +171,8 @@
 	addr[len] = '\0';
 	strncpy(addr, myfrom, len);
 
+	myfree(listdelim);
+
 	pid = fork();
 	
 	if(pid < 0) {
@@ -464,10 +480,10 @@
 
 int send_mail_many_fd(int sockfd, const char *from, const char *replyto,
 		      char *mailmap, size_t mailsize, int subfd,
-		      const char *listaddr, const char *archivefilename,
-		      const char *listdir, const char *mlmmjbounce,
-		      const char *hdrs, size_t hdrslen, const char *body,
-		      size_t bodylen)
+		      const char *listaddr, const char *listdelim,
+		      const char *archivefilename, const char *listdir,
+		      const char *mlmmjbounce, const char *hdrs, size_t hdrslen,
+		      const char *body, size_t bodylen)
 {
 	int res, ret, i;
 	struct strlist stl;
@@ -480,8 +496,9 @@
 		if(stl.count == maxverprecips) {
 			ret = send_mail_many_list(sockfd, from, replyto,
 					mailmap, mailsize, &stl, listaddr,
-					archivefilename, listdir, mlmmjbounce,
-					hdrs, hdrslen, body, bodylen);
+					listdelim, archivefilename, listdir,
+					mlmmjbounce, hdrs, hdrslen,
+					body, bodylen);
 			for(i = 0; i < stl.count; i++)
 				myfree(stl.strs[i]);
 			if(ret < 0)
@@ -492,9 +509,9 @@
 
 	if(stl.count) {
 		ret = send_mail_many_list(sockfd, from, replyto, mailmap,
-				mailsize, &stl, listaddr, archivefilename,
-				listdir, mlmmjbounce, hdrs, hdrslen, body,
-				bodylen);
+				mailsize, &stl, listaddr, listdelim,
+				archivefilename, listdir, mlmmjbounce,
+				hdrs, hdrslen, body, bodylen);
 		for(i = 0; i < stl.count; i++)
 			myfree(stl.strs[i]);
 		stl.count = 0;
@@ -557,10 +574,10 @@
 
 int send_mail_many_list(int sockfd, const char *from, const char *replyto,
 		   char *mailmap, size_t mailsize, struct strlist *addrs,
-		   const char *listaddr, const char *archivefilename,
-		   const char *listdir, const char *mlmmjbounce,
-		   const char *hdrs, size_t hdrslen, const char *body,
-		   size_t bodylen)
+		   const char *listaddr, const char *listdelim,
+		   const char *archivefilename, const char *listdir,
+		   const char *mlmmjbounce, const char *hdrs, size_t hdrslen,
+		   const char *body, size_t bodylen)
 {
 	int res = 0, i;
 	char *bounceaddr, *addr, *index;
@@ -585,7 +602,7 @@
 					    mailmap, mailsize, listdir, NULL,
 					    hdrs, hdrslen, body, bodylen);
 		} else {
-			bounceaddr = bounce_from_adr(addr, listaddr,
+			bounceaddr = bounce_from_adr(addr, listaddr, listdelim,
 						     archivefilename);
 			res = send_mail(sockfd, bounceaddr, addr, replyto,
 				  mailmap, mailsize, listdir, mlmmjbounce,
@@ -634,7 +651,8 @@
 	int sockfd = -1, mailfd = 0, opt, mindex = 0, subfd = 0, tmpfd, i;
 	int deletewhensent = 1, sendres = 0, archive = 1, digest = 0;
 	int ctrlarchive, res;
-	char *listaddr = NULL, *mailfilename = NULL, *subfilename = NULL;
+	char *listaddr = NULL, *listdelim = NULL;
+	char *mailfilename = NULL, *subfilename = NULL;
 	char *replyto = NULL, *bounceaddr = NULL, *to_addr = NULL;
 	char *relayhost = NULL, *archivefilename = NULL, *tmpstr;
 	char *listctrl = NULL, *subddirname = NULL, *listdir = NULL;
@@ -845,6 +863,9 @@
 		}
 	}
 
+	if(listdir)
+		listdelim = getlistdelim(listdir);
+
 	switch(listctrl[0]) {
 	case '1': /* A single mail is to be sent, do nothing */
 	case '5':
@@ -857,6 +878,7 @@
 			myfree(hdrs);
 			myfree(body);
 			myfree(subfilename);
+			myfree(listdelim);
 			/* No moderators is no error. Could be the sysadmin
 			 * likes to do it manually.
 			 */
@@ -870,6 +892,7 @@
 					    subfilename);
 			myfree(hdrs);
 			myfree(body);
+			myfree(listdelim);
 			exit(EXIT_FAILURE);
 		}
 		break;
@@ -877,7 +900,7 @@
 		archive = 0;
 		deletewhensent = 0;
 		archivefilename = mystrdup(mailfilename);
-		bounceaddr = bounce_from_adr(to_addr, listaddr,
+		bounceaddr = bounce_from_adr(to_addr, listaddr, listdelim,
 						archivefilename);
 		break;
 	default: /* normal list mail -- now handled when forking */
@@ -977,8 +1000,9 @@
 	case '2': /* Moderators */
 		initsmtp(&sockfd, relay, smtpport);
 		if(send_mail_many_fd(sockfd, bounceaddr, NULL, mailmap,
-				     st.st_size, subfd, NULL, NULL, listdir,
-				     NULL, hdrs, hdrslen, body, bodylen))
+				     st.st_size, subfd, NULL, NULL, NULL,
+				     listdir, NULL, hdrs, hdrslen,
+				     body, bodylen))
 			close(sockfd);
 		else
 			endsmtp(&sockfd);
@@ -986,8 +1010,9 @@
 	case '3': /* resending earlier failed mails */
 		initsmtp(&sockfd, relay, smtpport);
 		if(send_mail_many_fd(sockfd, NULL, NULL, mailmap, st.st_size,
-				subfd, listaddr, mailfilename, listdir,
-				mlmmjbounce, hdrs, hdrslen, body, bodylen))
+				subfd, listaddr, listdelim, mailfilename,
+				listdir, mlmmjbounce, hdrs, hdrslen,
+				body, bodylen))
 			close(sockfd);
 		else
 			endsmtp(&sockfd);
@@ -996,9 +1021,9 @@
 	case '4': /* send mails to owner */
 		initsmtp(&sockfd, relay, smtpport);
 		if(send_mail_many_fd(sockfd, bounceaddr, NULL, mailmap,
-				st.st_size, subfd, listaddr, mailfilename,
-				listdir, mlmmjbounce, hdrs, hdrslen, body,
-				bodylen))
+				st.st_size, subfd, listaddr, listdelim,
+				mailfilename, listdir, mlmmjbounce,
+				hdrs, hdrslen, body, bodylen))
 			close(sockfd);
 		else
 			endsmtp(&sockfd);
@@ -1035,16 +1060,18 @@
 		if((subddir = opendir(subddirname)) == NULL) {
 			log_error(LOG_ARGS, "Could not opendir(%s)",
 					    subddirname);
+			myfree(listdelim);
 			myfree(subddirname);
 			myfree(hdrs);
 			myfree(body);
 			exit(EXIT_FAILURE);
 		}
 
+		listdelim = getlistdelim(listdir);
 		listname = genlistname(listaddr);	
 		listfqdn = genlistfqdn(listaddr);	
-		verpfrom = concatstr(5, listname, "+bounces-", strindex, "@",
-				listfqdn);
+		verpfrom = concatstr(6, listname, listdelim, "bounces-",
+				strindex, "@", listfqdn);
 		myfree(listname);
 		myfree(listfqdn);
 
@@ -1120,6 +1147,7 @@
 								st.st_size,
 								&stl,
 								listaddr,
+								listdelim,
 								archivefilename,
 								listdir,
 								mlmmjbounce,
@@ -1149,7 +1177,7 @@
 			} else {
 				sendres = send_mail_many_list(sockfd, NULL,
 						NULL, mailmap, st.st_size,
-						&stl, listaddr,
+						&stl, listaddr, listdelim,
 						archivefilename, listdir,
 						mlmmjbounce, hdrs, hdrslen,
 						body, bodylen);
@@ -1180,6 +1208,7 @@
 		myfree(stl.strs[i]);
 	stl.count = 0;
 
+	myfree(listdelim);
 	myfree(hdrs);
 	myfree(body);
 	myfree(mlmmjbounce);
--- a/src/mlmmj-sub.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/mlmmj-sub.c	Mon Oct 10 00:17:52 2005 +1000
@@ -38,6 +38,7 @@
 #include "mylocking.h"
 #include "wrappers.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "strgen.h"
 #include "subscriberfuncs.h"
 #include "log_error.h"
@@ -47,15 +48,15 @@
 #include "memory.h"
 
 void confirm_sub(const char *listdir, const char *listaddr,
-		const char *subaddr, const char *mlmmjsend,
-		enum subtype typesub)
+		const char *listdelim, const char *subaddr,
+		const char *mlmmjsend, enum subtype typesub)
 {
 	char *queuefilename, *fromaddr, *listname, *listfqdn, *listtext;
 
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
 
 	myfree(listname);
 	myfree(listfqdn);
@@ -88,8 +89,8 @@
 }
 
 void notify_sub(const char *listdir, const char *listaddr,
-		const char *subaddr, const char *mlmmjsend,
-		enum subtype typesub)
+		const char *listdelim, const char *subaddr,
+		const char *mlmmjsend, enum subtype typesub)
 {
 	char *maildata[2] = { "newsub", NULL };
 	char *listfqdn, *listname, *fromaddr, *tostr;
@@ -100,8 +101,8 @@
 
 	maildata[1] = mystrdup(subaddr);
 	
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
-	tostr = concatstr(3, listname, "+owner@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
+	tostr = concatstr(4, listname, listdelim, "owner@", listfqdn);
 	
 	myfree(listname);
 	myfree(listfqdn);
@@ -135,8 +136,8 @@
 }
 
 void generate_subconfirm(const char *listdir, const char *listaddr,
-			 const char *subaddr, const char *mlmmjsend,
-			 enum subtype typesub)
+			 const char *listdelim, const char *subaddr,
+			 const char *mlmmjsend, enum subtype typesub)
 {
 	int subconffd;
 	char *confirmaddr, *listname, *listfqdn, *confirmfilename = NULL;
@@ -177,26 +178,27 @@
 
 	close(subconffd);
 
-	fromaddr = concatstr(5, listname, "+bounces-confsub-", randomstr,
-				"@", listfqdn);
+	fromaddr = concatstr(6, listname, listdelim, "bounces-confsub-",
+				randomstr, "@", listfqdn);
 	
 	switch(typesub) {
 		default:
 		case SUB_NORMAL:
 			listtext = mystrdup("sub-confirm");
-			tmpstr = mystrdup("+confsub-");
+			tmpstr = mystrdup("confsub-");
 			break;
 		case SUB_DIGEST:
 			listtext = mystrdup("sub-confirm-digest");
-			tmpstr = mystrdup("+confsub-digest-");
+			tmpstr = mystrdup("confsub-digest-");
 			break;
 		case SUB_NOMAIL:
 			listtext = mystrdup("sub-confirm-nomail");
-			tmpstr = mystrdup("+confsub-nomail-");
+			tmpstr = mystrdup("confsub-nomail-");
 			break;
 	}
 
-	confirmaddr = concatstr(5, listname, tmpstr, randomstr, "@", listfqdn);
+	confirmaddr = concatstr(6, listname, listdelim, tmpstr, randomstr, "@",
+				listfqdn);
 
 	myfree(randomstr);
 	myfree(tmpstr);
@@ -245,12 +247,14 @@
 		const char *mlmmjsend)
 {
 	char *queuefilename, *fromaddr, *listname, *listfqdn, *listaddr;
+	char *listdelim = getlistdelim(listdir);
 
 	listaddr = getlistaddr(listdir);
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
+	myfree(listdelim);
 
 	queuefilename = prepstdreply(listdir, "sub-subscribed", "$helpaddr$",
 				     subaddr, NULL, 0, NULL);
@@ -272,9 +276,9 @@
 
 int main(int argc, char **argv)
 {
-	char *listaddr, *listdir = NULL, *address = NULL, *subfilename = NULL;
-	char *mlmmjsend, *bindir, chstr[2], *subdir, *subddirname = NULL;
-	char *sublockname;
+	char *listaddr, *listdelim, *listdir = NULL, *address = NULL;
+	char *subfilename = NULL, *mlmmjsend, *bindir, chstr[2], *subdir;
+	char *subddirname = NULL, *sublockname;
 	int subconfirm = 0, confirmsub = 0, opt, subfilefd, lock, notifysub;
 	int changeuid = 1, status, digest = 0, nomail = 0;
 	int groupwritable = 0, sublock, sublockfd, nogensubscribed = 0, subbed;
@@ -438,14 +442,15 @@
 		exit(EXIT_FAILURE);
 	}
 	subbed = is_subbed_in(subddirname, address);
+	listdelim = getlistdelim(listdir);
 	if(subbed) {
 		if(subconfirm) {
 			close(subfilefd);
 			close(sublockfd);
 			unlink(sublockname);
 			myfree(sublockname);
-			generate_subconfirm(listdir, listaddr, address,
-					    mlmmjsend, typesub);
+			generate_subconfirm(listdir, listaddr, listdelim,
+					    address, mlmmjsend, typesub);
 		} else {
 			lseek(subfilefd, 0L, SEEK_END);
 			len = strlen(address);
@@ -478,8 +483,8 @@
 
 		if(childpid < 0) {
 			log_error(LOG_ARGS, "Could not fork");
-			confirm_sub(listdir, listaddr, address, mlmmjsend,
-					typesub);
+			confirm_sub(listdir, listaddr, listdelim, address,
+					mlmmjsend, typesub);
 		}
 		
 		if(childpid > 0) {
@@ -490,17 +495,19 @@
 
 		/* child confirms subscription */
 		if(childpid == 0)
-			confirm_sub(listdir, listaddr, address, mlmmjsend,
-					typesub);
+			confirm_sub(listdir, listaddr, listdelim, address,
+					mlmmjsend, typesub);
 	}
 
 	notifysub = statctrl(listdir, "notifysub");
 
 	/* Notify list owner about subscription */
 	if (notifysub)
-		notify_sub(listdir, listaddr, address, mlmmjsend, typesub);
+		notify_sub(listdir, listaddr, listdelim, address, mlmmjsend,
+				typesub);
 
 	myfree(listaddr);
+	myfree(listdelim);
 
 	return EXIT_SUCCESS;
 }
--- a/src/mlmmj-unsub.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/mlmmj-unsub.c	Mon Oct 10 00:17:52 2005 +1000
@@ -39,6 +39,7 @@
 #include "wrappers.h"
 #include "mygetline.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "subscriberfuncs.h"
 #include "strgen.h"
 #include "log_error.h"
@@ -47,15 +48,15 @@
 #include "prepstdreply.h"
 
 void confirm_unsub(const char *listdir, const char *listaddr,
-		   const char *subaddr, const char *mlmmjsend,
-		   enum subtype typesub)
+		   const char *listdelim, const char *subaddr,
+		   const char *mlmmjsend, enum subtype typesub)
 {
 	char *queuefilename, *fromaddr, *listname, *listfqdn, *listtext;
 
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
 
 	myfree(listname);
 	myfree(listfqdn);
@@ -89,8 +90,8 @@
 }
 
 void notify_unsub(const char *listdir, const char *listaddr,
-		  const char *subaddr, const char *mlmmjsend,
-		  enum subtype typesub)
+		  const char *listdelim, const char *subaddr,
+		  const char *mlmmjsend, enum subtype typesub)
 {
         char *maildata[4] = { "oldsub", NULL };
         char *listfqdn, *listname, *fromaddr, *tostr;
@@ -101,8 +102,8 @@
 
         maildata[1] = mystrdup(subaddr);
 
-        fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
-	tostr = concatstr(3, listname, "+owner@", listfqdn);
+        fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
+	tostr = concatstr(4, listname, listdelim, "owner@", listfqdn);
 
 	myfree(listname);
 	myfree(listfqdn);
@@ -138,8 +139,8 @@
 
 
 void generate_unsubconfirm(const char *listdir, const char *listaddr,
-			   const char *subaddr, const char *mlmmjsend,
-			   enum subtype typesub)
+			   const char *listdelim, const char *subaddr,
+			   const char *mlmmjsend, enum subtype typesub)
 {
 	char *confirmaddr, *listname, *listfqdn, *tmpstr;
 	char *queuefilename, *fromaddr;
@@ -180,26 +181,27 @@
 
 	close(subconffd);
 
-	fromaddr = concatstr(5, listname, "+bounces-confunsub-", randomstr,
-				"@", listfqdn);
+	fromaddr = concatstr(6, listname, listdelim, "bounces-confunsub-",
+				randomstr, "@", listfqdn);
 
 	switch(typesub) {
 		default:
 		case SUB_NORMAL:
 			listtext = mystrdup("unsub-confirm");
-			tmpstr = mystrdup("+confunsub-");
+			tmpstr = mystrdup("confunsub-");
 			break;
 		case SUB_DIGEST:
 			listtext = mystrdup("unsub-confirm-digest");
-			tmpstr = mystrdup("+confunsub-digest-");
+			tmpstr = mystrdup("confunsub-digest-");
 			break;
 		case SUB_NOMAIL:
 			listtext = mystrdup("unsub-confirm-nomail");
-			tmpstr = mystrdup("+confunsub-nomail-");
+			tmpstr = mystrdup("confunsub-nomail-");
 			break;
 	}
 
-	confirmaddr = concatstr(5, listname, tmpstr, randomstr, "@", listfqdn);
+	confirmaddr = concatstr(6, listname, listdelim, tmpstr, randomstr, "@",
+				listfqdn);
 
 	myfree(randomstr);
 	myfree(tmpstr);
@@ -289,12 +291,14 @@
 		const char *mlmmjsend)
 {
 	char *queuefilename, *fromaddr, *listname, *listfqdn, *listaddr;
+	char *listdelim = getlistdelim(listdir);
 
 	listaddr = getlistaddr(listdir);
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
+	myfree(listdelim);
 
 	queuefilename = prepstdreply(listdir, "unsub-notsubscribed",
 				     "$helpaddr$", subaddr, NULL, 0, NULL);
@@ -321,8 +325,8 @@
 	int confirmunsub = 0, unsubconfirm = 0, notifysub = 0, digest = 0;
 	int changeuid = 1, groupwritable = 0, sublock, sublockfd;
 	int nogennotsubscribed = 0;
-	char *listaddr, *listdir = NULL, *address = NULL, *subreadname = NULL;
-	char *subwritename, *mlmmjsend, *bindir, *subdir;
+	char *listaddr, *listdelim, *listdir = NULL, *address = NULL;
+	char *subreadname = NULL, *subwritename, *mlmmjsend, *bindir, *subdir;
 	char *subddirname, *sublockname;
 	off_t suboff;
 	DIR *subddir;
@@ -446,15 +450,17 @@
 		exit(EXIT_SUCCESS);
 	}
 
+	listdelim = getlistdelim(listdir);
 	if(unsubconfirm)
-		generate_unsubconfirm(listdir, listaddr, address, mlmmjsend,
-				typesub);
+		generate_unsubconfirm(listdir, listaddr, listdelim, address,
+				mlmmjsend, typesub);
 
 	if((subddir = opendir(subddirname)) == NULL) {
 		log_error(LOG_ARGS, "Could not opendir(%s)",
 				    subddirname);
 		myfree(subddirname);
 		myfree(listaddr);
+		myfree(listdelim);
 		exit(EXIT_FAILURE);
 	}
 
@@ -582,8 +588,8 @@
 
 			if(childpid < 0) {
 				log_error(LOG_ARGS, "Could not fork");
-				confirm_unsub(listdir, listaddr, address,
-						mlmmjsend, digest);
+				confirm_unsub(listdir, listaddr, listdelim,
+						address, mlmmjsend, digest);
 			}
 
 			if(childpid > 0) {
@@ -594,8 +600,8 @@
 
 			/* child confirms subscription */
 			if(childpid == 0)
-				confirm_unsub(listdir, listaddr, address,
-						mlmmjsend, digest);
+				confirm_unsub(listdir, listaddr, listdelim,
+						address, mlmmjsend, digest);
 		}
         }
 
@@ -605,9 +611,11 @@
 
         /* Notify list owner about subscription */
         if (notifysub)
-                notify_unsub(listdir, listaddr, address, mlmmjsend, typesub);
+                notify_unsub(listdir, listaddr, listdelim, address, mlmmjsend,
+				typesub);
 
 	myfree(listaddr);
+	myfree(listdelim);
 
 	return EXIT_SUCCESS;
 }
--- a/src/prepstdreply.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/prepstdreply.c	Mon Oct 10 00:17:52 2005 +1000
@@ -39,15 +39,16 @@
 #include "memory.h"
 #include "getlistaddr.h"
 #include "mlmmj.h"
+#include "getlistdelim.h"
 
-char *substitute(const char *line, const char *listaddr, size_t datacount,
-		 char **data)
+char *substitute(const char *line, const char *listaddr, const char *listdelim,
+		 size_t datacount, char **data)
 {
 	char *s1, *s2;
 
-	s1 = substitute_one(line, listaddr, datacount, data);
+	s1 = substitute_one(line, listaddr, listdelim, datacount, data);
 	while(s1) {
-		s2 = substitute_one(s1, listaddr, datacount, data);
+		s2 = substitute_one(s1, listaddr, listdelim, datacount, data);
 		if(s2) {
 			myfree(s1);
 			s1 = s2;
@@ -58,8 +59,8 @@
 	return mystrdup(line);
 }
 
-char *substitute_one(const char *line, const char *listaddr, size_t datacount,
-		     char **data)
+char *substitute_one(const char *line, const char *listaddr,
+		     const char *listdelim, size_t datacount, char **data)
 {
 	char *fqdn, *listname, *d1, *d2, *token, *value = NULL;
 	char *retstr, *origline;
@@ -96,31 +97,35 @@
 		value = mystrdup(listaddr);
 		goto concatandreturn;
 	} else if(strcmp(token, "listowner") == 0) {
-		value = concatstr(3, listname, "+owner@", fqdn);
+		value = concatstr(4, listname, listdelim, "owner@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "helpaddr") == 0) {
-		value = concatstr(3, listname, "+help@", fqdn);
+		value = concatstr(4, listname, listdelim, "help@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "listgetN") == 0) {
-		value = concatstr(3, listname, "+get-N@", fqdn);
+		value = concatstr(4, listname, listdelim, "get-N@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "listunsubaddr") == 0) {
-		value = concatstr(3, listname, "+unsubscribe@", fqdn);
+		value = concatstr(4, listname, listdelim, "unsubscribe@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "digestunsubaddr") == 0) {
-		value = concatstr(3, listname, "+unsubscribe-digest@", fqdn);
+		value = concatstr(4, listname, listdelim,
+				  "unsubscribe-digest@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "nomailunsubaddr") == 0) {
-		value = concatstr(3, listname, "+unsubscribe-nomail@", fqdn);
+		value = concatstr(4, listname, listdelim,
+				  "unsubscribe-nomail@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "listsubaddr") == 0) {
-		value = concatstr(3, listname, "+subscribe@", fqdn);
+		value = concatstr(4, listname, listdelim, "subscribe@", fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "digestsubaddr") == 0) {
-		value = concatstr(3, listname, "+subscribe-digest@", fqdn);
+		value = concatstr(4, listname, listdelim, "subscribe-digest@",
+				  fqdn);
 		goto concatandreturn;
 	} else if(strcmp(token, "nomailsubaddr") == 0) {
-		value = concatstr(3, listname, "+subscribe-nomail@", fqdn);
+		value = concatstr(4, listname, listdelim, "subscribe-nomail@",
+				  fqdn);
 		goto concatandreturn;
 	}
 	if(data) {
@@ -151,7 +156,7 @@
 		   char **data)
 {
 	int infd, outfd;
-	char *listaddr, *myfrom, *tmp, *subject, *retstr = NULL;
+	char *listaddr, *listdelim, *myfrom, *tmp, *subject, *retstr = NULL;
 	char *myreplyto, *myto, *str = NULL, *mydate, *mymsgid;
 
 	tmp = concatstr(3, listdir, "/text/", filename);
@@ -163,6 +168,7 @@
 	}
 
 	listaddr = getlistaddr(listdir);
+	listdelim = getlistdelim(listdir);
 
 	tmp = mygetline(infd);
 	if(strncasecmp(tmp, "Subject:", 8) != 0) {
@@ -170,17 +176,19 @@
 				"standard subject");
 		subject = mystrdup("mlmmj administrativa\n");
 	} else
-		subject = substitute(tmp, listaddr, tokencount, data);
+		subject = substitute(tmp, listaddr, listdelim, tokencount,
+				     data);
 
 	myfree(tmp);
 	
-	myfrom = substitute(from, listaddr, tokencount, data);
-	myto = substitute(to, listaddr, tokencount, data);
+	myfrom = substitute(from, listaddr, listdelim, tokencount, data);
+	myto = substitute(to, listaddr, listdelim, tokencount, data);
 	mydate = gendatestr();
 	mymsgid = genmsgid();
 
 	if(replyto) {
-		myreplyto = substitute(replyto, listaddr, tokencount, data);
+		myreplyto = substitute(replyto, listaddr, listdelim,
+				       tokencount, data);
 		tmp = concatstr(3, "Reply-To: ", myreplyto, "\n");
 		myfree(myreplyto);
 		myreplyto = tmp;
@@ -200,6 +208,7 @@
 	if(outfd < 0) {
 		log_error(LOG_ARGS, "Could not open std mail %s", retstr);
 		myfree(str);
+		myfree(listdelim);
 		return NULL;
 	}
 
@@ -209,6 +218,7 @@
 	if(writen(outfd, str, strlen(str)) < 0) {
 		log_error(LOG_ARGS, "Could not write std mail");
 		myfree(str);
+		myfree(listdelim);
 		return NULL;
 	}
 
@@ -216,10 +226,11 @@
 
 	while((str = mygetline(infd))) {
 		tmp = str;
-		str = substitute(tmp, listaddr, tokencount, data);
+		str = substitute(tmp, listaddr, listdelim, tokencount, data);
 		myfree(tmp);
 		if(writen(outfd, str, strlen(str)) < 0) {
 			myfree(str);
+			myfree(listdelim);
 			log_error(LOG_ARGS, "Could not write std mail");
 			return NULL;
 		}
--- a/src/send_digest.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/send_digest.c	Mon Oct 10 00:17:52 2005 +1000
@@ -36,6 +36,7 @@
 #include "strgen.h"
 #include "memory.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "wrappers.h"
 
 
@@ -45,7 +46,7 @@
 	int i, fd, archivefd, status, hdrfd;
 	char buf[45];
 	char *tmp, *queuename = NULL, *archivename, *fromstr;
-	char *boundary, *listaddr, *listname, *listfqdn;
+	char *boundary, *listaddr, *listdelim, *listname, *listfqdn;
 	pid_t childpid, pid;
 
 	if (addr) {
@@ -90,7 +91,11 @@
 		snprintf(buf, sizeof(buf), " (%d-%d)", firstindex, lastindex);
 	}
 
-	fromstr = concatstr(5, "From: ", listname, "+help@", listfqdn, "\n");
+	listdelim = getlistdelim(listdir);
+	fromstr = concatstr(6, "From: ", listname, listdelim, "help@", listfqdn,
+			    "\n");
+	myfree(listdelim);
+
 	tmp = concatstr(6, "MIME-Version: 1.0"
 			    "\nContent-Type: multipart/" DIGESTMIMETYPE "; "
 			    "boundary=", boundary,
--- a/src/send_help.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/send_help.c	Mon Oct 10 00:17:52 2005 +1000
@@ -34,6 +34,7 @@
 #include "strgen.h"
 #include "find_email_adr.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "log_error.h"
 #include "chomp.h"
 #include "wrappers.h"
@@ -44,13 +45,16 @@
 void send_help(const char *listdir, const char *emailaddr,
 	       const char *mlmmjsend)
 {
-	char *queuefilename, *listaddr, *listname, *listfqdn, *fromaddr;
+	char *queuefilename, *listaddr, *listdelim, *listname, *listfqdn;
+	char *fromaddr;
 
 	listaddr = getlistaddr(listdir);
+	listdelim = getlistdelim(listdir);
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
+	myfree(listdelim);
 
 	queuefilename = prepstdreply(listdir, "listhelp", "$listowner$",
 					emailaddr, NULL, 0, NULL);
--- a/src/send_list.c	Mon Oct 10 00:00:35 2005 +1000
+++ b/src/send_list.c	Mon Oct 10 00:17:52 2005 +1000
@@ -34,6 +34,7 @@
 #include "send_list.h"
 #include "strgen.h"
 #include "getlistaddr.h"
+#include "getlistdelim.h"
 #include "log_error.h"
 #include "chomp.h"
 #include "wrappers.h"
@@ -44,18 +45,20 @@
 void send_list(const char *listdir, const char *emailaddr,
 	       const char *mlmmjsend)
 {
-	char *queuefilename, *listaddr, *listname, *listfqdn, *fromaddr;
-	char *subdir, *fileiter;
+	char *queuefilename, *listaddr, *listdelim, *listname, *listfqdn;
+	char *fromaddr, *subdir, *fileiter;
 	DIR *dirp;
 	struct dirent *dp;
 	int fd, subfd;
 
 	listaddr = getlistaddr(listdir);
+	listdelim = getlistdelim(listdir);
 	listname = genlistname(listaddr);
 	listfqdn = genlistfqdn(listaddr);
 	subdir = concatstr(2, listdir, "/subscribers.d/");
 
-	fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
+	fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
+	myfree(listdelim);
 
 	queuefilename = prepstdreply(listdir, "listsubs", "$listowner$",
 					emailaddr, NULL, 0, NULL);