]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
probe: send message-id is possibel in probe emails
authorBaptiste Daroussin <bapt@FreeBSD.org>
Fri, 13 Jun 2025 13:33:57 +0000 (15:33 +0200)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Fri, 13 Jun 2025 13:35:07 +0000 (15:35 +0200)
When sending the probe emails, tries to add the message-id in the
message, to help users figuring finding the wrong email

Fixes: #8

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

index 456b0e88a8df1d32b8ddd82dbc969cf4424ea4d4..34f815f6d01d59a5bde007053187130dec36da1a 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-2024 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2023-2025 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
@@ -48,8 +48,10 @@ 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);
+file_lines_state *init_file_lines_data(int fd, char truncate, void *data);
 void rewind_file_lines(void *state);
 const char *get_file_line(void *state);
+const char *get_msgid_line(void *state);
 void finish_file_lines(file_lines_state *s);
 
 char *substitute(const char *line, int listfd, int ctrlfd, text *txt);
index eb158c60fa9faa25639615fb55cc55f1ea3139b3..d3016ced86f518bc2b067eb73e4cbbf152935926 100644 (file)
@@ -84,9 +84,9 @@ send_probe(struct ml *ml, const char *addr)
        txt = open_text(ml->fd, "probe", NULL, NULL, NULL, "bounce-probe");
        MY_ASSERT(txt);
        register_default_unformatted(txt, ml);
-       fls = init_file_lines_fd(openat(bfd, addr, O_RDONLY), ':');
+       fls = init_file_lines_data(openat(bfd, addr, O_RDONLY), ':', ml);
        register_formatted(txt, "bouncenumbers",
-                       rewind_file_lines, get_file_line, fls);
+                       rewind_file_lines, get_msgid_line, fls);
        queuefilename = prepstdreply(txt, ml, "$listowner$", myaddr, NULL);
        MY_ASSERT(queuefilename);
        close_text(txt);
index b14ecb1e7719ce66628b2a9cb0bb1d29bb57d1e7..7b340046601c58c1cde808b700f677fcd289d5af 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj.dk>
  * Copyright (C) 2007 Morten K. Poulsen <morten at afdelingp.dk>
  * Copyright (C) 2011 Ben Schmidt <mail_ben_schmidt at yahoo.com.au>
- * Copyright (C) 2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2023-2025 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
@@ -43,6 +43,7 @@
 #include "mlmmj.h"
 #include "unistr.h"
 #include "xstring.h"
+#include "do_all_the_voodoo_here.h"
 
 struct substitution {
        char *token;
@@ -136,6 +137,8 @@ struct file_lines_state {
        char truncate;
        char *line;
        size_t linecap;
+       char *formatted_str;
+       void *data;
 };
 
 
@@ -211,6 +214,17 @@ file_lines_state
        return (s);
 }
 
+file_lines_state *
+init_file_lines_data(int fd, char truncate, void *data)
+{
+       file_lines_state *s;
+
+       s = init_file_lines_fd(fd, truncate);
+       if (s == NULL)
+               return (NULL);
+       s->data = data;
+       return (s);
+}
 
 void rewind_file_lines(void *state)
 {
@@ -243,10 +257,44 @@ const char *get_file_line(void *state)
        return s->line;
 }
 
+const char *
+get_msgid_line(void *state)
+{
+       file_lines_state *s = (file_lines_state *)state;
+       const char *id = get_file_line(state);
+       if (id == NULL)
+               return (NULL);
+       if (s->data == NULL) {
+               return (id);
+       }
+       struct ml *m = (struct ml *)s->data;
+       struct mailhdr readhdrs[] = {
+               { "Message-ID", 0, NULL },
+               { NULL, 0, NULL }
+       };
+       int archive_fd = openat(m->fd, "archive", O_DIRECTORY|O_RDONLY);
+       if (archive_fd == -1)
+               return (id);
+       int msgfd = openat(archive_fd, id, O_RDONLY);
+       close(archive_fd);
+       if (msgfd == -1)
+               return (id);
+       FILE *f = fdopen(msgfd, "r");
+       scan_headers(f, readhdrs, NULL, NULL);
+       fclose(f);
+       if (readhdrs[0].valuecount == 0)
+               return (id);
+       free(s->formatted_str);
+       xasprintf(&s->formatted_str, "%s, %s%s",
+           id, readhdrs[0].token, readhdrs[0].values[0]);
+       return (s->formatted_str);
+}
+
 void finish_file_lines(file_lines_state *s)
 {
        if (s == NULL) return;
-       if (s->line != NULL) free(s->line);
+       free(s->line);
+       free(s->formatted_str);
        if (s->fp != NULL) fclose(s->fp);
        if (s->filename != NULL) free(s->filename);
        free(s);
index 1cb59bf0f4d31bfeefb5af09f422c079e1a2b0ac..9c74d3189e69c5f7bdfa640054b47750fb37ab12 100644 (file)
@@ -42,6 +42,7 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <errno.h>
+#include <signal.h>
 
 #include "atf-c/macros.h"
 #include "atf-c/utils.h"
@@ -158,7 +159,10 @@ 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_no_probefile);
+ATF_TC_WITHOUT_HEAD(send_probe_arobase);
 ATF_TC_WITHOUT_HEAD(send_probe);
