]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
customheaders allow substitution on variable $posteraddr$ 66/head
authorErwan MAS <erwan@mas.nom.fr>
Sat, 7 Jun 2025 18:37:00 +0000 (14:37 -0400)
committerErwan MAS <erwan@mas.nom.fr>
Sat, 7 Jun 2025 18:37:00 +0000 (14:37 -0400)
ChangeLog
include/wrappers.h
src/do_all_the_voodoo_here.c
src/dumpfd2fd.c
tests/mlmmj-receive.in

index 88fb175cfa7add6edfa1777d69ca3405dcdd3760..270fb715f88cd23c385b3ef87b0224a172ee79b9 100644 (file)
--- 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
index 8567c97ed8e0c7f7408a2c3f65dafca3bf9b598b..9b585cdb6b9b72dab2c2214c59696add1be7c895 100644 (file)
@@ -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 */
index 3ba56da73ca3c881e53e774c1abf273407c2831f..d6f6e12b17274361141c4d27c68bbdff7bec03cd 100644 (file)
@@ -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 */
index 61015607a62c80e4df2f27a56d632a0e8d6c8792..5dbcbdbeeaf9a4206828a8adc74c04014e6fa864 100644 (file)
@@ -29,6 +29,9 @@
 #include <limits.h>
 
 #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 ;
+}
+
index c84a6f55e115dd8d600e79b7e9fb058a39b29c2f..48bd498fd70471675d56ce8083d3bc8acd425d93 100644 (file)
@@ -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 <<EOF
+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 <first
+       cat >> expected-1.txt <<EOF
+EHLO heloname\r
+MAIL FROM:<test+bounces-1-user=test@mlmmjtest>\r
+RCPT TO:<user@test>\r
+DATA\r
+From: bob@test\r
+To: test@mlmmjtest\r
+Subject: yeah\r
+X-H1: test\r
+Nope: really not\r
+X-Poster-Address: bob@test\r
+\r
+Let's go, first email\r
+\r
+.\r
+MAIL FROM:<test+bounces-1-user2=test@mlmmjtest>\r
+RCPT TO:<user2@test>\r
+DATA\r
+From: bob@test\r
+To: test@mlmmjtest\r
+Subject: yeah\r
+X-H1: test\r
+Nope: really not\r
+X-Poster-Address: bob@test\r
+\r
+Let's go, first email\r
+\r
+.\r
+QUIT\r
+EOF
+       atf_check -o file:expected-1.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-1.txt
+cat > second <<EOF
+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 <second
+       cat >> expected-2.txt <<EOF
+EHLO heloname\r
+MAIL FROM:<test+bounces-2-user=test@mlmmjtest>\r
+RCPT TO:<user@test>\r
+DATA\r
+From: bob@test\r
+To: test@mlmmjtest\r
+X-H1: test\r
+Nope: really not\r
+X-Poster-Address: bob@test\r
+Mime: really\r
+Subject: yeah\r
+\r
+Let's go, first email\r
+\r
+.\r
+MAIL FROM:<test+bounces-2-user2=test@mlmmjtest>\r
+RCPT TO:<user2@test>\r
+DATA\r
+From: bob@test\r
+To: test@mlmmjtest\r
+X-H1: test\r
+Nope: really not\r
+X-Poster-Address: bob@test\r
+Mime: really\r
+Subject: yeah\r
+\r
+Let's go, first email\r
+\r
+.\r
+QUIT\r
+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 <first
        atf_check -o file:expected-1.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-1.txt
 }
+
+multi_line_headers_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 "user@test\nuser2@test" > list/subscribers.d/u
+cat > first <<EOF
+Received: from test.com ( mail.test.com [192.168.168.1])
+       by 192.168.168.168 with ESMTP id 0A21C400643
+       for <test@mlmmjtest>; 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 <first
+       cat >> expected-1.txt <<EOF
+EHLO heloname\r
+MAIL FROM:<test+bounces-1-user=test@mlmmjtest>\r
+RCPT TO:<user@test>\r
+DATA\r
+Received: from test.com ( mail.test.com [192.168.168.1])\r
+       by 192.168.168.168 with ESMTP id 0A21C400643\r
+       for <test@mlmmjtest>; Sat, 10 May 2025 17:17:17 +0000 (UTC)\r
+From: bob@test\r
+To: test@mlmmjtest\r
+Subject: yeah\r
+\r
+Let's go, first email\r
+\r
+.\r
+MAIL FROM:<test+bounces-1-user2=test@mlmmjtest>\r
+RCPT TO:<user2@test>\r
+DATA\r
+Received: from test.com ( mail.test.com [192.168.168.1])\r
+       by 192.168.168.168 with ESMTP id 0A21C400643\r
+       for <test@mlmmjtest>; Sat, 10 May 2025 17:17:17 +0000 (UTC)\r
+From: bob@test\r
+To: test@mlmmjtest\r
+Subject: yeah\r
+\r
+Let's go, first email\r
+\r
+.\r
+QUIT\r
+EOF
+       atf_check -o file:expected-1.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-1.txt
+cat > second <<EOF
+Received: from test.com ( mail.test.com [192.168.168.1])
+       by 192.168.168.168 with ESMTP id 0A21C400643
+       for <test@mlmmjtest>; 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 <second
+       cat >> expected-2.txt <<EOF
+EHLO heloname\r
+MAIL FROM:<test+bounces-2-user=test@mlmmjtest>\r
+RCPT TO:<user@test>\r
+DATA\r
+Received: from test.com ( mail.test.com [192.168.168.1])\r
+       by 192.168.168.168 with ESMTP id 0A21C400643\r
+       for <test@mlmmjtest>; Sat, 10 May 2025 17:17:17 +0000 (UTC)\r
+From: bob@test\r
+To: test@mlmmjtest\r
+Mime: really\r
+Subject: yeah\r
+\r
+Let's go, first email\r
+\r
+.\r
+MAIL FROM:<test+bounces-2-user2=test@mlmmjtest>\r
+RCPT TO:<user2@test>\r
+DATA\r
+Received: from test.com ( mail.test.com [192.168.168.1])\r
+       by 192.168.168.168 with ESMTP id 0A21C400643\r
+       for <test@mlmmjtest>; Sat, 10 May 2025 17:17:17 +0000 (UTC)\r
+From: bob@test\r
+To: test@mlmmjtest\r
+Mime: really\r
+Subject: yeah\r
+\r
+Let's go, first email\r
+\r
+.\r
+QUIT\r
+EOF
+       atf_check -o file:expected-2.txt sed -e "/^Message-ID:/d; /^Date:/d;" mail-2.txt
+}