]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
probes: fix a regression causing the probes not to sent the bounce numbers
authorBaptiste Daroussin <bapt@FreeBSD.org>
Thu, 11 Jan 2024 16:44:42 +0000 (17:44 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Thu, 11 Jan 2024 16:44:42 +0000 (17:44 +0100)
move the code sending the probe into a reusable function for it to be
testable, add a unit test which checks the probes properly contains
what is expected.

include/mlmmj.h
include/prepstdreply.h
src/mlmmj-bounce.c
src/mlmmj.c
src/prepstdreply.c
tests/mlmmj.c

index 6d6ed8c5631458e6076dd3019e25fc47d0171fc7..a45b76aed21e4df2872a8b3e02e5e3360b00cb91 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2002, 2003, 2004 Mads Martin Joergensen <mmj at mmj.dk>
- * Copyright (C) 2022-2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2022-2024 Baptiste Daroussin <bapt@FreeBSD.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -134,6 +134,7 @@ int open_listdir(const char *listdir, bool usercheck);
 void ml_init(struct ml *ml);
 bool ml_open(struct ml *ml, bool checkuser);
 void ml_close(struct ml *ml);
+bool send_probe(struct ml *ml, const char *addr);
 
 #define MY_ASSERT(expression) if (!(expression)) { \
                        errno = 0; \
index 4d15c8b077d1fd664d17427c3bce9f8878903fa4..456b0e88a8df1d32b8ddd82dbc969cf4424ea4d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj.dk>
  * Copyright (C) 2011 Ben Schmidt <mail_ben_schmidt at yahoo.com.au>
- * Copyright (C) 2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2023-2024 Baptiste Daroussin <bapt@FreeBSD.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -47,6 +47,7 @@ const char *get_memory_line(void *state);
 void finish_memory_lines(memory_lines_state *s);
 
 file_lines_state *init_file_lines(const char *filename, char truncate);
+file_lines_state *init_file_lines_fd(int fd, char truncate);
 void rewind_file_lines(void *state);
 const char *get_file_line(void *state);
 void finish_file_lines(file_lines_state *s);
index aa5be75339a94e3a0c95326c2ee69d302ce20c82..49399f813daff6cea2dc2474386dd1159efd62bc 100644 (file)
 #include "utils.h"
 #include "send_mail.h"
 
-static void
-unlink_bounce(struct ml *ml, const char *to)
+void
+do_probe(struct ml *ml, const char *addr)
 {
-       char *tmpstr, *a, *probefile;
-
-       /* error, so remove the probefile */
-       tmpstr = xstrdup(to);
-       a = strchr(tmpstr, '@');
-       MY_ASSERT(a);
-       *a = '=';
-       xasprintf(&probefile, "bounce/%s-probe", tmpstr);
-       unlinkat(ml->fd, probefile, 0);
-       free(probefile);
-       free(tmpstr);
-}
-
-void do_probe(struct ml *ml, const char *addr)
-{
-       text *txt;
-       file_lines_state *fls;
-       char *myaddr, *from, *a, *queuefilename;
-       char *probefile;
-       int fd;
-       time_t t;
-       struct mail mail = { 0 };
-
-       myaddr = lowercase(addr);
-
-       gen_addr_cookie(from, ml, "bounces-probe-", myaddr)
-
-       a = strrchr(myaddr, '=');
-       if (!a) {
-               free(myaddr);
-               free(from);
-               log_error(LOG_ARGS, "do_probe(): malformed address");
-               exit(EXIT_FAILURE);
-
-       }
-       *a = '@';
-
-       txt = open_text(ml->fd, "probe", NULL, NULL, NULL, "bounce-probe");
-       MY_ASSERT(txt);
-       register_default_unformatted(txt, ml);
-       register_unformatted(txt, "bouncenumbers", "%bouncenumbers%"); /* DEPRECATED */
-       fls = init_file_lines(addr, ':');
-       register_formatted(txt, "bouncenumbers",
-                       rewind_file_lines, get_file_line, fls);
-       queuefilename = prepstdreply(txt, ml, "$listowner$", myaddr, NULL);
-       MY_ASSERT(queuefilename);
-       close_text(txt);
-
-       finish_file_lines(fls);
-
-       xasprintf(&probefile, "bounce/%s-probe", addr);
-       t = time(NULL);
-       fd = openat(ml->fd, probefile, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
-       if(fd < 0)
-               log_error(LOG_ARGS, "Could not open %s", probefile);
-       else
-               if (dprintf(fd, "%ld", (long int)t) < 0)
-                       log_error(LOG_ARGS, "Could not write time in probe");
-       free(probefile);
-
-       mail.to = myaddr;
-       mail.from = from;
-       mail.fp = fopen(queuefilename, "r");
-       if (!send_single_mail(&mail, ml, false)) {
-               unlink_bounce(ml, myaddr);
-               exit(EXIT_FAILURE);
-       }
-       fclose(mail.fp);
-       exit(EXIT_SUCCESS);
+       if (send_probe(ml, addr))
+               exit(EXIT_SUCCESS);
+       exit(EXIT_FAILURE);
 }
 
 static void print_help(const char *prg)
index 2d5b65b7005ab18c4e90d7d6fe8181767e944701..3711aaa23e5eaed31ed7f14409c0574cbff4f92f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2021-2024 Baptiste Daroussin <bapt@FreeBSD.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -35,6 +35,7 @@
 #include <err.h>
 
 #include "getlistdelim.h"
+#include "send_mail.h"
 #include "mlmmj.h"
 #include "utils.h"
 #include "log_error.h"
 #include "gethdrline.h"
 #include "mygetline.h"
 #include "subscriberfuncs.h"
+#include "prepstdreply.h"
 #include "find_email_adr.h"
 #include "strgen.h"
 #include "ctrlvalue.h"
 
+bool
+send_probe(struct ml *ml, const char *addr)
+{
+       text *txt;
+       file_lines_state *fls;
+       char *myaddr, *from, *a, *queuefilename;
+       char *probefile;
+       int fd, bfd;
+       time_t t;
+       struct mail mail = { 0 };
+
+       myaddr = lowercase(addr);
+
+       gen_addr_cookie(from, ml, "bounces-probe-", myaddr)
+
+       a = strrchr(myaddr, '=');
+       if (!a) {
+               free(myaddr);
+               free(from);
+               log_error(LOG_ARGS, "do_probe(): malformed address");
+               return (false);
+       }
+       *a = '@';
+       bfd = openat(ml->fd, "bounce", O_DIRECTORY);
+       if (bfd == -1) {
+               free(myaddr);
+               free(from);
+               log_error(LOG_ARGS, "impossible to open bounce directory");
+               return (false);
+       }
+
+       txt = open_text(ml->fd, "probe", NULL, NULL, NULL, "bounce-probe");
+       MY_ASSERT(txt);
+       register_default_unformatted(txt, ml);
+       register_unformatted(txt, "bouncenumbers", "%bouncenumbers%"); /* DEPRECATED */
+       fls = init_file_lines_fd(openat(bfd, addr, O_RDONLY), ':');
+       register_formatted(txt, "bouncenumbers",
+                       rewind_file_lines, get_file_line, fls);
+       queuefilename = prepstdreply(txt, ml, "$listowner$", myaddr, NULL);
+       MY_ASSERT(queuefilename);
+       close_text(txt);
+       finish_file_lines(fls);
+
+       xasprintf(&probefile, "%s-probe", addr);
+       t = time(NULL);
+       fd = openat(bfd, probefile, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
+       if(fd < 0)
+               log_error(LOG_ARGS, "Could not open %s", probefile);
+       else
+               if (dprintf(fd, "%ld", (long int)t) < 0)
+                       log_error(LOG_ARGS, "Could not write time in probe");
+
+       mail.to = myaddr;
+       mail.from = from;
+       mail.fp = fopen(queuefilename, "r");
+       if (!send_single_mail(&mail, ml, false)) {
+               unlinkat(bfd, probefile, 0);
+               free(probefile);
+               return (false);
+       }
+       free(probefile);
+       fclose(mail.fp);
+       return (true);
+}
+
+
 bool
 parse_lastdigest(char *line, long *lastindex, time_t *lasttime,
      long *lastissue, const char **errstr)
index 04fc131eef13d194d72099105fb9218e777d04b7..8081e13d15a585592def85d9956c726767a1d32a 100644 (file)
@@ -189,7 +189,8 @@ finish_memory_lines(memory_lines_state *s)
 }
 
 
-file_lines_state *init_file_lines(const char *filename, char truncate)
+file_lines_state *
+init_file_lines(const char *filename, char truncate)
 {
        file_lines_state *s = xcalloc(1, sizeof(file_lines_state));
        s->filename = xstrdup(filename);
@@ -197,6 +198,19 @@ file_lines_state *init_file_lines(const char *filename, char truncate)
        return s;
 }
 
+file_lines_state
+*init_file_lines_fd(int fd, char truncate)
+{
+       file_lines_state *s;
+
+       if (fd == -1)
+               return (NULL);
+       s = xcalloc(1, sizeof(file_lines_state));
+       s->fp = fdopen(fd, "r");
+       s->truncate = truncate;
+       return (s);
+}
+
 
 void rewind_file_lines(void *state)
 {
index b95325833b44217c9384fa03811646a281456aa5..4e0b95e4ee128699232a11a0a7507206399301d3 100644 (file)
@@ -152,6 +152,7 @@ ATF_TC_WITHOUT_HEAD(requeuemail);
 ATF_TC_WITHOUT_HEAD(gethdrline);
 ATF_TC_WITHOUT_HEAD(readlf);
 ATF_TC_WITHOUT_HEAD(mod_get_addr_type);
+ATF_TC_WITHOUT_HEAD(send_probe);
 
 ATF_TC_BODY(random_int, tc)
 {
@@ -2797,6 +2798,64 @@ ATF_TC_BODY(mod_get_addr_type, tc)
        atf_utils_wait(p, 1, "", "");
 }
 
+ATF_TC_BODY(send_probe, tc)
+{
+       char *dir;
+       init_ml(true);
+       struct ml ml;
+       ml_init(&ml);
+       ml.dir = "list";
+       ml_open(&ml, false);
+       rmdir("list/text");
+       xasprintf(&dir, "%s/../listtexts/en",
+           atf_tc_get_config_var(tc, "srcdir"));
+
+       symlink(dir, "list/text");
+       atf_utils_create_file("list/control/smtpport", "25678");
+       atf_utils_create_file("list/control/smtphelo", "heloname");
+       int smtppipe[2];
+       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
+       pid_t p2 = single_mail_reception(smtppipe[1]);
+       atf_utils_readline(smtppipe[0]);
+       pid_t p = atf_utils_fork();
+       if (p == 0) {
+               if (send_probe(&ml, "bapt=freebsd.org"))
+                       exit(0);
+               exit(1);
+       }
+       atf_utils_wait(p2, 0, "save:mailout.txt", "");
+       atf_utils_wait(p, 0, "", "");
+
+       if (!atf_utils_grep_file("Some messages to you could not be delivered", "mailout.txt")) {
+               atf_utils_cat_file("mailout.txt", "");
+               atf_tc_fail("invalid file");
+       }
+
+       p = atf_utils_fork();
+       if (p == 0) {
+               if (send_probe(&ml, "bapt@freebsd.org"))
+                       exit(0);
+               exit(1);
+       }
+       atf_utils_wait(p, 1, "", "");
+
+       atf_utils_create_file("list/bounce/bapt=freebsd.org", "1234:blabla\n");
+       p2 = single_mail_reception(smtppipe[1]);
+       atf_utils_readline(smtppipe[0]);
+       p = atf_utils_fork();
+       if (p == 0) {
+               if (send_probe(&ml, "bapt=freebsd.org"))
+                       exit(0);
+               exit(1);
+       }
+       atf_utils_wait(p2, 0, "save:mailout.txt", "");
+       atf_utils_wait(p, 0, "", "");
+       if (!atf_utils_grep_file("1234", "mailout.txt")) {
+               atf_utils_cat_file("mailout.txt", ">");
+               atf_tc_fail("invalid mail sent");
+       }
+}
+
 ATF_TP_ADD_TCS(tp)
 {
        ATF_TP_ADD_TC(tp, random_int);
@@ -2883,6 +2942,7 @@ ATF_TP_ADD_TCS(tp)
        ATF_TP_ADD_TC(tp, gethdrline);
        ATF_TP_ADD_TC(tp, readlf);
        ATF_TP_ADD_TC(tp, mod_get_addr_type);
+       ATF_TP_ADD_TC(tp, send_probe);
 
        return (atf_no_error());
 }