From 59181abed498a8832cb0f7a6f0fcc4cb88889ac6 Mon Sep 17 00:00:00 2001 From: Erwan MAS Date: Sat, 7 Jun 2025 14:37:00 -0400 Subject: [PATCH] customheaders allow substitution on variable $posteraddr$ --- ChangeLog | 3 + include/wrappers.h | 1 + src/do_all_the_voodoo_here.c | 101 +++++++++++------ src/dumpfd2fd.c | 28 +++++ tests/mlmmj-receive.in | 209 ++++++++++++++++++++++++++++++++++- 5 files changed, 307 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 88fb175c..270fb715 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +master + o customheaeders allow now substitution of $posteraddr$ (Erwan Mas) + o Fix portability issue on Hurd (Erwan Mas) 1.5.2 o Plenty of portability fixes 1.5.1 diff --git a/include/wrappers.h b/include/wrappers.h index 8567c97e..9b585cdb 100644 --- a/include/wrappers.h +++ b/include/wrappers.h @@ -30,5 +30,6 @@ ssize_t readn(int fd, void *vptr, size_t n); int random_int(void); int dumpfd2fd(int infd, int outfd); int copy_file(int infd, int outfd, size_t bufsiz); +int process_headers_fd(int infd, int outfd,const char *from); #endif /* WRAPPERS_H */ diff --git a/src/do_all_the_voodoo_here.c b/src/do_all_the_voodoo_here.c index 3ba56da7..d6f6e12b 100644 --- a/src/do_all_the_voodoo_here.c +++ b/src/do_all_the_voodoo_here.c @@ -34,6 +34,7 @@ #include "do_all_the_voodoo_here.h" #include "log_error.h" #include "wrappers.h" +#include "find_email_adr.h" bool findit(const char *line, const strlist *headers) @@ -49,6 +50,7 @@ findit(const char *line, const strlist *headers) return false; } +/* read line and populate a struct to save a list important header see mlmmj-process.c:254 and mlmmj.h:97 */ void getinfo(const char *line, struct mailhdr *readhdrs) { int i = 0; @@ -73,23 +75,60 @@ int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, strlist *allhdrs, const char *prefix, int replyto) { char *hdrline, *unfolded, *unqp; + strlist allunfoldeds = tll_init(); + char *posteraddr = NULL; bool hdrsadded = false; bool subject_present = false; FILE *f = fdopen(dup(infd), "r"); + /* scan all headers and populate readhdrs , allhdrs , allunfoldeds */ + for(;;) { + /* hdrline contains the header in one line and unfolded contains the original data */ hdrline = gethdrline(f, &unfolded); + /* end of headers */ + if(hdrline == NULL) { + break; + } + + /* Do we want info from hdrs? Get it before it's gone */ + if(readhdrs) + getinfo(hdrline, readhdrs); + + /* Snatch a copy of the header */ + tll_push_back(*allhdrs, xstrdup(hdrline)); + + /* Snatch a copy of unfolded */ + tll_push_back(allunfoldeds, xstrdup(unfolded)); + + free(hdrline); + free(unfolded); + } + /* if we have custom headers , extract posteraddr from current header */ + if(hdrfd >= 0) { + strlist fromemails = tll_init(); + if ( readhdrs[0].valuecount == 1 ) { + find_email_adr(readhdrs[0].values[0], &fromemails); + posteraddr = tll_front(fromemails); + } + } + /* scan all headers from allhdrs , and do the real things */ + tll_foreach(*allhdrs, a_header ) { + + /* hdrline contains the unfolded value of the header and unfolded contains the original data */ + hdrline=a_header->item ; + unfolded=tll_pop_front(allunfoldeds) ; + /* add extra headers before MIME* headers, or after all headers */ if(!hdrsadded && - (hdrline == NULL || strncasecmp(hdrline, "mime", 4) == 0)) { + ( strncasecmp(hdrline, "mime", 4) == 0)) { if(hdrfd >= 0) { - if(dumpfd2fd(hdrfd, outfd) < 0) { + if(process_headers_fd(hdrfd,outfd,posteraddr) < 0) { log_error(LOG_ARGS, "Could not " "add extra headers"); - free(hdrline); - free(unfolded); + tll_free_and_free(allunfoldeds, free); return -1; } fsync(outfd); @@ -97,33 +136,6 @@ int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, hdrsadded = true; } - /* end of headers */ - if(hdrline == NULL) { - /* add Subject if none is present - and a prefix is defined */ - if (prefix && !subject_present) { - dprintf(outfd, "Subject: %s\n", prefix); - subject_present = true; - } - /* write LF */ - if(dprintf(outfd, "\n") < 0) { - free(hdrline); - free(unfolded); - log_error(LOG_ARGS, "Error writing hdrs."); - return -1; - } - free(hdrline); - free(unfolded); - break; - } - - /* Do we want info from hdrs? Get it before it's gone */ - if(readhdrs) - getinfo(hdrline, readhdrs); - - /* Snatch a copy of the header */ - tll_push_back(*allhdrs, xstrdup(hdrline)); - /* Add Subject: prefix if wanted */ if(prefix) { if(strncasecmp(hdrline, "Subject:", 8) == 0) { @@ -132,7 +144,6 @@ int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, if(strstr(hdrline + 8, prefix) == NULL && strstr(unqp, prefix) == NULL) { dprintf(outfd, "Subject: %s%s\n", prefix, hdrline + 8); - free(hdrline); free(unqp); continue; } @@ -150,10 +161,32 @@ int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, dprintf(outfd, "Reply-To:%s\n", hdrline + 5); } } + } - free(hdrline); - free(unfolded); + if(!hdrsadded ) { + if(hdrfd >= 0) { + if(process_headers_fd(hdrfd,outfd,posteraddr) < 0) { + log_error(LOG_ARGS, "Could not " + "add extra headers"); + tll_free_and_free(allunfoldeds, free); + return -1; + } + fsync(outfd); + } + } + + if (prefix && !subject_present) { + dprintf(outfd, "Subject: %s\n", prefix); + subject_present = true; + } + /* write LF */ + if(dprintf(outfd, "\n") < 0) { + tll_free_and_free(allunfoldeds, free); + log_error(LOG_ARGS, "Error writing hdrs."); + return -1; } + + tll_free_and_free(allunfoldeds, free); lseek(infd, ftello(f), SEEK_SET); /* Just print the rest of the mail */ diff --git a/src/dumpfd2fd.c b/src/dumpfd2fd.c index 61015607..5dbcbdbe 100644 --- a/src/dumpfd2fd.c +++ b/src/dumpfd2fd.c @@ -29,6 +29,9 @@ #include #include "config.h" +#include "log_error.h" +#include "xmalloc.h" +#include "mygetline.h" #define DUMPBUF 4096 @@ -77,3 +80,28 @@ int dumpfd2fd(int from, int to) return (r); } + +int process_headers_fd(int infd, int outfd,const char *from) +{ + char *line; + int r; + + while((line = mygetline(infd))) { + char *to_be_subst ; char *new_line ; + to_be_subst = strstr(line,"$posteraddr$") ; + if ( to_be_subst != NULL) { + *to_be_subst = '\0' ; + to_be_subst = to_be_subst + 12 ; + xasprintf(&new_line, "%s%s%s", line, from , to_be_subst ) ; + free(line); + line=new_line ; + } + if( (r=dprintf(outfd, "%s", line)) < 0) { + log_error(LOG_ARGS, "Could not write headers"); + return r ; + } + free(line); + } + return 0 ; +} + diff --git a/tests/mlmmj-receive.in b/tests/mlmmj-receive.in index c84a6f55..48bd498f 100644 --- a/tests/mlmmj-receive.in +++ b/tests/mlmmj-receive.in @@ -26,8 +26,10 @@ tests_init \ normal_email \ delheaders \ customheaders \ + customheaders_with_subst \ verp \ - normal_email_with_dot + normal_email_with_dot \ + multi_line_headers mlmmjreceive=$(command -v mlmmj-receive) @@ -2836,6 +2838,106 @@ EOF atf_check -o file:expected-2.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-2.txt } +customheaders_with_subst_body() +{ + atf_check $top_builddir/tests/fakesmtpd + trap kill_fakesmtp EXIT TERM + init_ml list + rmdir list/text + ln -s ${top_srcdir}/listtexts/en list/text + echo test@mlmmjtest > list/control/listaddress + echo "25678" > list/control/smtpport + echo "heloname" > list/control/smtphelo + printf "X-H1: test\nNope: really not\nX-Poster-Address: \$posteraddr\$\n" > list/control/customheaders + + printf "user@test\nuser2@test" > list/subscribers.d/u +cat > first <> expected-1.txt < +RCPT TO: +DATA +From: bob@test +To: test@mlmmjtest +Subject: yeah +X-H1: test +Nope: really not +X-Poster-Address: bob@test + +Let's go, first email + +. +MAIL FROM: +RCPT TO: +DATA +From: bob@test +To: test@mlmmjtest +Subject: yeah +X-H1: test +Nope: really not +X-Poster-Address: bob@test + +Let's go, first email + +. +QUIT +EOF + atf_check -o file:expected-1.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-1.txt +cat > second <> expected-2.txt < +RCPT TO: +DATA +From: bob@test +To: test@mlmmjtest +X-H1: test +Nope: really not +X-Poster-Address: bob@test +Mime: really +Subject: yeah + +Let's go, first email + +. +MAIL FROM: +RCPT TO: +DATA +From: bob@test +To: test@mlmmjtest +X-H1: test +Nope: really not +X-Poster-Address: bob@test +Mime: really +Subject: yeah + +Let's go, first email + +. +QUIT +EOF + atf_check -o file:expected-2.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-2.txt +} + verp_body() { atf_check $top_builddir/tests/fakesmtpd @@ -2977,3 +3079,108 @@ EOF atf_check -s exit:0 $mlmmjreceive -L list -F list/control/listaddress + echo "25678" > list/control/smtpport + echo "heloname" > list/control/smtphelo + + printf "user@test\nuser2@test" > list/subscribers.d/u +cat > first <; Sat, 10 May 2025 17:17:17 +0000 (UTC) +From: bob@test +To: test@mlmmjtest +Return-path: bob@test +Subject: yeah + +Let's go, first email +EOF + + atf_check -s exit:0 $mlmmjreceive -L list -F > expected-1.txt < +RCPT TO: +DATA +Received: from test.com ( mail.test.com [192.168.168.1]) + by 192.168.168.168 with ESMTP id 0A21C400643 + for ; Sat, 10 May 2025 17:17:17 +0000 (UTC) +From: bob@test +To: test@mlmmjtest +Subject: yeah + +Let's go, first email + +. +MAIL FROM: +RCPT TO: +DATA +Received: from test.com ( mail.test.com [192.168.168.1]) + by 192.168.168.168 with ESMTP id 0A21C400643 + for ; Sat, 10 May 2025 17:17:17 +0000 (UTC) +From: bob@test +To: test@mlmmjtest +Subject: yeah + +Let's go, first email + +. +QUIT +EOF + atf_check -o file:expected-1.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-1.txt +cat > second <; Sat, 10 May 2025 17:17:17 +0000 (UTC) +From: bob@test +To: test@mlmmjtest +Return-path: bob@test +Mime: really +Subject: yeah + +Let's go, first email +EOF + + atf_check -s exit:0 $mlmmjreceive -L list -F > expected-2.txt < +RCPT TO: +DATA +Received: from test.com ( mail.test.com [192.168.168.1]) + by 192.168.168.168 with ESMTP id 0A21C400643 + for ; Sat, 10 May 2025 17:17:17 +0000 (UTC) +From: bob@test +To: test@mlmmjtest +Mime: really +Subject: yeah + +Let's go, first email + +. +MAIL FROM: +RCPT TO: +DATA +Received: from test.com ( mail.test.com [192.168.168.1]) + by 192.168.168.168 with ESMTP id 0A21C400643 + for ; Sat, 10 May 2025 17:17:17 +0000 (UTC) +From: bob@test +To: test@mlmmjtest +Mime: really +Subject: yeah + +Let's go, first email + +. +QUIT +EOF + atf_check -o file:expected-2.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-2.txt +} -- 2.47.2