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);
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)
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) {
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) {
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;
}
if(sendres)
requeuemail(ml.fd,
mindex,
- &stl);
+ &stl, NULL);
} else {
mail.from = NULL;
mail.replyto = NULL;
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;
#include "init_sockfd.h"
#include "mlmmj.h"
#include "strgen.h"
+#include "tllist.h"
#include "xmalloc.h"
#include "ctrlvalue.h"
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);
+}
+
* IN THE SOFTWARE.
*/
+#include "tllist.h"
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <sys/socket.h>
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)
{
}
}
+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);
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());
}