]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
send_single_mail: add tests and fix logic error
authorBaptiste Daroussin <bapt@FreeBSD.org>
Wed, 15 Feb 2023 08:47:24 +0000 (09:47 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Wed, 15 Feb 2023 08:47:24 +0000 (09:47 +0100)
include/send_mail.h
src/mlmmj-send.c
src/send_mail.c
tests/mlmmj.c

index 71bca7c51c416688f4cf3d30ff739e59bc4a7c52..a1775b710c0b0b1e0d4661c5c39bf623f15c7b88 100644 (file)
@@ -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);
index b4a1403531ca648c099e4ac82c147786395c3b96..fd1b2e3377b986948bb6bd409a0a8f9124678ac6 100644 (file)
@@ -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)
 {
index 9fb6738a5874834a086c14066ce33f64940741bc..577f0c6817d1caff366841aeaac10a565842f8ca 100644 (file)
  * IN THE SOFTWARE.
  */
 
+#include <sys/stat.h>
+
 #include <stdio.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #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);
 }
+
index d14903d9ae218752df770e4906d2705ab022dc59..7f82b5c50a67aaaf5ede0a80496362ed23525277 100644 (file)
@@ -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:<test@meh>\r\n"
+               "RCPT TO:<plop@meh>\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());
 }