Mercurial > hg > mlmmj
changeset 268:1dbadf407849
mlmmj-send now prepares headers and mail, and To: header feature added
author | mmj |
---|---|
date | Thu, 24 Jun 2004 21:56:06 +1000 |
parents | 55738fb09e46 |
children | facf047c93c5 |
files | ChangeLog TUNABLES include/mail-functions.h include/mlmmj-send.h include/mlmmj.h src/Makefile.am src/mail-functions.c src/mlmmj-send.c |
diffstat | 8 files changed, 229 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Tue Jun 22 19:08:47 2004 +1000 +++ b/ChangeLog Thu Jun 24 21:56:06 2004 +1000 @@ -1,3 +1,10 @@ +0.8.1 + o Add the option to add a To: header including the recipient emailaddress. + NOTE that this does not remove any existing To: headers, they should be + removed in control/delheaders + o Optimize mlmmj-send by preparing the mail in memory to reduce the amount of + write syscalls. control/memmailsize (size in bytes) controls how big it can + be. Default is 16k before it's send line by line. o Make sure we check if the Subject: prefix might be present in the de-quoted printable version of the Subject. If so, don't add it. o Fix bug with queuefilename not being correctly initialized when generating
--- a/TUNABLES Tue Jun 22 19:08:47 2004 +1000 +++ b/TUNABLES Thu Jun 24 21:56:06 2004 +1000 @@ -63,3 +63,16 @@ If this file exists, all headers of a post to the list is matched against the rules. The first rule to match wins. See README.access for syntax and examples. + + · memorymailsize (normal) + + Here is specified in bytes how big a mail can be and still be prepared for + sending in memory. It's greatly reducing the amount of write system calls to + prepare it in memory before sending it, but can also lead to denial of + service attacks. Default is 16k (16384 bytes). + + · addtohdr (boolean) + + When this file is present, a To: header including the recipients + emailaddress will be added to outgoing mail. Recommended usage is to remove + existing To: headers with delheaders (see above) first.
--- a/include/mail-functions.h Tue Jun 22 19:08:47 2004 +1000 +++ b/include/mail-functions.h Thu Jun 24 21:56:06 2004 +1000 @@ -32,7 +32,11 @@ int write_mail_from(int sockfd, const char *from_addr); int write_rcpt_to(int sockfd, const char *rcpt_addr); int write_custom_line(int sockfd, const char *line); -int write_mailbody_from_map(int sockfd, char *mailmap, size_t mailsize); +int write_mailbody_from_map(int sockfd, char *mailmap, size_t mailsize, + const char *tohdr); +char *get_preppedhdrs_from_map(char *mapstart, size_t *hdrslen); +char *get_prepped_mailbody_from_map(char *mapstart, size_t size, + size_t *bodylen); int write_replyto(int sockfd, const char *replyaddr); int write_dot(int sockfd); int write_quit(int sockfd);
--- a/include/mlmmj-send.h Tue Jun 22 19:08:47 2004 +1000 +++ b/include/mlmmj-send.h Thu Jun 24 21:56:06 2004 +1000 @@ -26,11 +26,15 @@ int send_mail(int sockfd, const char *from, const char *to, const char *replyto, char *mailmap, size_t mailsize, - const char *listdir, const char *mlmmjbounce); + const char *listdir, const char *mlmmjbounce, + const char *hdrs, size_t hdrslen, const char *body, + size_t bodylen); int send_mail_many(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 *listdir, const char *mlmmjbounce, + const char *hdrs, size_t hdrslen, const char *body, + size_t bodylen); int initsmtp(int *sockfd, const char *relayhost); int endsmtp(int *sockfd);
--- a/include/mlmmj.h Tue Jun 22 19:08:47 2004 +1000 +++ b/include/mlmmj.h Thu Jun 24 21:56:06 2004 +1000 @@ -42,6 +42,9 @@ mlmmj-maintd runs daemonized? 7200s is 2 hours */ #define MAINTD_LOGFILE "mlmmj-maintd.lastrun.log" +#define MEMORYMAILSIZE 16384 /* How big can a mail be before we don't want to + it in memory? control/memorymailsize */ + struct strlist { int count; char **strs;
--- a/src/Makefile.am Tue Jun 22 19:08:47 2004 +1000 +++ b/src/Makefile.am Thu Jun 24 21:56:06 2004 +1000 @@ -15,7 +15,8 @@ mlmmj_send_SOURCES = mlmmj-send.c writen.c mail-functions.c itoa.c chomp.c \ incindexfile.c checkwait_smtpreply.c getlistaddr.c \ mylocking.c init_sockfd.c strgen.c random-int.c \ - print-version.c log_error.c mygetline.c memory.c + print-version.c log_error.c mygetline.c memory.c \ + statctrl.c ctrlvalue.c mlmmj_recieve_SOURCES = mlmmj-recieve.c writen.c random-int.c strgen.c \ print-version.c log_error.c dumpfd2fd.c memory.c
--- a/src/mail-functions.c Tue Jun 22 19:08:47 2004 +1000 +++ b/src/mail-functions.c Thu Jun 24 21:56:06 2004 +1000 @@ -116,11 +116,13 @@ } -int write_mailbody_from_map(int sockfd, char *mapstart, size_t size) +int write_mailbody_from_map(int sockfd, char *mapstart, size_t size, + const char *tohdr) { char *cur, *next; char newlinebuf[3]; size_t len; + int i = 1; for(next = cur = mapstart; next < mapstart + size; next++) { if(*next == '\n') { @@ -139,6 +141,14 @@ log_error(LOG_ARGS, "Could not write mail"); return -1; } + if(i && tohdr && *(next+1) == '\n') { /* add To: header */ + if(writen(sockfd, tohdr, strlen(tohdr)) < 0) { + log_error(LOG_ARGS, "Could not write" + " To: header"); + return -1; + } + i = 0; /* Make sure we don't write it again */ + } cur = next + 1; } } @@ -146,6 +156,85 @@ return 0; } +char *get_preppedhdrs_from_map(char *mapstart, size_t *hlen) +{ + char *cur, *next, *endhdrs, *retstr, *r; + const char newlinebuf[] = "\r\n"; + size_t hdrlen, n = 0; + + endhdrs = strstr(mapstart, "\n\n"); + if(endhdrs == NULL) + return NULL; /* The map doesn't map a file with a mail */ + + hdrlen = endhdrs - mapstart + 1; + + for(next = cur = mapstart; next < mapstart + hdrlen; next++) + if(*next == '\n') + n++; + + retstr = mymalloc(hdrlen + n); + *hlen = hdrlen + n; + r = retstr; + + for(next = cur = mapstart; next < mapstart + hdrlen; next++) { + if(*next == '\n') { + strncpy(r, cur, next - cur); + r += next - cur; + strncpy(r, newlinebuf, 2); + r += 2; + cur = next + 1; + } + } + + return retstr; +} + +char *get_prepped_mailbody_from_map(char *mapstart, size_t size, size_t *blen) +{ + char *cur, *next, *endhdrs, *retstr, *r; + char newlinebuf[3]; + size_t bodylen, len, n = 0; + + endhdrs = strstr(mapstart, "\n\n"); + if(endhdrs == NULL) + return NULL; /* The map doesn't map a file with a mail */ + + endhdrs++; /* Skip the first newline, it's in hdrs */ + + bodylen = size - (endhdrs - mapstart); + + for(next = cur = endhdrs; next < mapstart + size; next++) { + if(*next == '\n') { + n++; + if(*(next+1) == '.') + n++; + } + } + + retstr = mymalloc(bodylen + n); + *blen = bodylen + n; + r = retstr; + + for(next = cur = endhdrs; next < mapstart + size; next++) { + if(*next == '\n') { + strncpy(r, cur, next - cur); + r += next - cur; + newlinebuf[0] = '\r'; + newlinebuf[1] = '\n'; + len = 2; + if(*(next+1) == '.') { + newlinebuf[2] = '.'; + len = 3; + } + strncpy(r, newlinebuf, len); + r += len; + cur = next + 1; + } + } + + return retstr; +} + /* "\r\n" has length 2 */ #define EXTRA_CUSTOM_LEN 3
--- a/src/mlmmj-send.c Tue Jun 22 19:08:47 2004 +1000 +++ b/src/mlmmj-send.c Thu Jun 24 21:56:06 2004 +1000 @@ -36,6 +36,7 @@ #include <syslog.h> #include <stdarg.h> #include <sys/mman.h> +#include <limits.h> #include "mlmmj-send.h" #include "mlmmj.h" @@ -51,6 +52,11 @@ #include "mygetline.h" #include "wrappers.h" #include "memory.h" +#include "statctrl.h" +#include "ctrlvalue.h" + +static int addtohdr = 0; +static int prepmailinmem = 0; char *bounce_from_adr(const char *recipient, const char *listadr, const char *mailfilename) @@ -158,10 +164,12 @@ int send_mail(int sockfd, const char *from, const char *to, const char *replyto, char *mailmap, size_t mailsize, - const char *listdir, const char *mlmmjbounce) + const char *listdir, const char *mlmmjbounce, + const char *hdrs, size_t hdrslen, const char *body, + size_t bodylen) { int retval = 0; - char *reply; + char *reply, *tohdr; retval = write_mail_from(sockfd, from); if(retval) { @@ -222,11 +230,38 @@ } } - retval = write_mailbody_from_map(sockfd, mailmap, mailsize); + if(addtohdr) + tohdr = concatstr(3, "To: ", to, "\r\n"); + else + tohdr = NULL; + + if(prepmailinmem) { + retval = writen(sockfd, hdrs, hdrslen); + if(retval < 0) { + log_error(LOG_ARGS, "Could not write mailheaders.\n"); + return retval; + } + if(tohdr) { + retval = writen(sockfd, tohdr, strlen(tohdr)); + if(retval < 0) { + log_error(LOG_ARGS, "Could not write To:.\n"); + return retval; + } + myfree(tohdr); + } + retval = writen(sockfd, body, bodylen); + if(retval < 0) { + log_error(LOG_ARGS, "Could not write mailbody.\n"); + return retval; + } + } else { + retval = write_mailbody_from_map(sockfd, mailmap, mailsize, + tohdr); if(retval) { - log_error(LOG_ARGS, "Could not write mailbody\n"); + log_error(LOG_ARGS, "Could not write mail\n"); return retval; } + } retval = write_dot(sockfd); if(retval) { @@ -297,7 +332,9 @@ int send_mail_many(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 *listdir, const char *mlmmjbounce, + const char *hdrs, size_t hdrslen, const char *body, + size_t bodylen) { int sendres = 0, addrfd; char *bounceaddr, *addr, *index, *dirname, *addrfilename; @@ -330,12 +367,14 @@ if(from) sendres = send_mail(sockfd, from, addr, replyto, - mailmap, mailsize, listdir, NULL); + mailmap, mailsize, listdir, NULL, + hdrs, hdrslen, body, bodylen); else { bounceaddr = bounce_from_adr(addr, listaddr, archivefilename); sendres = send_mail(sockfd, bounceaddr, addr, replyto, - mailmap, mailsize, listdir, mlmmjbounce); + mailmap, mailsize, listdir, mlmmjbounce, + hdrs, hdrslen, body, bodylen); myfree(bounceaddr); } if(sendres && listaddr && archivefilename) { @@ -411,7 +450,7 @@ int main(int argc, char **argv) { - size_t len = 0; + size_t len = 0, hdrslen, bodylen; int sockfd = 0, mailfd = 0, opt, mindex, subfd, tmpfd; int deletewhensent = 1, sendres, archive = 1; char *listaddr, *mailfilename = NULL, *subfilename = NULL; @@ -419,6 +458,8 @@ char *relayhost = NULL, *archivefilename = NULL, *tmpstr; char *listctrl = NULL, *subddirname = NULL, *listdir = NULL; char *mlmmjbounce = NULL, *bindir, *mailmap, *probefile, *a; + char *body = NULL, *hdrs = NULL, *memmailsizestr = NULL; + size_t memmailsize = 0; DIR *subddir; struct dirent *dp; struct stat st; @@ -519,12 +560,45 @@ exit(EXIT_FAILURE); } + addtohdr = statctrl(listdir, "addtohdr"); + memmailsizestr = ctrlvalue(listdir, "memorymailsize"); + if(memmailsizestr) { + memmailsize = strtol(memmailsizestr, NULL, 10); + myfree(memmailsizestr); + } + + if(memmailsize == 0) + memmailsize = MEMORYMAILSIZE; + + if(st.st_size > memmailsize) { + prepmailinmem = 0; + errno = 0; + log_error(LOG_ARGS, "Not preparing in memory. " + "Mail is %ld bytes", (long)st.st_size); + } else + prepmailinmem = 1; + mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, mailfd, 0); if(mailmap == MAP_FAILED) { log_error(LOG_ARGS, "Could not mmap mailfd"); exit(EXIT_FAILURE); } + if(prepmailinmem) { + hdrs = get_preppedhdrs_from_map(mailmap, &hdrslen); + if(hdrs == NULL) { + log_error(LOG_ARGS, "Could not prepare headers"); + exit(EXIT_FAILURE); + } + body = get_prepped_mailbody_from_map(mailmap, st.st_size, + &bodylen); + if(body == NULL) { + log_error(LOG_ARGS, "Could not prepare mailbody"); + myfree(hdrs); + exit(EXIT_FAILURE); + } + } + switch(listctrl[0]) { case '1': /* A single mail is to be sent, do nothing */ case '5': @@ -534,6 +608,8 @@ if((subfd = open(subfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s':", subfilename); + myfree(hdrs); + myfree(body); myfree(subfilename); /* No moderators is no error. Could be the sysadmin * likes to do it manually. @@ -546,6 +622,8 @@ if((subfd = open(subfilename, O_RDONLY)) < 0) { log_error(LOG_ARGS, "Could not open '%s':", subfilename); + myfree(hdrs); + myfree(body); exit(EXIT_FAILURE); } @@ -569,7 +647,8 @@ case '1': /* A single mail is to be sent */ initsmtp(&sockfd, relayhost); sendres = send_mail(sockfd, bounceaddr, to_addr, replyto, - mailmap, st.st_size, listdir, NULL); + mailmap, st.st_size, listdir, NULL, + hdrs, hdrslen, body, bodylen); endsmtp(&sockfd); if(sendres) { /* error, so keep it in the queue */ @@ -610,8 +689,9 @@ break; case '2': /* Moderators */ initsmtp(&sockfd, relayhost); - if(send_mail_many(sockfd, bounceaddr, NULL, mailmap, st.st_size, - subfd, NULL, NULL, listdir, NULL)) + if(send_mail_many(sockfd, bounceaddr, NULL, mailmap, + st.st_size, subfd, NULL, NULL, listdir, + NULL, hdrs, hdrslen, body, bodylen)) close(sockfd); else endsmtp(&sockfd); @@ -620,7 +700,7 @@ initsmtp(&sockfd, relayhost); if(send_mail_many(sockfd, NULL, NULL, mailmap, st.st_size, subfd, listaddr, mailfilename, listdir, - mlmmjbounce)) + mlmmjbounce, hdrs, hdrslen, body, bodylen)) close(sockfd); else endsmtp(&sockfd); @@ -630,7 +710,7 @@ initsmtp(&sockfd, relayhost); if(send_mail_many(sockfd, bounceaddr, NULL, mailmap, st.st_size, subfd, listaddr, mailfilename, listdir, - mlmmjbounce)) + mlmmjbounce, hdrs, hdrslen, body, bodylen)) close(sockfd); else endsmtp(&sockfd); @@ -638,7 +718,8 @@ case '5': /* bounceprobe - handle relayhost local users bouncing*/ initsmtp(&sockfd, relayhost); sendres = send_mail(sockfd, bounceaddr, to_addr, replyto, - mailmap, st.st_size, listdir, NULL); + mailmap, st.st_size, listdir, NULL, + hdrs, hdrslen, body, bodylen); endsmtp(&sockfd); if(sendres) { /* error, so remove the probefile */ @@ -658,6 +739,8 @@ log_error(LOG_ARGS, "Could not opendir(%s)", subddirname); myfree(subddirname); + myfree(hdrs); + myfree(body); exit(EXIT_FAILURE); } myfree(subddirname); @@ -680,7 +763,8 @@ initsmtp(&sockfd, relayhost); sendres = send_mail_many(sockfd, NULL, NULL, mailmap, st.st_size, subfd, listaddr, - archivefilename, listdir, mlmmjbounce); + archivefilename, listdir, mlmmjbounce, + hdrs, hdrslen, body, bodylen); if (sendres) { /* If send_mail_many() failed we close the * connection to the mail server in a brutal @@ -696,6 +780,8 @@ break; } + myfree(hdrs); + myfree(body); munmap(mailmap, st.st_size); close(mailfd);