]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
prepstdreply: duplicate and simplify
authorBaptiste Daroussin <bapt@FreeBSD.org>
Wed, 5 Jan 2022 09:03:35 +0000 (10:03 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Wed, 5 Jan 2022 09:12:48 +0000 (10:12 +0100)
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

15 files changed:
include/mlmmj.h
include/prepstdreply.h
include/send_help.h
include/send_mails.h
src/listcontrol.c
src/mlmmj-maintd.c
src/mlmmj-process.c
src/mlmmj-sub.c
src/mlmmj-unsub.c
src/mlmmj.c
src/prepstdreply.c
src/send_help.c
src/send_list.c
src/send_mails.c
tests/mlmmj.c

index 1cbb744eb9bf33697f660a37bc00920576d65c86..82655d4c2267dd4507945e505d22ba106614e7f6 100644 (file)
@@ -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; \
index 76ab1b1b1eb9942b1a1fdfc65225640b8816baca..7c6153fd3b64d103947d061a0d4b4d41b232c41f 100644 (file)
@@ -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 */
index 15ecd60b239c9a9c138bfa85b77feb61e85beec7..f060dd10dd76fac61c09c8c840d7b6dad9451503 100644 (file)
@@ -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
index 2cfd2def767794854e0cf48fdb53a85c4cc9b4ba..1b1aa6ada868c47074d7975d4605d9aa17716299 100644 (file)
@@ -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
index 634565831766862f8b6ea669ead5fbf75ebb610a..d5936def1df3091f7973a3118f9ebadc52c1a759 100644 (file)
@@ -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 */
index db4754c112d0186cf78d4dd7af3041caf903ff82..e9849cf904166034b83c2ffbf6e34ed56ded1a2a 100644 (file)
@@ -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);
        }
index 68e8f7a9b59558e6557c1060c6fcdd1855d5e9e4..5b557b8361a03cfb3184ce9dab5ba5dc19455bfa 100644 (file)
@@ -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);
 }
index 74360bf615e40e348fdb3bc675c670a3cbb31d95..059c25e5c6877f7fcd9d26bfc1cdcff476eb6f72 100644 (file)
@@ -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);
 }
index 36fab13a96814b8011857ad7fb695429b124197a..2051686148fb4fc55dda38486b4fcff13cd322a0 100644 (file)
@@ -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);
 }
index 883849b25d5461864020a7c25e620251c8f233a9..4d012fa880e907a5f60d2badf78072b015c00c4d 100644 (file)
@@ -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);
+}
index a898b4271fc791c41c7f65f6b80223238fbf5d43..a3b1925939d3b9266f0c43086f3322ae015a8282 100644 (file)
@@ -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;
+}
index 5a9e0aaf688b91986091bf753e06bddfa260b89b..eed6634a0bd6ff7e85212a65044891742600f0fc 100644 (file)
 #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);
 }
index 4e75e3b33a0bb8cd01bb804c2ab79ba9f725c0b1..315852747b1f82391154f158c06110822eb0a0b4 100644 (file)
@@ -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);
 }
index 8c996f08ca5503baf20d21ba308be9813d053721..5a8375596285d509a735395a0cbc41c49f7965ed 100644 (file)
@@ -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 */
index d01743ce95b6820e613f04faecbde058513e4e92..a2d6710a53c15f03e9d619c1d4a9eebd49343222 100644 (file)
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#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)) {