mlmmj

changeset b72bcb7e08a2

Arbitrary headers in listtexts, fix default Content-Transfer-Encoding: header, and document \uNNNN substitution Also, the interface to prepstdreply() has changed; there is no longer a customheaders argument, which was never used anyway, and is now essentially redundant due to this patch.
author Ben Schmidt
date Mon, 20 Sep 2010 01:44:58 +1000
parents 5db75af2d0db
children b00eb39643c1
files ChangeLog README.listtexts include/prepstdreply.h src/mlmmj-bounce.c src/mlmmj-process.c src/mlmmj-sub.c src/mlmmj-unsub.c src/prepstdreply.c src/send_help.c src/send_list.c
diffstat 10 files changed, 207 insertions(+), 107 deletions(-) [+]
line diff
     1.1 --- a/ChangeLog	Mon Sep 20 01:41:32 2010 +1000
     1.2 +++ b/ChangeLog	Mon Sep 20 01:44:58 2010 +1000
     1.3 @@ -1,5 +1,6 @@
     1.4 + o Allow arbitrary headers in list texts
     1.5   o Ensure digest listtext is always closed
     1.6 - o Fix Content-Transfer-Encoding: header for digests
     1.7 + o Fix Content-Transfer-Encoding: header for digests and list texts
     1.8   o Fixed a bug that could cause a crash if $posteraddr$ appeared in the
     1.9     maxmaiilsize listtext
    1.10   o Documented listtexts
     2.1 --- a/README.listtexts	Mon Sep 20 01:41:32 2010 +1000
     2.2 +++ b/README.listtexts	Mon Sep 20 01:44:58 2010 +1000
     2.3 @@ -106,22 +106,38 @@
     2.4  
     2.5  They have the following format:
     2.6  
     2.7 -- Subject line
     2.8 +- Headers
     2.9  - Blank line
    2.10  - Body
    2.11  
    2.12  They are expected to be in UTF-8 encoding and have Unix line endings.
    2.13  
    2.14 -The subject line is the text 'Subject: ' (Mlmmj expects the space, even though
    2.15 -this is not ordinarily required in mail messages) followed by the subject line
    2.16 -to be used for the mail. The subject line may include UTF-8 characters, which
    2.17 -will automatically be escaped using the =?utf-8?q?...?= quoting mechanism.
    2.18 +The headers should be formatted as they should appear in the mail message. They
    2.19 +will begin the mail message. Header continuation via lines beginning with
    2.20 +linear whitespace is supported.
    2.21 +
    2.22 +Following the headers found in the list text, Mlmmj will output the following
    2.23 +default headers, unless the same header is already provided in the list text.
    2.24 +
    2.25 +- From:
    2.26 +- To:
    2.27 +- Message-ID:
    2.28 +- Date:
    2.29 +- Subject: mlmmj administrivia
    2.30 +- MIME-Version: 1.0
    2.31 +- Content-Type: text/plain; charset=utf-8
    2.32 +- Content-Transfer-Encoding: 8bit
    2.33 +
    2.34 +The Subject: header is treated specially: it may include UTF-8 characters,
    2.35 +which will automatically be escaped using the =?utf-8?q?...?= quoting
    2.36 +mechanism.
    2.37  
    2.38  List text substitutions
    2.39  -----------------------
    2.40  
    2.41 -Both subject and body may include the following, which are substituted prior to
    2.42 -sending the message:
    2.43 +Both headers and body may include the following, which are substituted prior to
    2.44 +sending the message (though note that some of these substitutions are
    2.45 +multi-line substitutions and would not work in a header):
    2.46  
    2.47  - $bouncenumbers$
    2.48    (available only in bounceprobe)
    2.49 @@ -222,5 +238,12 @@
    2.50    (available only in submod-moderator and [un]sub-confirm[-digest|-nomail])
    2.51    the address requested to be (un-)subscribed
    2.52  
    2.53 +- \uNNNN
    2.54 +  (NNNN are hex digits)
    2.55 +  a Unicode character
    2.56 +  (this is not really appropriate for use in a header, except perhaps the
    2.57 +  Subject: header as Mlmmj does automatic quoting for that header as described
    2.58 +  above)
    2.59  
    2.60  
    2.61 +
     3.1 --- a/include/prepstdreply.h	Mon Sep 20 01:41:32 2010 +1000
     3.2 +++ b/include/prepstdreply.h	Mon Sep 20 01:44:58 2010 +1000
     3.3 @@ -32,6 +32,6 @@
     3.4  int open_listtext(const char *listdir, const char *filename);
     3.5  char *prepstdreply(const char *listdir, const char *filename, const char *from,
     3.6  		const char *to, const char *replyto, size_t tokencount,
     3.7 -		char **data, char *customheaders, const char *mailname);
     3.8 +		char **data, const char *mailname);
     3.9  
    3.10  #endif /* PREPSTDREPLY_H */
     4.1 --- a/src/mlmmj-bounce.c	Mon Sep 20 01:41:32 2010 +1000
     4.2 +++ b/src/mlmmj-bounce.c	Mon Sep 20 01:44:58 2010 +1000
     4.3 @@ -146,7 +146,7 @@
     4.4  
     4.5  	maildata[1] = indexstr;
     4.6  	queuefilename = prepstdreply(listdir, "bounce-probe", "$listowner$",
     4.7 -					myaddr, NULL, 1, maildata, NULL, NULL);
     4.8 +					myaddr, NULL, 1, maildata, NULL);
     4.9  	MY_ASSERT(queuefilename);
    4.10  	myfree(indexstr);
    4.11  
     5.1 --- a/src/mlmmj-process.c	Mon Sep 20 01:41:32 2010 +1000
     5.2 +++ b/src/mlmmj-process.c	Mon Sep 20 01:44:58 2010 +1000
     5.3 @@ -133,7 +133,7 @@
     5.4  	myfree(listfqdn);
     5.5  
     5.6  	queuefilename = prepstdreply(listdir, "moderation", "$listowner$",
     5.7 -				     to, replyto, 2, maildata, NULL,
     5.8 +				     to, replyto, 2, maildata,
     5.9  				     mailfilename);
    5.10  
    5.11  	/* we might need to exec more than one mlmmj-send */
    5.12 @@ -176,7 +176,7 @@
    5.13  
    5.14  	queuefilename = prepstdreply(listdir, "moderation-poster",
    5.15  				     "$listowner$", efromsender,
    5.16 -				     NULL, 1, maildata+2, NULL, mailfilename);
    5.17 +				     NULL, 1, maildata+2, mailfilename);
    5.18  
    5.19  	execlp(mlmmjsend, mlmmjsend,
    5.20  			"-l", "1",
    5.21 @@ -696,7 +696,7 @@
    5.22  			queuefilename = prepstdreply(listdir,
    5.23  					"maxmailsize", "$listowner$",
    5.24  					fromemails.emaillist[0],
    5.25 -					NULL, 1, maildata+2, NULL, donemailname);
    5.26 +					NULL, 1, maildata+2, donemailname);
    5.27  			MY_ASSERT(queuefilename)
    5.28  			myfree(listdelim);
    5.29  			myfree(listname);
    5.30 @@ -811,7 +811,7 @@
    5.31  				     listfqdn);
    5.32  		queuefilename = prepstdreply(listdir, "notintocc",
    5.33  					"$listowner$", fromemails.emaillist[0],
    5.34 -					     NULL, 0, NULL, NULL, donemailname);
    5.35 +					     NULL, 0, NULL, donemailname);
    5.36  		MY_ASSERT(queuefilename)
    5.37  		myfree(listdelim);
    5.38  		myfree(listname);
    5.39 @@ -872,7 +872,7 @@
    5.40  					"bounces-help@", listfqdn);
    5.41  			queuefilename = prepstdreply(listdir, "subonlypost",
    5.42  					"$listowner$", fromemails.emaillist[0],
    5.43 -						     NULL, 1, maildata, NULL, donemailname);
    5.44 +						     NULL, 1, maildata, donemailname);
    5.45  			MY_ASSERT(queuefilename)
    5.46  			myfree(listaddr);
    5.47  			myfree(listdelim);
    5.48 @@ -927,7 +927,7 @@
    5.49  			queuefilename = prepstdreply(listdir, "access",
    5.50  							"$listowner$",
    5.51  							fromemails.emaillist[0],
    5.52 -						     NULL, 0, NULL, NULL, donemailname);
    5.53 +						     NULL, 0, NULL, donemailname);
    5.54  			MY_ASSERT(queuefilename)
    5.55  			myfree(listaddr);
    5.56  			myfree(listdelim);
     6.1 --- a/src/mlmmj-sub.c	Mon Sep 20 01:41:32 2010 +1000
     6.2 +++ b/src/mlmmj-sub.c	Mon Sep 20 01:44:58 2010 +1000
     6.3 @@ -147,7 +147,7 @@
     6.4  	maildata[5] = moderators;
     6.5  
     6.6  	queuefilename = prepstdreply(listdir, "submod-moderator",
     6.7 -				"$listowner$", to, replyto, 3, maildata, NULL, NULL);
     6.8 +				"$listowner$", to, replyto, 3, maildata, NULL);
     6.9  	
    6.10  	myfree(maildata[1]);
    6.11  	
    6.12 @@ -189,7 +189,7 @@
    6.13  
    6.14  	from = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
    6.15  	queuefilename = prepstdreply(listdir, "submod-requester", "$listowner$",
    6.16 -					subaddr, NULL, 0, NULL, NULL, NULL);
    6.17 +					subaddr, NULL, 0, NULL, NULL);
    6.18  	
    6.19  	myfree(listname);
    6.20  	myfree(listfqdn);
    6.21 @@ -282,7 +282,7 @@
    6.22  	}
    6.23  
    6.24  	queuefilename = prepstdreply(listdir, listtext, "$helpaddr$",
    6.25 -				     subaddr, NULL, 0, NULL, NULL, NULL);
    6.26 +				     subaddr, NULL, 0, NULL, NULL);
    6.27  	MY_ASSERT(queuefilename);
    6.28  	myfree(listtext);
    6.29  
    6.30 @@ -329,7 +329,7 @@
    6.31  	}
    6.32  
    6.33  	queuefilename = prepstdreply(listdir, listtext, "$listowner$",
    6.34 -				"$listowner$", NULL, 1, maildata, NULL, NULL);
    6.35 +				"$listowner$", NULL, 1, maildata, NULL);
    6.36  	MY_ASSERT(queuefilename)
    6.37  	myfree(listtext);
    6.38  	myfree(maildata[1]);
    6.39 @@ -416,7 +416,7 @@
    6.40  	maildata[3] = mystrdup(confirmaddr);
    6.41  
    6.42  	queuefilename = prepstdreply(listdir, listtext, "$helpaddr$", subaddr,
    6.43 -				     confirmaddr, 2, maildata, NULL, NULL);
    6.44 +				     confirmaddr, 2, maildata, NULL);
    6.45  
    6.46  	myfree(maildata[1]);
    6.47  	myfree(maildata[3]);
    6.48 @@ -469,7 +469,7 @@
    6.49  	myfree(listdelim);
    6.50  
    6.51  	queuefilename = prepstdreply(listdir, "sub-subscribed", "$helpaddr$",
    6.52 -				     subaddr, NULL, 0, NULL, NULL, NULL);
    6.53 +				     subaddr, NULL, 0, NULL, NULL);
    6.54  	MY_ASSERT(queuefilename);
    6.55  
    6.56  	myfree(listaddr);
     7.1 --- a/src/mlmmj-unsub.c	Mon Sep 20 01:41:32 2010 +1000
     7.2 +++ b/src/mlmmj-unsub.c	Mon Sep 20 01:44:58 2010 +1000
     7.3 @@ -76,7 +76,7 @@
     7.4  	}
     7.5  
     7.6  	queuefilename = prepstdreply(listdir, listtext, "$helpaddr$",
     7.7 -				     subaddr, NULL, 0, NULL, NULL, NULL);
     7.8 +				     subaddr, NULL, 0, NULL, NULL);
     7.9  	MY_ASSERT(queuefilename);
    7.10  	myfree(listtext);
    7.11  
    7.12 @@ -124,7 +124,7 @@
    7.13  	}
    7.14  	
    7.15  	queuefilename = prepstdreply(listdir, listtext, "$listowner$",
    7.16 -				     "$listowner$", NULL, 1, maildata, NULL, NULL);
    7.17 +				     "$listowner$", NULL, 1, maildata, NULL);
    7.18  	MY_ASSERT(queuefilename);
    7.19  	myfree(listtext);
    7.20  	myfree(maildata[1]);
    7.21 @@ -213,7 +213,7 @@
    7.22  	maildata[3] = mystrdup(confirmaddr);
    7.23  
    7.24  	queuefilename = prepstdreply(listdir, listtext, "$helpaddr$", subaddr,
    7.25 -				     confirmaddr, 2, maildata, NULL, NULL);
    7.26 +				     confirmaddr, 2, maildata, NULL);
    7.27  
    7.28  	myfree(maildata[1]);
    7.29  	myfree(maildata[3]);
    7.30 @@ -305,7 +305,7 @@
    7.31  	myfree(listdelim);
    7.32  
    7.33  	queuefilename = prepstdreply(listdir, "unsub-notsubscribed",
    7.34 -				     "$helpaddr$", subaddr, NULL, 0, NULL, NULL, NULL);
    7.35 +				     "$helpaddr$", subaddr, NULL, 0, NULL, NULL);
    7.36  	MY_ASSERT(queuefilename);
    7.37  
    7.38  	myfree(listaddr);
     8.1 --- a/src/prepstdreply.c	Mon Sep 20 01:41:32 2010 +1000
     8.2 +++ b/src/prepstdreply.c	Mon Sep 20 01:44:58 2010 +1000
     8.3 @@ -208,12 +208,14 @@
     8.4  
     8.5  char *prepstdreply(const char *listdir, const char *filename, const char *from,
     8.6  		   const char *to, const char *replyto, size_t tokencount,
     8.7 -		   char **data, char *customheaders, const char *mailname)
     8.8 +		   char **data, const char *mailname)
     8.9  {
    8.10 +	size_t i, len;
    8.11  	int infd, outfd;
    8.12 -	char *listaddr, *listdelim, *myfrom, *tmp, *subject, *retstr = NULL;
    8.13 +	char *listaddr, *listdelim, *tmp, *retstr = NULL;
    8.14  	char *listfqdn, *line, *utfline, *utfsub, *utfsub2;
    8.15 -	char *myreplyto, *myto, *str = NULL, *mydate, *mymsgid;
    8.16 +	char *str = NULL;
    8.17 +	char *headers[10] = { NULL }; /* relies on NULL to flag end */
    8.18  
    8.19  	if ((infd = open_listtext(listdir, filename)) < 0) {
    8.20  		return NULL;
    8.21 @@ -223,49 +225,6 @@
    8.22  	listdelim = getlistdelim(listdir);
    8.23  	listfqdn = genlistfqdn(listaddr);
    8.24  
    8.25 -	line = mygetline(infd);
    8.26 -	if(!line || (strncasecmp(line, "Subject: ", 9) != 0)) {
    8.27 -		log_error(LOG_ARGS, "No Subject in '%s' listtext. Using "
    8.28 -				"standard subject", filename);
    8.29 -		subject = mystrdup("mlmmj administrativa");
    8.30 -	} else {
    8.31 -		chomp(line);
    8.32 -		utfsub = unistr_escaped_to_utf8(line + 9);
    8.33 -		utfsub2 = substitute(utfsub, listaddr, listdelim, tokencount,
    8.34 -				     data, NULL);
    8.35 -		subject = unistr_utf8_to_header(utfsub2);
    8.36 -		myfree(utfsub);
    8.37 -		myfree(utfsub2);
    8.38 -		myfree(line);
    8.39 -
    8.40 -		/* skip empty line after subject */
    8.41 -		line = mygetline(infd);
    8.42 -		if (line && (line[0] == '\n')) {
    8.43 -			myfree(line);
    8.44 -			line = NULL;
    8.45 -		}
    8.46 -	}
    8.47 -	if (line) {
    8.48 -		utfline = unistr_escaped_to_utf8(line);
    8.49 -		myfree(line);
    8.50 -	} else {
    8.51 -		utfline = NULL;
    8.52 -	}
    8.53 -	
    8.54 -	myfrom = substitute(from, listaddr, listdelim, tokencount, data, NULL);
    8.55 -	myto = substitute(to, listaddr, listdelim, tokencount, data, NULL);
    8.56 -	mydate = gendatestr();
    8.57 -	mymsgid = genmsgid(listfqdn);
    8.58 -
    8.59 -	if(replyto) {
    8.60 -		myreplyto = substitute(replyto, listaddr, listdelim,
    8.61 -				       tokencount, data, NULL);
    8.62 -		tmp = concatstr(3, "Reply-To: ", myreplyto, "\n");
    8.63 -		myfree(myreplyto);
    8.64 -		myreplyto = tmp;
    8.65 -	} else
    8.66 -		myreplyto = NULL;
    8.67 -
    8.68  	do {
    8.69  		tmp = random_str();
    8.70  		myfree(retstr);
    8.71 @@ -278,48 +237,164 @@
    8.72  	
    8.73  	if(outfd < 0) {
    8.74  		log_error(LOG_ARGS, "Could not open std mail %s", retstr);
    8.75 -		myfree(str);
    8.76  		myfree(listaddr);
    8.77  		myfree(listdelim);
    8.78  		myfree(listfqdn);
    8.79 -		myfree(utfline);
    8.80  		return NULL;
    8.81  	}
    8.82  
    8.83 -	str = concatstr(14,
    8.84 -			"From: ", myfrom,
    8.85 -			"\nTo: ", myto,
    8.86 -			"\n", myreplyto,
    8.87 -			mymsgid,
    8.88 -			mydate,
    8.89 -			"Subject: ", subject,
    8.90 -			"\nMIME-Version: 1.0"
    8.91 -			"\nContent-Type: text/plain; charset=utf-8"
    8.92 -			"\nContent-Encoding: 8bit"
    8.93 -			"\n", customheaders,
    8.94 -			"\n", utfline);
    8.95 +	tmp = substitute(from, listaddr, listdelim,
    8.96 +	                 tokencount, data, NULL);
    8.97 +	headers[0] = concatstr(2, "From: ", tmp);
    8.98 +	myfree(tmp);
    8.99 +	tmp = substitute(to, listaddr, listdelim,
   8.100 +	                 tokencount, data, NULL);
   8.101 +	headers[1] = concatstr(2, "To: ", tmp);
   8.102 +	myfree(tmp);
   8.103 +	headers[2] = genmsgid(listfqdn);
   8.104 +	chomp(headers[2]);
   8.105 +	headers[3] = gendatestr();
   8.106 +	chomp(headers[3]);
   8.107 +	headers[4] = mystrdup("Subject: mlmmj administrivia");
   8.108 +	headers[5] = mystrdup("MIME-Version: 1.0");
   8.109 +	headers[6] = mystrdup("Content-Type: text/plain; charset=utf-8");
   8.110 +	headers[7] = mystrdup("Content-Transfer-Encoding: 8bit");
   8.111  
   8.112 -	myfree(utfline);
   8.113 +	if(replyto) {
   8.114 +		tmp = substitute(replyto, listaddr, listdelim,
   8.115 +		                 tokencount, data, NULL);
   8.116 +		headers[8] = concatstr(2, "Reply-To: ", tmp);
   8.117 +		myfree(tmp);
   8.118 +	}
   8.119  
   8.120 -	if(writen(outfd, str, strlen(str)) < 0) {
   8.121 +	for(;;) {
   8.122 +		line = mygetline(infd);
   8.123 +		if (!line) {
   8.124 +			log_error(LOG_ARGS, "No body in '%s' listtext",
   8.125 +					filename);
   8.126 +			break;
   8.127 +		}
   8.128 +		if (*line == '\n') {
   8.129 +			/* end of headers */
   8.130 +			myfree(line);
   8.131 +			line = NULL;
   8.132 +			break;
   8.133 +		}
   8.134 +		chomp(line);
   8.135 +		if (*line == ' ' || *line == '\t') {
   8.136 +			/* line beginning with linear whitespace is a
   8.137 +			   continuation of previous header line */
   8.138 +			utfsub = unistr_escaped_to_utf8(line);
   8.139 +			str = substitute(utfsub, listaddr, listdelim,
   8.140 +			                 tokencount, data, NULL);
   8.141 +			myfree(utfsub);
   8.142 +			len = strlen(str);
   8.143 +			str[len] = '\n';
   8.144 +			if(writen(outfd, str, len+1) < 0) {
   8.145  		log_error(LOG_ARGS, "Could not write std mail");
   8.146  		myfree(str);
   8.147 +				myfree(line);
   8.148 +				myfree(listaddr);
   8.149 +				myfree(listdelim);
   8.150 +				myfree(listfqdn);
   8.151 +				return NULL;
   8.152 +			}
   8.153 +			myfree(str);
   8.154 +		} else {
   8.155 +			tmp = line;
   8.156 +			len = 0;
   8.157 +			while (*tmp && *tmp != ':') {
   8.158 +				tmp++;
   8.159 +				len++;
   8.160 +			}
   8.161 +			if (!*tmp) {
   8.162 +				log_error(LOG_ARGS, "No headers or invalid "
   8.163 +						"header in '%s' listtext",
   8.164 +						filename);
   8.165 +				break;
   8.166 +			}
   8.167 +			tmp++;
   8.168 +			len++;
   8.169 +			/* remove the standard header if one matches */
   8.170 +			for (i=0; headers[i] != NULL; i++) {
   8.171 +				if (strncasecmp(line, headers[i], len) == 0) {
   8.172 +					myfree(headers[i]);
   8.173 +					while (headers[i] != NULL) {
   8.174 +						headers[i] = headers[i+1];
   8.175 +						i++;
   8.176 +					}
   8.177 +					break;
   8.178 +				}
   8.179 +			}
   8.180 +			utfsub = unistr_escaped_to_utf8(tmp);
   8.181 +			*tmp = '\0';
   8.182 +			utfsub2 = substitute(utfsub, listaddr, listdelim,
   8.183 +			                     tokencount, data, NULL);
   8.184 +			myfree(utfsub);
   8.185 +			if (strncasecmp(line, "Subject:", len) == 0) {
   8.186 +				tmp = unistr_utf8_to_header(utfsub2);
   8.187 +				myfree(utfsub2);
   8.188 +				str = concatstr(2, line, tmp);
   8.189 +				myfree(tmp);
   8.190 +			} else {
   8.191 +				str = concatstr(2, line, utfsub2);
   8.192 +				myfree(utfsub2);
   8.193 +			}
   8.194 +			len = strlen(str);
   8.195 +			str[len] = '\n';
   8.196 +			if(writen(outfd, str, len+1) < 0) {
   8.197 +				log_error(LOG_ARGS, "Could not write std mail");
   8.198 +				myfree(str);
   8.199 +				myfree(line);
   8.200 +				myfree(listaddr);
   8.201 +				myfree(listdelim);
   8.202 +				myfree(listfqdn);
   8.203 +				return NULL;
   8.204 +			}
   8.205 +			myfree(str);
   8.206 +		}
   8.207 +		myfree(line);
   8.208 +	}
   8.209 +
   8.210 +	for (i=0; headers[i] != NULL; i++) {
   8.211 +		len = strlen(headers[i]);
   8.212 +		headers[i][len] = '\n';
   8.213 +		if(writen(outfd, headers[i], len+1) < 0) {
   8.214 +			log_error(LOG_ARGS, "Could not write std mail");
   8.215 +			if (line)
   8.216 +				myfree(line);
   8.217 +			myfree(str);
   8.218  		myfree(listaddr);
   8.219  		myfree(listdelim);
   8.220  		myfree(listfqdn);
   8.221  		return NULL;
   8.222  	}
   8.223 +	}
   8.224  
   8.225 +	/* end the headers */
   8.226 +	if(writen(outfd, "\n", 1) < 0) {
   8.227 +		log_error(LOG_ARGS, "Could not write std mail");
   8.228 +		myfree(str);
   8.229 +		if (line)
   8.230 +			myfree(line);
   8.231 +		myfree(listaddr);
   8.232 +		myfree(listdelim);
   8.233 +		myfree(listfqdn);
   8.234 +		return NULL;
   8.235 +	}
   8.236 +
   8.237 +	if (line) {
   8.238 +		str = concatstr(2, line, "\n");
   8.239 +		myfree(line);
   8.240 +	} else {
   8.241 +		str = mygetline(infd);
   8.242 +	}
   8.243 +	while(str) {
   8.244 +		utfline = unistr_escaped_to_utf8(str);
   8.245  	myfree(str);
   8.246  
   8.247 -	while((str = mygetline(infd))) {
   8.248 -		tmp = str;
   8.249 -		utfline = unistr_escaped_to_utf8(str);
   8.250 -		myfree(tmp);
   8.251 -
   8.252 -		tmp = utfline;
   8.253  		str = substitute(utfline, listaddr, listdelim, tokencount, data, mailname);
   8.254 -		myfree(tmp);
   8.255 +		myfree(utfline);
   8.256  
   8.257  		if(writen(outfd, str, strlen(str)) < 0) {
   8.258  			myfree(str);
   8.259 @@ -330,6 +405,7 @@
   8.260  			return NULL;
   8.261  		}
   8.262  		myfree(str);
   8.263 +		str = mygetline(infd);
   8.264  	}
   8.265  	
   8.266  	fsync(outfd);
     9.1 --- a/src/send_help.c	Mon Sep 20 01:41:32 2010 +1000
     9.2 +++ b/src/send_help.c	Mon Sep 20 01:44:58 2010 +1000
     9.3 @@ -57,7 +57,7 @@
     9.4  	myfree(listdelim);
     9.5  
     9.6  	queuefilename = prepstdreply(listdir, textfile, "$listowner$",
     9.7 -					emailaddr, NULL, 0, NULL, NULL, NULL);
     9.8 +					emailaddr, NULL, 0, NULL, NULL);
     9.9  	if(queuefilename == NULL) {
    9.10  		log_error(LOG_ARGS, "Could not prepare %s mail", name);
    9.11  		exit(EXIT_FAILURE);
    10.1 --- a/src/send_list.c	Mon Sep 20 01:41:32 2010 +1000
    10.2 +++ b/src/send_list.c	Mon Sep 20 01:44:58 2010 +1000
    10.3 @@ -99,7 +99,7 @@
    10.4  	myfree(listdelim);
    10.5  
    10.6  	queuefilename = prepstdreply(listdir, "listsubs", "$listowner$",
    10.7 -					emailaddr, NULL, 0, NULL, NULL, NULL);
    10.8 +					emailaddr, NULL, 0, NULL, NULL);
    10.9  	if(queuefilename == NULL) {
   10.10  		log_error(LOG_ARGS, "Could not prepare sub list mail");
   10.11  		exit(EXIT_FAILURE);