Mercurial > hg > mlmmj
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); |