From: Baptiste Daroussin Date: Mon, 6 Mar 2023 13:19:37 +0000 (+0100) Subject: requeuemail: isolate test and fix regression X-Git-Tag: RELEASE_1_4_0b1~95 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8c20488ded8b64b9b13e569c0a190b883928ad31;p=thirdparty%2Fmlmmj.git requeuemail: isolate test and fix regression --- diff --git a/include/send_mail.h b/include/send_mail.h index a1775b71..8daa623a 100644 --- a/include/send_mail.h +++ b/include/send_mail.h @@ -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); diff --git a/src/mlmmj-send.c b/src/mlmmj-send.c index f15eb76a..28c530fe 100644 --- a/src/mlmmj-send.c +++ b/src/mlmmj-send.c @@ -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; diff --git a/src/send_mail.c b/src/send_mail.c index ab94255a..6151585f 100644 --- a/src/send_mail.c +++ b/src/send_mail.c @@ -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); +} + diff --git a/tests/mlmmj.c b/tests/mlmmj.c index ca2a3328..4d4c12e9 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -20,6 +20,7 @@ * IN THE SOFTWARE. */ +#include "tllist.h" #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" #include @@ -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()); }