]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
requeuemail: isolate test and fix regression
authorBaptiste Daroussin <bapt@FreeBSD.org>
Mon, 6 Mar 2023 13:19:37 +0000 (14:19 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Mon, 6 Mar 2023 13:50:34 +0000 (14:50 +0100)
include/send_mail.h
src/mlmmj-send.c
src/send_mail.c
tests/mlmmj.c

index a1775b710c0b0b1e0d4661c5c39bf623f15c7b88..8daa623a7f89e250f7284aa51613099bdbf32a24 100644 (file)
@@ -43,3 +43,4 @@ int send_mail(int sockfd, struct mail *mail, int listfd, int ctrlfd, bool bounce
 int do_bouncemail(int listfd, int ctrlfd, const char *from);
 bool send_single_mail(struct mail *mail, struct ml *ml, bool bounce);
 void save_queue(const char *queuefilename, struct mail *mail);
+bool requeuemail(int listfd, int index, strlist *addrs, const char *addr);
index f15eb76aba8c40166040d312b2d6af4d446a0a9e..28c530fedf7fa38518d6dcbac738813b1d8c4885 100644 (file)
@@ -288,54 +288,6 @@ int send_mail_many_fd(int sockfd, struct mail *mail, int subfd,
        return 0;
 }
 
-int
-requeuemail(int listfd, int index, strlist *addrs)
-{
-       int addrfd;
-       char *dirname, *addrfilename;
-       
-       xasprintf(&dirname, "requeue/%d", index);
-       if(mkdirat(listfd, dirname, 0750) < 0 && errno != EEXIST) {
-               log_error(LOG_ARGS, "Could not mkdir(%s) for "
-                               "requeueing. Mail cannot "
-                               "be requeued.", dirname);
-               free(dirname);
-               return -1;
-       }
-       xasprintf(&addrfilename, "%s/subscribers");
-       free(dirname);
-       addrfd = openat(listfd, addrfilename, O_WRONLY|O_CREAT|O_APPEND,
-                       S_IRUSR|S_IWUSR);
-       if(addrfd < 0) {
-               log_error(LOG_ARGS, "Could not open %s",
-                               addrfilename);
-               free(addrfilename);
-               return -1;
-       }
-       free(addrfilename);
-       /* Dump the remaining addresses. We dump the remaining before
-        * we write the failing address to ensure the potential good
-        * ones will be tried first when mlmmj-maintd sends out mails
-        * that have been requeued. addrcount was so far we were */
-       char *addr = tll_pop_front(*addrs);
-       tll_foreach(*addrs, it) {
-               if(dprintf(addrfd, "%s\n", it->item) < 0) {
-                       log_error(LOG_ARGS, "Could not add [%s] "
-                                           "to requeue file", it->item);
-                       return -1;
-               }
-       }
-       if(dprintf(addrfd, "%s\n", addr) < 0) {
-               log_error(LOG_ARGS, "Could not add [%s] to requeue "
-                               "file", addr);
-               return -1;
-       }
-       free(addr);
-       close(addrfd);
-
-       return 0;
-}
-
 int send_mail_many_list(int sockfd, struct mail *mail, strlist *addrs,
                   const char *listaddr, const char *listdelim,
                   const char *archivefilename, int listfd, int ctrlfd)
@@ -343,14 +295,14 @@ int send_mail_many_list(int sockfd, struct mail *mail, strlist *addrs,
        int res = 0, status, index;
        char *bounceaddr, *addr;
 
-       tll_foreach(*addrs, it) {
+       while (tll_length(*addrs) > 0) {
+               addr = tll_pop_front(*addrs);
                bounceaddr = NULL;
-               addr = it->item;
                if(strchr(addr, '@') == NULL) {
                        errno = 0;
                        log_error(LOG_ARGS, "No @ in address, ignoring %s",
                                        addr);
-                       tll_remove_and_free(*addrs, it, free);
+                       free(addr);
                        continue;
                }
                if(gotsigterm && listaddr && archivefilename) {
@@ -358,7 +310,8 @@ int send_mail_many_list(int sockfd, struct mail *mail, strlist *addrs,
                        log_error(LOG_ARGS, "TERM signal received, "
                                                "shutting down.");
                        index = get_index_from_filename(archivefilename);
-                       status = requeuemail(listfd, index, addrs);
+                       status = requeuemail(listfd, index, addrs, addr);
+                       free(addr);
                        return status;
                }
                if (mail->from == NULL) {
@@ -372,10 +325,11 @@ int send_mail_many_list(int sockfd, struct mail *mail, strlist *addrs,
                if(res && listaddr && archivefilename) {
                        /* we failed, so save the addresses and bail */
                        index = get_index_from_filename(archivefilename);
-                       status = requeuemail(listfd, index, addrs);
+                       status = requeuemail(listfd, index, addrs, addr);
+                       free(addr);
                        return status;
                }
-               tll_remove_and_free(*addrs, it, free);
+               free(addr);
        }
        return 0;
 }
@@ -737,7 +691,7 @@ int main(int argc, char **argv)
                                                if(sendres)
                                                        requeuemail(ml.fd,
                                                                mindex,
-                                                               &stl);
+                                                               &stl, NULL);
                                        } else {
                                                mail.from = NULL;
                                                mail.replyto = NULL;
@@ -761,7 +715,7 @@ int main(int argc, char **argv)
                                mail.replyto = NULL;
                                sendres = send_mail_verp(sockfd, &stl, &mail, verp);
                                if(sendres)
-                                       requeuemail(ml.fd, mindex, &stl);
+                                       requeuemail(ml.fd, mindex, &stl, NULL);
                        } else {
                                mail.from = NULL;
                                mail.replyto = NULL;
index ab94255a66202f2f45d8cdf12892b3509dccdcb8..6151585f91dde4a7e4023497f1f81071182e2a90 100644 (file)
@@ -35,6 +35,7 @@
 #include "init_sockfd.h"
 #include "mlmmj.h"
 #include "strgen.h"
+#include "tllist.h"
 #include "xmalloc.h"
 #include "ctrlvalue.h"
 
@@ -410,3 +411,46 @@ send_single_mail(struct mail *mail, struct ml *ml, bool bounce)
        return (true);
 }
 
+bool
+requeuemail(int listfd, int index, strlist *addrs, const char *addr)
+{
+       int addrfd, dfd;
+       char *dirname;
+
+       if (addrs == NULL || tll_length(*addrs) == 0)
+               return (false);
+       xasprintf(&dirname, "requeue/%d", index);
+       if(mkdirat(listfd, dirname, 0750) < 0 && errno != EEXIST) {
+               log_error(LOG_ARGS, "Could not mkdir(%s) for "
+                               "requeueing. Mail cannot "
+                               "be requeued.", dirname);
+               free(dirname);
+               return (false);
+       }
+       dfd = openat(listfd, dirname, O_DIRECTORY);
+       free(dirname);
+       addrfd = openat(dfd, "subscribers", O_WRONLY|O_CREAT|O_APPEND,
+                       S_IRUSR|S_IWUSR);
+       if(addrfd < 0) {
+               log_error(LOG_ARGS, "Could not open %s/subscribers",
+                   dirname);
+               free(dirname);
+               close(dfd);
+               return (false);
+       }
+       free(dirname);
+       close(dfd);
+       /* Dump the remaining addresses. We dump the remaining before
+        * we write the failing address to ensure the potential good
+        * ones will be tried first when mlmmj-maintd sends out mails
+        * that have been requeued. addrcount was so far we were */
+       tll_foreach(*addrs, it) {
+               dprintf(addrfd, "%s\n", it->item);
+       }
+       if (addr != NULL)
+               dprintf(addrfd, "%s\n", addr);
+       close(addrfd);
+
+       return (true);
+}
+
index ca2a332845fb7b0a78ec2bc36ff0b55297da309f..4d4c12e9d557a681307f4e5280c6ef02e0e45747 100644 (file)
@@ -20,6 +20,7 @@
  * IN THE SOFTWARE.
  */
 
+#include "tllist.h"
 #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
 
 #include <sys/socket.h>
@@ -145,6 +146,7 @@ ATF_TC_WITHOUT_HEAD(generate_subconfirm);
 ATF_TC_WITHOUT_HEAD(confirm_sub);
 ATF_TC_WITHOUT_HEAD(listcontrol);
 ATF_TC_WITHOUT_HEAD(send_help);
+ATF_TC_WITHOUT_HEAD(requeuemail);
 
 ATF_TC_BODY(random_int, tc)
 {
@@ -2530,6 +2532,48 @@ ATF_TC_BODY(send_help, tc)
        }
 }
 
+ATF_TC_BODY(requeuemail, tc)
+{
+       strlist l = tll_init();
+       init_ml(true);
+       int dfd = open("list", O_DIRECTORY);
+
+       rmdir("list/requeue");
+       ATF_REQUIRE(!requeuemail(dfd, 1, NULL, NULL));
+       ATF_REQUIRE(!requeuemail(dfd, 1, NULL, NULL));
+       ATF_REQUIRE(!requeuemail(dfd, 1, &l, NULL));
+       tll_push_back(l, "test1");
+       rmdir("list/requeue");
+       ATF_REQUIRE(!requeuemail(dfd, 1, &l, NULL));
+       mkdir("list/requeue", 0755);
+       ATF_REQUIRE(requeuemail(dfd, 1, &l, NULL));
+       if (!atf_utils_file_exists("list/requeue/1/subscribers"))
+               atf_tc_fail("queue file does not exists");
+       if (!atf_utils_compare_file("list/requeue/1/subscribers", "test1\n")) {
+               atf_utils_cat_file("list/requeue/1/subscribers", "");
+               atf_tc_fail("Invalid queue content");
+       }
+       unlink("list/requeue/1/subscribers");
+       tll_push_back(l, "testhey");
+       tll_push_back(l, "test2");
+       ATF_REQUIRE(requeuemail(dfd, 1, &l, NULL));
+       if (!atf_utils_file_exists("list/requeue/1/subscribers"))
+               atf_tc_fail("queue file does not exists");
+       if (!atf_utils_compare_file("list/requeue/1/subscribers", "test1\ntesthey\ntest2\n")) {
+               atf_utils_cat_file("list/requeue/1/subscribers", "");
+               atf_tc_fail("Invalid queue content");
+       }
+       unlink("list/requeue/1/subscribers");
+       ATF_REQUIRE(requeuemail(dfd, 1, &l, "fail"));
+       if (!atf_utils_file_exists("list/requeue/1/subscribers"))
+               atf_tc_fail("queue file does not exists");
+       if (!atf_utils_compare_file("list/requeue/1/subscribers", "test1\ntesthey\ntest2\nfail\n")) {
+               atf_utils_cat_file("list/requeue/1/subscribers", ">");
+               atf_tc_fail("Invalid queue content (fail)");
+       }
+       close(dfd);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
        ATF_TP_ADD_TC(tp, random_int);
@@ -2611,6 +2655,7 @@ ATF_TP_ADD_TCS(tp)
        ATF_TP_ADD_TC(tp, confirm_sub);
        ATF_TP_ADD_TC(tp, listcontrol);
        ATF_TP_ADD_TC(tp, send_help);
+       ATF_TP_ADD_TC(tp, requeuemail);
 
        return (atf_no_error());
 }