From: Baptiste Daroussin Date: Wed, 5 Jan 2022 09:03:35 +0000 (+0100) Subject: prepstdreply: duplicate and simplify X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc8cbda8810147a5b213e524997695b6af8b9ace;p=thirdparty%2Fmlmmj.git prepstdreply: duplicate and simplify in the migration time duplicate the function to convert it into a function which mainly manipulated file descriptors and prevent uselessly reopening the queued file later --- diff --git a/include/mlmmj.h b/include/mlmmj.h index 1cbb744e..82655d4c 100644 --- a/include/mlmmj.h +++ b/include/mlmmj.h @@ -87,6 +87,11 @@ struct mailhdr { char **values; }; +struct queuedmail { + int fd; + char *name; +}; + /* Has to go here, since it's used in many places */ enum subtype { @@ -116,6 +121,8 @@ void print_version(const char *prg); void mlmmj_list_init(struct mlmmj_list *list); bool mlmmj_list_open(struct mlmmj_list *list); void mlmmj_list_close(struct mlmmj_list *list); +void queuedmail_free(struct queuedmail *q); +struct queuedmail *queuedmail_new(void); #define MY_ASSERT(expression) if (!(expression)) { \ errno = 0; \ diff --git a/include/prepstdreply.h b/include/prepstdreply.h index 76ab1b1b..7c6153fd 100644 --- a/include/prepstdreply.h +++ b/include/prepstdreply.h @@ -64,6 +64,8 @@ void register_formatted(text *txt, const char *token, char *get_processed_text_line(text *txt, int headers, struct mlmmj_list *list); char *prepstdreply(text *txt, struct mlmmj_list *list, const char *from, const char *to, const char *replyto, bool infd); +struct queuedmail *prepqstdreply(text *txt, struct mlmmj_list *list, + const char *from, const char *to, const char *replyto); void close_text(text *txt); #endif /* PREPSTDREPLY_H */ diff --git a/include/send_help.h b/include/send_help.h index 15ecd60b..f060dd10 100644 --- a/include/send_help.h +++ b/include/send_help.h @@ -28,7 +28,7 @@ #include "mlmmj.h" -void send_help(struct mlmmj_list *list, const char *queuefilename, +void send_help(struct mlmmj_list *list, struct queuedmail *q, const char *emailaddr); #endif diff --git a/include/send_mails.h b/include/send_mails.h index 2cfd2def..1b1aa6ad 100644 --- a/include/send_mails.h +++ b/include/send_mails.h @@ -35,5 +35,5 @@ int initsmtp(int *sockfd, const char *relayhost, unsigned short port, const char int endsmtp(int *sockfd); int send_mail(int sockfd, const char *from, const char *to, const char *replyto, char *mailmap, size_t mailsize, struct mlmmj_list *list, const char *mlmmjbounce, const char *hdrs, size_t hdrslen, const char *body, size_t bodylen, bool addtohdr, bool prepmailinmem); int bouncemail(struct mlmmj_list *list, const char *mlmmjbounce, const char *from); -bool send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int queue, const char *mailfilename); +bool send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, struct queuedmail *q); #endif diff --git a/src/listcontrol.c b/src/listcontrol.c index 63456583..d5936def 100644 --- a/src/listcontrol.c +++ b/src/listcontrol.c @@ -128,8 +128,8 @@ int listcontrol(struct email_container *fromemails, struct mlmmj_list *list, struct strlist *owners; int owner_idx; text *txt; - char *queuefilename; - + struct queuedmail *q; + /* A closed list doesn't allow subscribtion and unsubscription */ closedlist = statctrl(list, "closedlist"); @@ -225,12 +225,12 @@ int listcontrol(struct email_container *fromemails, struct mlmmj_list *list, MY_ASSERT(txt); register_unformatted(txt, "subaddr", fromemails->emaillist[0]); - queuefilename = prepstdreply(txt, list, "$listowner$", - fromemails->emaillist[0], NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", + fromemails->emaillist[0], NULL); + MY_ASSERT(q); close_text(txt); - send_help(list, queuefilename, fromemails->emaillist[0]); - return -1; + send_help(list, q, fromemails->emaillist[0]); + /* send_help does not return */ } log_oper(list->dir, OPLOGFNAME, "mlmmj-sub: request for digest" " subscription from %s", @@ -272,11 +272,11 @@ int listcontrol(struct email_container *fromemails, struct mlmmj_list *list, MY_ASSERT(txt); register_unformatted(txt, "subaddr", fromemails->emaillist[0]); - queuefilename = prepstdreply(txt, list, "$listowner$", - fromemails->emaillist[0], NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", + fromemails->emaillist[0], NULL); + MY_ASSERT(q); close_text(txt); - send_help(list, queuefilename, fromemails->emaillist[0]); + send_help(list, q, fromemails->emaillist[0]); return -1; } log_oper(list->dir, OPLOGFNAME, "mlmmj-sub: request for nomail" @@ -319,11 +319,11 @@ int listcontrol(struct email_container *fromemails, struct mlmmj_list *list, MY_ASSERT(txt); register_unformatted(txt, "subaddr", fromemails->emaillist[0]); - queuefilename = prepstdreply(txt, list, "$listowner$", - fromemails->emaillist[0], NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", + fromemails->emaillist[0], NULL); + MY_ASSERT(q); close_text(txt); - send_help(list, queuefilename, fromemails->emaillist[0]); + send_help(list, q, fromemails->emaillist[0]); return -1; } log_oper(list->dir, OPLOGFNAME, "mlmmj-sub: request for both" @@ -795,11 +795,11 @@ permit: fromemails->emaillist[0]); txt = open_text(list, "help", NULL, NULL, NULL, "listhelp"); MY_ASSERT(txt); - queuefilename = prepstdreply(txt, list, - "$listowner$", fromemails->emaillist[0], NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, + "$listowner$", fromemails->emaillist[0], NULL); + MY_ASSERT(q); close_text(txt); - send_help(list, queuefilename, fromemails->emaillist[0]); + send_help(list, q, fromemails->emaillist[0]); break; /* listname+faq@domain.tld */ @@ -816,11 +816,11 @@ permit: fromemails->emaillist[0]); txt = open_text(list, "faq", NULL, NULL, NULL, "listfaq"); MY_ASSERT(txt); - queuefilename = prepstdreply(txt, list, - "$listowner$", fromemails->emaillist[0], NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, + "$listowner$", fromemails->emaillist[0], NULL); + MY_ASSERT(q); close_text(txt); - send_help(list, queuefilename, fromemails->emaillist[0]); + send_help(list, q, fromemails->emaillist[0]); break; /* listname+get-INDEX@domain.tld */ diff --git a/src/mlmmj-maintd.c b/src/mlmmj-maintd.c index db4754c1..e9849cf9 100644 --- a/src/mlmmj-maintd.c +++ b/src/mlmmj-maintd.c @@ -171,12 +171,12 @@ int resend_queue(struct mlmmj_list *list, const char *mlmmjsend) { DIR *queuedir; struct dirent *dp; - char *mailname, *fromname, *toname, *reptoname, *from, *to, *repto; + char *fromname, *toname, *reptoname, *from, *to, *repto; char *ch; struct stat st; int fromfd, tofd, fd, err = 0; - int queuefd; time_t t, bouncelife = 0; + struct queuedmail q; if((queuedir = fdopendir(list->queuefd)) == NULL) { log_error(LOG_ARGS, "Could not queue directory"); @@ -184,33 +184,36 @@ int resend_queue(struct mlmmj_list *list, const char *mlmmjsend) } while((dp = readdir(queuedir)) != NULL) { - mailname = dp->d_name; - queuefd = openat(list->queuefd, mailname, O_RDONLY); - if(queuefd < 0 || fstat(queuefd, &st) < 0) { - log_error(LOG_ARGS, "Could not open or fstat(%s)", mailname); + q.name = dp->d_name; + q.fd = openat(list->queuefd, q.name, O_RDONLY); + if(q.fd < 0 || fstat(q.fd, &st) < 0) { + log_error(LOG_ARGS, "Could not open or fstat(%s)", q.name); continue; } - if(!S_ISREG(st.st_mode)) + if(!S_ISREG(st.st_mode)) { + close(q.fd); continue; + } if(strchr(dp->d_name, '.')) { char *tmpname = xstrdup(dp->d_name); ch = strrchr(tmpname, '.'); MY_ASSERT(ch); *ch = '\0'; + close(q.fd); /* delete orphaned sidecar files */ if (fstatat(list->queuefd, tmpname, &st, 0) < 0) { if(errno == ENOENT) - unlinkat(list->queuefd, mailname, 0); + unlinkat(list->queuefd, q.name, 0); } free(tmpname); continue; } - xasprintf(&fromname, "%s.mailfrom", mailname); - xasprintf(&toname, "%s.reciptto", mailname); - xasprintf(&reptoname, "%s.reply-to", mailname); + xasprintf(&fromname, "%s.mailfrom", q.name); + xasprintf(&toname, "%s.reciptto", q.name); + xasprintf(&reptoname, "%s.reply-to", q.name); fromfd = openat(list->queuefd, fromname, O_RDONLY); if(fromfd < 0) @@ -223,7 +226,7 @@ int resend_queue(struct mlmmj_list *list, const char *mlmmjsend) mail currently being sent */ t = time(NULL); if(t - st.st_mtime > (time_t)36000) { - unlinkat(list->queuefd, mailname, 0); + unlinkat(list->queuefd, q.name, 0); /* avoid leaving orphans */ unlinkat(list->queuefd, fromname, 0); unlinkat(list->queuefd, toname, 0); @@ -236,6 +239,7 @@ int resend_queue(struct mlmmj_list *list, const char *mlmmjsend) close(fromfd); if(tofd >= 0) close(tofd); + close(q.fd); continue; } @@ -265,7 +269,8 @@ int resend_queue(struct mlmmj_list *list, const char *mlmmjsend) t = time(NULL); if(t - st.st_mtime > bouncelife) { - unlinkat(list->queuefd, mailname, 0); + unlinkat(list->queuefd, q.name, 0); + close(q.fd); free(from); free(to); free(repto); @@ -277,7 +282,7 @@ int resend_queue(struct mlmmj_list *list, const char *mlmmjsend) mh.to = to; mh.from = from; mh.replyto = repto; - if (send_single_mail(list, &mh, queuefd, mailname)) + if (send_single_mail(list, &mh, &q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } diff --git a/src/mlmmj-process.c b/src/mlmmj-process.c index 68e8f7a9..5b557b83 100644 --- a/src/mlmmj-process.c +++ b/src/mlmmj-process.c @@ -133,8 +133,9 @@ static void newmoderated(struct mlmmj_list *list, const char *mailfilename, const char *efromismod = NULL; const char *mailbasename = mybasename(mailfilename); char *to, *reject; - int notifymod = 0, status, queuefd; + int notifymod = 0, status; pid_t childpid, pid; + struct queuedmail *q; #if 0 printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename, mailbasename); @@ -195,12 +196,13 @@ static void newmoderated(struct mlmmj_list *list, const char *mailfilename, finish_memory_lines(mls); if(efromismod) { + struct queuedmail myq; memset(&mh, 0, sizeof(mh)); mh.to = efromsender; mh.from = from; - queuefd = openat(list->queuefd, queuefilename, - O_RDONLY); - if (send_single_mail(list, &mh, queuefd, queuefilename)) + myq.name = queuefilename; + myq.fd = openat(list->queuefd, myq.name, O_RDONLY); + if (send_single_mail(list, &mh, &myq)) exit(EXIT_SUCCESS); } else execlp(mlmmjsend, mlmmjsend, @@ -225,17 +227,16 @@ static void newmoderated(struct mlmmj_list *list, const char *mailfilename, register_formatted(txt, "moderators", rewind_memory_lines, get_memory_line, mls); register_originalmail(txt, mailfilename); - queuefilename = prepstdreply(txt, list, "$listowner$", efromsender, NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", efromsender, NULL); + MY_ASSERT(q); close_text(txt); finish_memory_lines(mls); - queuefd = openat(list->queuefd, queuefilename, O_RDONLY); memset(&mh, 0, sizeof(mh)); mh.to = efromsender; mh.from = from; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -440,10 +441,10 @@ send_denymail(struct mlmmj_list *list, const char *cause, const char *subcause, char *causestr, const char *posteraddr, const char *subject, char *donemailname, const char *mailfile) { - char *fromaddr, *queuefilename; + char *fromaddr; text *txt; struct mail_headers mh; - int queuefd; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); txt = open_text(list, "deny", "post", cause, NULL, subcause); @@ -453,9 +454,8 @@ send_denymail(struct mlmmj_list *list, const char *cause, const char *subcause, if (causestr != NULL) register_unformatted(txt, cause, causestr); register_originalmail(txt, donemailname); - queuefilename = prepstdreply(txt, list, "$listowner$", posteraddr, NULL, false); - MY_ASSERT(queuefilename); - queuefd = openat(list->queuefd, queuefilename, O_RDONLY); + q = prepqstdreply(txt, list, "$listowner$", posteraddr, NULL); + MY_ASSERT(q); close_text(txt); unlink(donemailname); unlink(mailfile); @@ -464,7 +464,7 @@ send_denymail(struct mlmmj_list *list, const char *cause, const char *subcause, memset(&mh, 0, sizeof(mh)); mh.to = posteraddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } diff --git a/src/mlmmj-sub.c b/src/mlmmj-sub.c index 74360bf6..059c25e5 100644 --- a/src/mlmmj-sub.c +++ b/src/mlmmj-sub.c @@ -61,6 +61,7 @@ static void moderate_sub(struct mlmmj_list *list, const char *subaddr, const char *modetype; struct strlist *submods; pid_t childpid, pid; + struct queuedmail *q; /* generate the file in moderation/ */ switch(typesub) { @@ -207,17 +208,16 @@ static void moderate_sub(struct mlmmj_list *list, const char *subaddr, register_unformatted(txt, "moderators", "%gatekeepers"); /* DEPRECATED */ register_formatted(txt, "gatekeepers", rewind_memory_lines, get_memory_line, mls); - queuefilename = prepstdreply(txt, list, "$listowner$", subaddr, NULL, false); + q = prepqstdreply(txt, list, "$listowner$", subaddr, NULL); MY_ASSERT(queuefilename); close_text(txt); finish_memory_lines(mls); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = from; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -285,7 +285,8 @@ static void confirm_sub(struct mlmmj_list *list, const char *subaddr, enum subtype typesub, enum subreason reasonsub) { text *txt; - char *queuefilename, *fromaddr, *listtext; + char *fromaddr, *listtext; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); @@ -313,16 +314,16 @@ static void confirm_sub(struct mlmmj_list *list, const char *subaddr, free(listtext); MY_ASSERT(txt); register_unformatted(txt, "subaddr", subaddr); - queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, true); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - send_single_mail(list, &mh, queuefd, queuefilename); + send_single_mail(list, &mh, q); + queuedmail_free(q); } static void notify_sub(struct mlmmj_list *list, const char *subaddr, @@ -330,7 +331,8 @@ static void notify_sub(struct mlmmj_list *list, const char *subaddr, { char *fromaddr, *tostr; text *txt; - char *queuefilename = NULL, *listtext = NULL; + struct queuedmail *q; + char *listtext = NULL; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); @@ -361,16 +363,15 @@ static void notify_sub(struct mlmmj_list *list, const char *subaddr, MY_ASSERT(txt); register_unformatted(txt, "subaddr", subaddr); register_unformatted(txt, "newsub", subaddr); /* DEPRECATED */ - queuefilename = prepstdreply(txt, list, "$listowner$", "$listowner$", NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", "$listowner$", NULL); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -381,8 +382,9 @@ static void generate_subconfirm(struct mlmmj_list *list, const char *subaddr, int subconffd; char *confirmaddr, *confirmfilename = NULL; text *txt; - char *listtext, *queuefilename = NULL, *fromaddr; + char *listtext, *fromaddr; char *randomstr = NULL, *tmpstr; + struct queuedmail *q; do { free(confirmfilename); @@ -452,15 +454,14 @@ static void generate_subconfirm(struct mlmmj_list *list, const char *subaddr, register_unformatted(txt, "subaddr", subaddr); register_unformatted(txt, "confaddr", confirmaddr); /* DEPRECATED */ register_unformatted(txt, "confirmaddr", confirmaddr); - queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr, true); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -492,7 +493,8 @@ static void generate_subscribed(struct mlmmj_list *list, const char *subaddr, enum subtype typesub) { text *txt; - char *queuefilename, *fromaddr; + char *fromaddr; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); @@ -502,16 +504,15 @@ static void generate_subscribed(struct mlmmj_list *list, const char *subaddr, "sub-subscribed"); MY_ASSERT(txt); register_unformatted(txt, "subaddr", subaddr); - queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } diff --git a/src/mlmmj-unsub.c b/src/mlmmj-unsub.c index 36fab13a..20516861 100644 --- a/src/mlmmj-unsub.c +++ b/src/mlmmj-unsub.c @@ -44,7 +44,8 @@ static void confirm_unsub(struct mlmmj_list *list, const char *subaddr, enum subtype typesub, enum subreason reasonsub) { text *txt; - char *queuefilename, *fromaddr, *listtext; + char *fromaddr, *listtext; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); @@ -67,16 +68,15 @@ static void confirm_unsub(struct mlmmj_list *list, const char *subaddr, free(listtext); MY_ASSERT(txt); register_unformatted(txt, "subaddr", subaddr); - queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -86,8 +86,8 @@ static void notify_unsub(struct mlmmj_list *list, const char *subaddr, { char *fromaddr, *tostr; text *txt; - char *queuefilename = NULL; const char *listtext; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); @@ -112,16 +112,15 @@ static void notify_unsub(struct mlmmj_list *list, const char *subaddr, MY_ASSERT(txt); register_unformatted(txt, "subaddr", subaddr); register_unformatted(txt, "oldsub", subaddr); /* DEPRECATED */ - queuefilename = prepstdreply(txt, list, "$listowner$", "$listowner$", NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", "$listowner$", NULL); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = tostr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -133,9 +132,10 @@ static void generate_unsubconfirm(struct mlmmj_list *list, const char *subaddr, const char *tmpstr; char *confirmaddr; text *txt; - char *queuefilename, *fromaddr; + char *fromaddr; char *randomstr = NULL, *confirmfilename = NULL, *listtext; int subconffd; + struct queuedmail *q; do { free(confirmfilename); @@ -196,16 +196,15 @@ static void generate_unsubconfirm(struct mlmmj_list *list, const char *subaddr, register_unformatted(txt, "subaddr", subaddr); register_unformatted(txt, "confaddr", confirmaddr); /* DEPRECATED */ register_unformatted(txt, "confirmaddr", confirmaddr); - queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } @@ -238,7 +237,8 @@ static void generate_notsubscribed(struct mlmmj_list *list, const char *subaddr, enum subtype typesub) { text *txt; - char *queuefilename, *fromaddr; + char *fromaddr; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounes-help@%s", list->name, list->delim, list->fqdn); @@ -247,16 +247,15 @@ static void generate_notsubscribed(struct mlmmj_list *list, const char *subaddr, "unsub-notsubscribed"); MY_ASSERT(txt); register_unformatted(txt, "subaddr", subaddr); - queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL); + MY_ASSERT(q); close_text(txt); - int queuefd = openat(list->queuefd, queuefilename, O_RDONLY); struct mail_headers mh; memset(&mh, 0, sizeof(mh)); mh.to = subaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } diff --git a/src/mlmmj.c b/src/mlmmj.c index 883849b2..4d012fa8 100644 --- a/src/mlmmj.c +++ b/src/mlmmj.c @@ -95,3 +95,22 @@ mlmmj_list_open(struct mlmmj_list *list) } return (true); } + +void +queuedmail_free(struct queuedmail *q) +{ + if (q == NULL) + return; + free(q->name); + if (q->fd != -1) + close(q->fd); + free(q); +} + +struct queuedmail * +queuedmail_new(void) +{ + struct queuedmail *q = xcalloc(1, sizeof(struct queuedmail)); + q->fd = -1; + return (q); +} diff --git a/src/prepstdreply.c b/src/prepstdreply.c index a898b427..a3b19259 100644 --- a/src/prepstdreply.c +++ b/src/prepstdreply.c @@ -1617,7 +1617,7 @@ char *prepstdreply(text *txt, struct mlmmj_list *list, return NULL; } - for (i=0; i<6; i++) { + for (i=0; i<6; i++) { tmp = xstrdup("randomN"); tmp[6] = '0' + i; str = random_str(); @@ -1754,3 +1754,159 @@ char *prepstdreply(text *txt, struct mlmmj_list *list, freeandreturn: return retstr; } + +struct queuedmail *prepqstdreply(text *txt, struct mlmmj_list *list, + const char *from, const char *to, + const char *replyto) +{ + size_t len, i; + char *line; + char *str; + char *tmp; + char *headers[10] = { NULL }; /* relies on NULL to flag end */ + struct queuedmail *q = xcalloc(1, sizeof(struct queuedmail)); + + do { + if (list->queuefd == -1) + list->queuefd = openat(list->fd, "queue", O_DIRECTORY); + free(q->name); + q->name = random_str(); + q->fd = openat(list->queuefd, q->name, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + } while ((q->fd < 0) && (errno == EEXIST)); + + if(q->fd < 0) { + log_error(LOG_ARGS, "Could not open std mail %s", q->name); + queuedmail_free(q); + return NULL; + } + + for (i=0; i<6; i++) { + tmp = xstrdup("randomN"); + tmp[6] = '0' + i; + str = random_str(); + register_unformatted(txt, tmp, str); + free(tmp); + free(str); + } + + tmp = substitute(from, list, txt); + xasprintf(&headers[0], "From: %s", tmp); + free(tmp); + tmp = substitute(to, list, txt); + xasprintf(&headers[1], "To: %s", tmp); + free(tmp); + headers[2] = genmsgid(list->fqdn); + chomp(headers[2]); + headers[3] = gendatestr(); + chomp(headers[3]); + headers[4] = xstrdup("Subject: mlmmj administrivia"); + headers[5] = xstrdup("MIME-Version: 1.0"); + headers[6] = xstrdup("Content-Type: text/plain; charset=utf-8"); + headers[7] = xstrdup("Content-Transfer-Encoding: 8bit"); + + if(replyto) { + tmp = substitute(replyto, list, txt); + xasprintf(&headers[8], "Reply-To: %s", tmp); + free(tmp); + } + + for(;;) { + line = get_processed_text_line(txt, 1, list); + if (!line) { + log_error(LOG_ARGS, "No body in listtext"); + break; + } + if (*line == '\0') { + /* end of headers */ + free(line); + line = NULL; + break; + } + if (*line == ' ' || *line == '\t') { + /* line beginning with linear whitespace is a + continuation of previous header line */ + if(dprintf(q->fd, "%s\n", line) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + free(line); + queuedmail_free(q); + return (NULL); + } + } else { + tmp = line; + len = 0; + while (*tmp && *tmp != ':') { + tmp++; + len++; + } + if (!*tmp) { + log_error(LOG_ARGS, "No headers or invalid " + "header in listtext"); + break; + } + tmp++; + len++; + /* remove the standard header if one matches */ + for (i=0; headers[i] != NULL; i++) { + if (strncasecmp(line, headers[i], len) == 0) { + free(headers[i]); + while (headers[i] != NULL) { + headers[i] = headers[i+1]; + i++; + } + break; + } + } + if (strncasecmp(line, "Subject:", len) == 0) { + tmp = unistr_utf8_to_header(tmp); + free(line); + xasprintf(&line, "Subject: %s", tmp); + free(tmp); + } + if(dprintf(q->fd, "%s\n", line) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + free(line); + queuedmail_free(q); + return (NULL); + } + } + free(line); + line = NULL; + } + + for (i=0; headers[i] != NULL; i++) { + if(dprintf(q->fd, "%s\n", headers[i]) < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + if (line) + free(line); + queuedmail_free(q); + return (NULL); + } + } + + /* end the headers */ + if(dprintf(q->fd, "\n") < 0) { + log_error(LOG_ARGS, "Could not write std mail"); + if (line) + free(line); + queuedmail_free(q); + return (NULL); + } + + if (line == NULL) { + line = get_processed_text_line(txt, 0, list); + } + while(line) { + if(dprintf(q->fd, "%s\n", line) < 0) { + free(str); + log_error(LOG_ARGS, "Could not write std mail"); + queuedmail_free(q); + return (NULL); + } + free(line); + line = get_processed_text_line(txt, 0, list); + } + + fsync(q->fd); + + return q; +} diff --git a/src/send_help.c b/src/send_help.c index 5a9e0aaf..eed6634a 100644 --- a/src/send_help.c +++ b/src/send_help.c @@ -31,20 +31,18 @@ #include "send_help.h" #include "send_mails.h" -void send_help(struct mlmmj_list *list, const char *queuefilename, +void send_help(struct mlmmj_list *list, struct queuedmail *q, const char *emailaddr) { struct mail_headers mh; char *fromaddr; - int queuefd; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); memset(&mh, 0, sizeof(mh)); mh.to = emailaddr; mh.from = fromaddr; - queuefd = openat(list->queuefd, queuefilename, O_RDONLY); - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } diff --git a/src/send_list.c b/src/send_list.c index 4e75e3b3..31585274 100644 --- a/src/send_list.c +++ b/src/send_list.c @@ -163,10 +163,10 @@ void send_list(struct mlmmj_list *list, const char *emailaddr) { text *txt; subs_list_state *normalsls, *digestsls, *nomailsls; - char *queuefilename; struct mail_headers mh; char *fromaddr; - int fd, queuefd;; + int fd;; + struct queuedmail *q; xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn); @@ -185,15 +185,14 @@ void send_list(struct mlmmj_list *list, const char *emailaddr) rewind_subs_list, get_sub, digestsls); register_formatted(txt, "nomailsubs", rewind_subs_list, get_sub, nomailsls); - queuefilename = prepstdreply(txt, list, "$listowner$", emailaddr, NULL, false); - MY_ASSERT(queuefilename); + q = prepqstdreply(txt, list, "$listowner$", emailaddr, NULL); + MY_ASSERT(q); close_text(txt); - queuefd = openat(list->queuefd, queuefilename, O_RDONLY); /* DEPRECATED */ /* Add lists manually if they weren't encountered in the list text */ if (!normalsls->used && !digestsls->used && !nomailsls->used) { - fd = open(queuefilename, O_WRONLY); + fd = openat(list->queuefd, q->name, O_WRONLY); if(fd < 0) { log_error(LOG_ARGS, "Could not open sub list mail"); exit(EXIT_FAILURE); @@ -218,7 +217,7 @@ void send_list(struct mlmmj_list *list, const char *emailaddr) memset(&mh, 0, sizeof(mh)); mh.to = emailaddr; mh.from = fromaddr; - if (send_single_mail(list, &mh, queuefd, queuefilename)) + if (send_single_mail(list, &mh, q)) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } diff --git a/src/send_mails.c b/src/send_mails.c index 8c996f08..5a837559 100644 --- a/src/send_mails.c +++ b/src/send_mails.c @@ -369,7 +369,7 @@ bouncemail(struct mlmmj_list *list, const char *mlmmjbounce, const char *from) } bool -send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, const char *mailfilename) +send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, struct queuedmail *q) { ssize_t memmailsize; bool prepmailinmem = true; @@ -387,7 +387,7 @@ send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, c if (memmailsize == 0) memmailsize = MEMORYMAILSIZE; - if (fstat(mailfd, &st) < 0) { + if (fstat(q->fd, &st) < 0) { log_error(LOG_ARGS, "Could not stat mailfd"); return (false); } @@ -399,7 +399,7 @@ send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, c "MAil is %zu bytes", st.st_size); } - mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, mailfd, 0); + mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, q->fd, 0); if (mailmap == MAP_FAILED) { log_error(LOG_ARGS, "Could not mmap mailfd"); return (false); @@ -453,7 +453,7 @@ send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, c sockfd = -1; /* dump data we want when resending first check * if it already exists. In that case continue */ - xasprintf(&tmpstr, "%s.mailfrom", mailfilename); + xasprintf(&tmpstr, "%s.mailfrom", q->name); if(stat(tmpstr, &st) == 0) { free(tmpstr); goto out; @@ -466,7 +466,7 @@ send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, c fsync(tmpfd); } close(tmpfd); - xasprintf(&tmpstr, "%s.reciptto", mailfilename); + xasprintf(&tmpstr, "%s.reciptto", q->name); if(stat(tmpstr, &st) == 0) { free(tmpstr); goto out; @@ -480,7 +480,7 @@ send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, c } close(tmpfd); if(mh->replyto) { - xasprintf(&tmpstr, "%s.reply-to", mailfilename); + xasprintf(&tmpstr, "%s.reply-to", q->name); if(stat(tmpstr, &st) == 0) { free(tmpstr); goto out; @@ -502,7 +502,6 @@ out: free(hdrs); free(body); munmap(mailmap, st.st_size); - close(mailfd); free(smtphelo); /* TODO Archive goes here */ diff --git a/tests/mlmmj.c b/tests/mlmmj.c index d01743ce..a2d6710a 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -35,6 +35,7 @@ #include #include +#include "xmalloc.h" #include "chomp.h" #include "mlmmj.h" #include "wrappers.h" @@ -248,6 +249,7 @@ static const char *formatted_text1 = ATF_TC_BODY(open_text, tc) { struct mlmmj_list list; + char *qname; init_ml(true); mlmmj_list_init(&list); @@ -258,7 +260,8 @@ ATF_TC_BODY(open_text, tc) text *txt = open_text(&list, "finish", "sub", "request", "normal", "sub-confirm"); ATF_CHECK(txt != NULL); register_unformatted(txt, "subaddr", "john@doe.net"); - char *qname = prepstdreply(txt, &list, "$helpaddr$", "john@doe.net", NULL, false); + struct queuedmail *q = prepqstdreply(txt, &list, "$helpaddr$", "john@doe.net", NULL); + xasprintf(&qname, "%s/queue/%s", list.dir, q->name); if (!atf_utils_grep_file("^To: john@doe.net", qname) || !atf_utils_grep_file("^The email address .*john@doe.net.*", qname) || !atf_utils_grep_file("^Subject: .*Welcome_to_test", qname)) {