+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
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 */
#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)
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;
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);
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) {
if(strstr(hdrline + 8, prefix) == NULL &&
strstr(unqp, prefix) == NULL) {
dprintf(outfd, "Subject: %s%s\n", prefix, hdrline + 8);
- free(hdrline);
free(unqp);
continue;
}
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 */
#include <limits.h>
#include "config.h"
+#include "log_error.h"
+#include "xmalloc.h"
+#include "mygetline.h"
#define DUMPBUF 4096
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 ;
+}
+
normal_email \
delheaders \
customheaders \
+ customheaders_with_subst \
verp \
- normal_email_with_dot
+ normal_email_with_dot \
+ multi_line_headers
mlmmjreceive=$(command -v mlmmj-receive)
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
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
+}