comparison src/prepstdreply.c @ 741: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 4a8acfd3f95f
children b00eb39643c1
comparison
equal deleted inserted replaced
740:5db75af2d0db 741:b72bcb7e08a2
206 } 206 }
207 207
208 208
209 char *prepstdreply(const char *listdir, const char *filename, const char *from, 209 char *prepstdreply(const char *listdir, const char *filename, const char *from,
210 const char *to, const char *replyto, size_t tokencount, 210 const char *to, const char *replyto, size_t tokencount,
211 char **data, char *customheaders, const char *mailname) 211 char **data, const char *mailname)
212 { 212 {
213 size_t i, len;
213 int infd, outfd; 214 int infd, outfd;
214 char *listaddr, *listdelim, *myfrom, *tmp, *subject, *retstr = NULL; 215 char *listaddr, *listdelim, *tmp, *retstr = NULL;
215 char *listfqdn, *line, *utfline, *utfsub, *utfsub2; 216 char *listfqdn, *line, *utfline, *utfsub, *utfsub2;
216 char *myreplyto, *myto, *str = NULL, *mydate, *mymsgid; 217 char *str = NULL;
218 char *headers[10] = { NULL }; /* relies on NULL to flag end */
217 219
218 if ((infd = open_listtext(listdir, filename)) < 0) { 220 if ((infd = open_listtext(listdir, filename)) < 0) {
219 return NULL; 221 return NULL;
220 } 222 }
221 223
222 listaddr = getlistaddr(listdir); 224 listaddr = getlistaddr(listdir);
223 listdelim = getlistdelim(listdir); 225 listdelim = getlistdelim(listdir);
224 listfqdn = genlistfqdn(listaddr); 226 listfqdn = genlistfqdn(listaddr);
225
226 line = mygetline(infd);
227 if(!line || (strncasecmp(line, "Subject: ", 9) != 0)) {
228 log_error(LOG_ARGS, "No Subject in '%s' listtext. Using "
229 "standard subject", filename);
230 subject = mystrdup("mlmmj administrativa");
231 } else {
232 chomp(line);
233 utfsub = unistr_escaped_to_utf8(line + 9);
234 utfsub2 = substitute(utfsub, listaddr, listdelim, tokencount,
235 data, NULL);
236 subject = unistr_utf8_to_header(utfsub2);
237 myfree(utfsub);
238 myfree(utfsub2);
239 myfree(line);
240
241 /* skip empty line after subject */
242 line = mygetline(infd);
243 if (line && (line[0] == '\n')) {
244 myfree(line);
245 line = NULL;
246 }
247 }
248 if (line) {
249 utfline = unistr_escaped_to_utf8(line);
250 myfree(line);
251 } else {
252 utfline = NULL;
253 }
254
255 myfrom = substitute(from, listaddr, listdelim, tokencount, data, NULL);
256 myto = substitute(to, listaddr, listdelim, tokencount, data, NULL);
257 mydate = gendatestr();
258 mymsgid = genmsgid(listfqdn);
259
260 if(replyto) {
261 myreplyto = substitute(replyto, listaddr, listdelim,
262 tokencount, data, NULL);
263 tmp = concatstr(3, "Reply-To: ", myreplyto, "\n");
264 myfree(myreplyto);
265 myreplyto = tmp;
266 } else
267 myreplyto = NULL;
268 227
269 do { 228 do {
270 tmp = random_str(); 229 tmp = random_str();
271 myfree(retstr); 230 myfree(retstr);
272 retstr = concatstr(3, listdir, "/queue/", tmp); 231 retstr = concatstr(3, listdir, "/queue/", tmp);
276 235
277 } while ((outfd < 0) && (errno == EEXIST)); 236 } while ((outfd < 0) && (errno == EEXIST));
278 237
279 if(outfd < 0) { 238 if(outfd < 0) {
280 log_error(LOG_ARGS, "Could not open std mail %s", retstr); 239 log_error(LOG_ARGS, "Could not open std mail %s", retstr);
281 myfree(str);
282 myfree(listaddr); 240 myfree(listaddr);
283 myfree(listdelim); 241 myfree(listdelim);
284 myfree(listfqdn); 242 myfree(listfqdn);
285 myfree(utfline); 243 return NULL;
286 return NULL; 244 }
287 } 245
288 246 tmp = substitute(from, listaddr, listdelim,
289 str = concatstr(14, 247 tokencount, data, NULL);
290 "From: ", myfrom, 248 headers[0] = concatstr(2, "From: ", tmp);
291 "\nTo: ", myto, 249 myfree(tmp);
292 "\n", myreplyto, 250 tmp = substitute(to, listaddr, listdelim,
293 mymsgid, 251 tokencount, data, NULL);
294 mydate, 252 headers[1] = concatstr(2, "To: ", tmp);
295 "Subject: ", subject, 253 myfree(tmp);
296 "\nMIME-Version: 1.0" 254 headers[2] = genmsgid(listfqdn);
297 "\nContent-Type: text/plain; charset=utf-8" 255 chomp(headers[2]);
298 "\nContent-Encoding: 8bit" 256 headers[3] = gendatestr();
299 "\n", customheaders, 257 chomp(headers[3]);
300 "\n", utfline); 258 headers[4] = mystrdup("Subject: mlmmj administrivia");
301 259 headers[5] = mystrdup("MIME-Version: 1.0");
302 myfree(utfline); 260 headers[6] = mystrdup("Content-Type: text/plain; charset=utf-8");
303 261 headers[7] = mystrdup("Content-Transfer-Encoding: 8bit");
304 if(writen(outfd, str, strlen(str)) < 0) { 262
263 if(replyto) {
264 tmp = substitute(replyto, listaddr, listdelim,
265 tokencount, data, NULL);
266 headers[8] = concatstr(2, "Reply-To: ", tmp);
267 myfree(tmp);
268 }
269
270 for(;;) {
271 line = mygetline(infd);
272 if (!line) {
273 log_error(LOG_ARGS, "No body in '%s' listtext",
274 filename);
275 break;
276 }
277 if (*line == '\n') {
278 /* end of headers */
279 myfree(line);
280 line = NULL;
281 break;
282 }
283 chomp(line);
284 if (*line == ' ' || *line == '\t') {
285 /* line beginning with linear whitespace is a
286 continuation of previous header line */
287 utfsub = unistr_escaped_to_utf8(line);
288 str = substitute(utfsub, listaddr, listdelim,
289 tokencount, data, NULL);
290 myfree(utfsub);
291 len = strlen(str);
292 str[len] = '\n';
293 if(writen(outfd, str, len+1) < 0) {
294 log_error(LOG_ARGS, "Could not write std mail");
295 myfree(str);
296 myfree(line);
297 myfree(listaddr);
298 myfree(listdelim);
299 myfree(listfqdn);
300 return NULL;
301 }
302 myfree(str);
303 } else {
304 tmp = line;
305 len = 0;
306 while (*tmp && *tmp != ':') {
307 tmp++;
308 len++;
309 }
310 if (!*tmp) {
311 log_error(LOG_ARGS, "No headers or invalid "
312 "header in '%s' listtext",
313 filename);
314 break;
315 }
316 tmp++;
317 len++;
318 /* remove the standard header if one matches */
319 for (i=0; headers[i] != NULL; i++) {
320 if (strncasecmp(line, headers[i], len) == 0) {
321 myfree(headers[i]);
322 while (headers[i] != NULL) {
323 headers[i] = headers[i+1];
324 i++;
325 }
326 break;
327 }
328 }
329 utfsub = unistr_escaped_to_utf8(tmp);
330 *tmp = '\0';
331 utfsub2 = substitute(utfsub, listaddr, listdelim,
332 tokencount, data, NULL);
333 myfree(utfsub);
334 if (strncasecmp(line, "Subject:", len) == 0) {
335 tmp = unistr_utf8_to_header(utfsub2);
336 myfree(utfsub2);
337 str = concatstr(2, line, tmp);
338 myfree(tmp);
339 } else {
340 str = concatstr(2, line, utfsub2);
341 myfree(utfsub2);
342 }
343 len = strlen(str);
344 str[len] = '\n';
345 if(writen(outfd, str, len+1) < 0) {
346 log_error(LOG_ARGS, "Could not write std mail");
347 myfree(str);
348 myfree(line);
349 myfree(listaddr);
350 myfree(listdelim);
351 myfree(listfqdn);
352 return NULL;
353 }
354 myfree(str);
355 }
356 myfree(line);
357 }
358
359 for (i=0; headers[i] != NULL; i++) {
360 len = strlen(headers[i]);
361 headers[i][len] = '\n';
362 if(writen(outfd, headers[i], len+1) < 0) {
363 log_error(LOG_ARGS, "Could not write std mail");
364 if (line)
365 myfree(line);
366 myfree(str);
367 myfree(listaddr);
368 myfree(listdelim);
369 myfree(listfqdn);
370 return NULL;
371 }
372 }
373
374 /* end the headers */
375 if(writen(outfd, "\n", 1) < 0) {
305 log_error(LOG_ARGS, "Could not write std mail"); 376 log_error(LOG_ARGS, "Could not write std mail");
306 myfree(str); 377 myfree(str);
378 if (line)
379 myfree(line);
307 myfree(listaddr); 380 myfree(listaddr);
308 myfree(listdelim); 381 myfree(listdelim);
309 myfree(listfqdn); 382 myfree(listfqdn);
310 return NULL; 383 return NULL;
311 } 384 }
312 385
313 myfree(str); 386 if (line) {
314 387 str = concatstr(2, line, "\n");
315 while((str = mygetline(infd))) { 388 myfree(line);
316 tmp = str; 389 } else {
390 str = mygetline(infd);
391 }
392 while(str) {
317 utfline = unistr_escaped_to_utf8(str); 393 utfline = unistr_escaped_to_utf8(str);
318 myfree(tmp); 394 myfree(str);
319 395
320 tmp = utfline;
321 str = substitute(utfline, listaddr, listdelim, tokencount, data, mailname); 396 str = substitute(utfline, listaddr, listdelim, tokencount, data, mailname);
322 myfree(tmp); 397 myfree(utfline);
323 398
324 if(writen(outfd, str, strlen(str)) < 0) { 399 if(writen(outfd, str, strlen(str)) < 0) {
325 myfree(str); 400 myfree(str);
326 myfree(listaddr); 401 myfree(listaddr);
327 myfree(listdelim); 402 myfree(listdelim);
328 myfree(listfqdn); 403 myfree(listfqdn);
329 log_error(LOG_ARGS, "Could not write std mail"); 404 log_error(LOG_ARGS, "Could not write std mail");
330 return NULL; 405 return NULL;
331 } 406 }
332 myfree(str); 407 myfree(str);
333 } 408 str = mygetline(infd);
334 409 }
410
335 fsync(outfd); 411 fsync(outfd);
336 close(outfd); 412 close(outfd);
337 413
338 myfree(listaddr); 414 myfree(listaddr);
339 myfree(listdelim); 415 myfree(listdelim);