+ATF_TC_WITHOUT_HEAD(send_probe_archive);
 ATF_TC_WITHOUT_HEAD(parse_content_type);
 ATF_TC_WITHOUT_HEAD(find_in_list);
 ATF_TC_WITHOUT_HEAD(do_access);
@@ -2817,7 +2821,7 @@ ATF_TC_BODY(mod_get_addr_type, tc)
        atf_utils_wait(p, 1, "", "");
 }
 
-ATF_TC_BODY(send_probe, tc)
+ATF_TC_BODY(send_probe_no_probefile, tc)
 {
        init_ml(true);
        struct ml ml;
@@ -2844,19 +2848,79 @@ ATF_TC_BODY(send_probe, tc)
                atf_utils_cat_file("mailout.txt", "");
                atf_tc_fail("invalid file");
        }
+}
 
-       p = atf_utils_fork();
+ATF_TC_BODY(send_probe_arobase, tc)
+{
+       init_ml(true);
+       struct ml ml;
+       ml_init(&ml);
+       ml.dir = "list";
+       ml_open(&ml, false);
+       setup_listtext(tc);
+       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 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_TC_BODY(send_probe, tc)
+{
+       init_ml(true);
+       struct ml ml;
+       ml_init(&ml);
+       ml.dir = "list";
+       ml_open(&ml, false);
+       setup_listtext(tc);
+       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]);
-       p = atf_utils_fork();
+
+       atf_utils_create_file("list/bounce/bapt=freebsd.org", "1234:blabla\n32:qftgd\n");
+       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("1234\r", "mailout.txt")) {
+               atf_utils_cat_file("mailout.txt", ">");
+               atf_tc_fail("invalid mail sent");
+       }
+}
+
+ATF_TC_BODY(send_probe_archive, tc)
+{
+       init_ml(true);
+       struct ml ml;
+       ml_init(&ml);
+       ml.dir = "list";
+       ml_open(&ml, false);
+       setup_listtext(tc);
+       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]);
+
+       atf_utils_create_file("list/bounce/bapt=freebsd.org", "1234:blabla\n21:hey\n32:ertt\n");
+       atf_utils_create_file("list/archive/1234", "From: bob@test\nMessage-ID: <msgid>\nX-None: bla\n\nContent\n");
+       atf_utils_create_file("list/archive/21", "From: bob@test\nMessage-ID: <msgid2>\nX-None: bla\n\nContent\n");
+       pid_t p = atf_utils_fork();
        if (p == 0) {
                if (send_probe(&ml, "bapt=freebsd.org"))
                        exit(0);
@@ -2864,7 +2928,16 @@ ATF_TC_BODY(send_probe, tc)
        }
        atf_utils_wait(p2, 0, "save:mailout.txt", "");
        atf_utils_wait(p, 0, "", "");
-       if (!atf_utils_grep_file("1234", "mailout.txt")) {
+
+       if (!atf_utils_grep_file("- 1234, Message-ID: <msgid>\r", "mailout.txt")) {
+               atf_utils_cat_file("mailout.txt", ">");
+               atf_tc_fail("invalid mail sent");
+       }
+       if (!atf_utils_grep_file("- 21, Message-ID: <msgid2>\r", "mailout.txt")) {
+               atf_utils_cat_file("mailout.txt", ">");
+               atf_tc_fail("invalid mail sent");
+       }
+       if (!atf_utils_grep_file("- 32\r", "mailout.txt")) {
                atf_utils_cat_file("mailout.txt", ">");
                atf_tc_fail("invalid mail sent");
        }
@@ -3094,7 +3167,10 @@ 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_no_probefile);
+       ATF_TP_ADD_TC(tp, send_probe_arobase);
        ATF_TP_ADD_TC(tp, send_probe);
+       ATF_TP_ADD_TC(tp, send_probe_archive);
        ATF_TP_ADD_TC(tp, parse_content_type);
        ATF_TP_ADD_TC(tp, find_in_list);
        ATF_TP_ADD_TC(tp, do_access);