From: Baptiste Daroussin Date: Wed, 15 Feb 2023 08:47:24 +0000 (+0100) Subject: send_single_mail: add tests and fix logic error X-Git-Tag: RELEASE_1_4_0b1~130 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0183ae6e1fa133e808ec35914f4fc0b1e3ea841;p=thirdparty%2Fmlmmj.git send_single_mail: add tests and fix logic error --- diff --git a/include/send_mail.h b/include/send_mail.h index 71bca7c5..a1775b71 100644 --- a/include/send_mail.h +++ b/include/send_mail.h @@ -42,3 +42,4 @@ int endsmtp(int *sockfd); 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); diff --git a/src/mlmmj-send.c b/src/mlmmj-send.c index b4a14035..fd1b2e33 100644 --- a/src/mlmmj-send.c +++ b/src/mlmmj-send.c @@ -70,35 +70,6 @@ void catch_sig_term(int sig __unused) gotsigterm = 1; } -static bool -save_file(const char *name, const char *ext, const char *content) -{ - char *tmpstr; - int fd; - - xasprintf(&tmpstr, "%s.%s", name, ext); - fd = open(tmpstr, O_WRONLY|O_CREAT|O_EXCL|O_SYNC, S_IRUSR|S_IWUSR); - if (fd == -1) { - free(tmpstr); - return (false); - } - dprintf(fd, "%s", content); - close(fd); - free(tmpstr); - return (true); -} - -static void -save_queue(const char *queuefilename, struct mail *mail) -{ - if (!save_file(queuefilename, "mailfrom", mail->from)) - return; - if (!save_file(queuefilename, "reciptto", mail->to)) - return; - if (mail->replyto != NULL) - save_file(queuefilename, "reply-to", mail->replyto); -} - int get_index_from_filename(const char *filename) { diff --git a/src/send_mail.c b/src/send_mail.c index 9fb6738a..577f0c68 100644 --- a/src/send_mail.c +++ b/src/send_mail.c @@ -21,8 +21,11 @@ * IN THE SOFTWARE. */ +#include + #include #include +#include #include "checkwait_smtpreply.h" #include "mail-functions.h" @@ -253,6 +256,12 @@ send_mail(int sockfd, struct mail *mail, int listfd, int ctrlfd, bool bounce) return 0; } + if (mail->fp == NULL) { + errno = 0; + log_error(LOG_ARGS, "No mail to send, ignoring"); + return 0; + } + retval = write_mail_from(sockfd, mail->from, ""); if(retval) { log_error(LOG_ARGS, "Could not write MAIL FROM\n"); @@ -356,6 +365,35 @@ newsmtp(struct ml *ml) return (sockfd); } +static bool +save_file(const char *name, const char *ext, const char *content) +{ + char *tmpstr; + int fd; + + xasprintf(&tmpstr, "%s.%s", name, ext); + fd = open(tmpstr, O_WRONLY|O_CREAT|O_EXCL|O_SYNC, S_IRUSR|S_IWUSR); + if (fd == -1) { + free(tmpstr); + return (false); + } + dprintf(fd, "%s", content); + close(fd); + free(tmpstr); + return (true); +} + +void +save_queue(const char *queuefilename, struct mail *mail) +{ + if (!save_file(queuefilename, "mailfrom", mail->from)) + return; + if (!save_file(queuefilename, "reciptto", mail->to)) + return; + if (mail->replyto != NULL) + save_file(queuefilename, "reply-to", mail->replyto); +} + bool send_single_mail(struct mail *mail, struct ml *ml, bool bounce) { @@ -364,10 +402,11 @@ send_single_mail(struct mail *mail, struct ml *ml, bool bounce) sockfd = newsmtp(ml); if (sockfd == -1) return (false); - if (!send_mail(sockfd, mail, ml->fd, ml->ctrlfd, bounce)) { + if (send_mail(sockfd, mail, ml->fd, ml->ctrlfd, bounce) != 0) { endsmtp(&sockfd); return (false); } endsmtp(&sockfd); return (true); } + diff --git a/tests/mlmmj.c b/tests/mlmmj.c index d14903d9..7f82b5c5 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -137,6 +137,8 @@ ATF_TC_WITHOUT_HEAD(list_subs); ATF_TC_WITHOUT_HEAD(notify_sub); ATF_TC_WITHOUT_HEAD(get_processed_text_line); ATF_TC_WITHOUT_HEAD(newsmtp); +ATF_TC_WITHOUT_HEAD(save_queue); +ATF_TC_WITHOUT_HEAD(send_single_mail); ATF_TC_BODY(random_int, tc) { @@ -2066,6 +2068,132 @@ ATF_TC_BODY(newsmtp, tc) atf_utils_wait(p, 0, "EHLO heloname\r\nQUIT\r\n", ""); } +ATF_TC_BODY(save_queue, tc) +{ + struct mail mail = {}; + mail.to = "plop"; + mail.from = "bla"; + + save_queue("myfile", &mail); + if (!atf_utils_file_exists("myfile.reciptto")) + atf_tc_fail("myfile.receiptto does not exists"); + if (!atf_utils_compare_file("myfile.reciptto", "plop")) + atf_tc_fail("myfile.reciptto: invalid content"); + if (!atf_utils_file_exists("myfile.mailfrom")) + atf_tc_fail("myfile.receiptto does not exists"); + if (!atf_utils_compare_file("myfile.mailfrom", "bla")) + atf_tc_fail("myfile.mailfrom: invalid content"); + if (atf_utils_file_exists("myfile.reply-to")) + atf_tc_fail("myfile.reply-to should not exists"); + + mail.replyto = "hey"; + save_queue("myfile2", &mail); + if (!atf_utils_file_exists("myfile2.reciptto")) + atf_tc_fail("myfile2.receiptto does not exists"); + if (!atf_utils_compare_file("myfile2.reciptto", "plop")) + atf_tc_fail("myfile2.recriptto: invalid content"); + if (!atf_utils_file_exists("myfile2.mailfrom")) + atf_tc_fail("myfile2.receiptto does not exists"); + if (!atf_utils_compare_file("myfile2.mailfrom", "bla")) + atf_tc_fail("myfile2.mailfrom: invalid content"); + if (!atf_utils_file_exists("myfile2.reply-to")) + atf_tc_fail("myfile2.reply-to does not exists"); + if (!atf_utils_compare_file("myfile2.reply-to", "hey")) + atf_tc_fail("myfile2.reply-to: invalid content"); + + unlink("myfile2.reply-to"); + unlink("myfile2.mailfrom"); + /* the files exists reciptto exist so it should fail and stop there */ + save_queue("myfile2", &mail); + if (!atf_utils_file_exists("myfile2.mailfrom")) + atf_tc_fail("myfile2.mailfrom does not exists but should have been created"); + if (atf_utils_file_exists("myfile2.reply-to")) + atf_tc_fail("myfile2.reply-to should not exists"); + /* will return in the first loop */ + unlink("myfile2.reciptto"); + save_queue("myfile2", &mail); + if (atf_utils_file_exists("myfile2.reciptto")) + atf_tc_fail("myfile2.reciptto should not exists"); + if (atf_utils_file_exists("myfile2.reply-to")) + atf_tc_fail("myfile2.reply-to should not exists"); +} + +ATF_TC_BODY(send_single_mail, tc) +{ + init_ml(true); + struct ml ml; + ml_init(&ml); + ml.dir = "list"; + struct mail mail = {}; + ATF_REQUIRE_MSG(ml_open(&ml, false), "impossible to open the mailing list"); + atf_utils_create_file("list/control/smtpport", "25678"); + int smtppipe[2]; + ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0); + pid_t p = atf_utils_fork(); + if (p == 0) { + int s = fakesmtp(smtppipe[1]); + int c; + struct sockaddr_in cl; + socklen_t clsize = 0; + c = accept(s, (struct sockaddr *) &cl, &clsize); + if (c == -1) + err(5, "accept()"); + dprintf(c, "220 me fake smtp\n"); + const char *replies[] = { + "250-hostname.net\n" + "250-PIPELINEING\n" + "250-SIZE 20480000\n" + "250-ETRN\n" + "250-STARTTLS\n" + "250-ENHANCEDSTATUSCODES\n" + "250-8BITMIME\n" + "250-DSN\n" + "250-SMTPUTF8\n" + "250 CHUNKING\n", + "250 2.1.0 OK\n", + "250 2.1.0 OK\n", + "350 2.1.0 OK\n", + NULL, + NULL, + NULL, + NULL, + NULL, + "250 2.1.0 OK\n", + "221 2.0.0 bye\n", + }; + read_print_reply(c, replies, NELEM(replies)); + exit(0); + } + close(smtppipe[1]); + atf_utils_readline(smtppipe[0]); + atf_utils_create_file("list/control/smtphelo", "heloname"); + atf_utils_create_file("list/control/relayhost", "127.0.0.1"); + atf_utils_create_file("mymail.txt", "headers\n\nbody\n"); + mail.to = "plop@meh"; + mail.from = "test@meh"; + mail.fp = fopen("mymail.txt", "r"); + mail.addtohdr = true; + ATF_REQUIRE(send_single_mail(&mail, &ml, false)); + atf_utils_wait(p, 0, "save:out.txt", ""); + const char *output = "" + "EHLO heloname\r\n" + "MAIL FROM:\r\n" + "RCPT TO:\r\n" + "DATA\r\nheaders\r\n" + "To: plop@meh\r\n" + "\r\n" + "body\r\n" + "\r\n" + ".\r\n" + "QUIT\r\n"; + if (!atf_utils_compare_file("out.txt", output)) { + printf("Invalid file expected: \n===\n%s\n===\ngot:\n===\n", output); + atf_utils_cat_file("out.txt", ">"); + printf("\n===\n"); + atf_tc_fail("Invalid output"); + } +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, random_int); @@ -2140,6 +2268,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, notify_sub); ATF_TP_ADD_TC(tp, get_processed_text_line); ATF_TP_ADD_TC(tp, newsmtp); + ATF_TP_ADD_TC(tp, save_queue); + ATF_TP_ADD_TC(tp, send_single_mail); return (atf_no_error()); }