changeset 568:99f493df54af

Add support for qmail (envelope from address in environment variable)
author mortenp
date Mon, 04 Sep 2006 08:04:12 +1000
parents baffb3e41df7
children 0ce85f30f3bb
files ChangeLog include/listcontrol.h src/listcontrol.c src/mlmmj-process.c
diffstat 4 files changed, 107 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Sep 04 07:52:44 2006 +1000
+++ b/ChangeLog	Mon Sep 04 08:04:12 2006 +1000
@@ -1,3 +1,4 @@
+ o Add support for qmail (envelope from address in environment variable)
  o Add digest text part
  o Add subscriber moderation
  o Fix default subject in administrative mails
--- a/include/listcontrol.h	Mon Sep 04 07:52:44 2006 +1000
+++ b/include/listcontrol.h	Mon Sep 04 08:04:12 2006 +1000
@@ -27,7 +27,7 @@
 #include "find_email_adr.h"
 
 int listcontrol(struct email_container *fromemails, const char *listdir,
-		const char *controladdr, const char *mlmmjsub,
+		const char *controlstr, const char *mlmmjsub,
 		const char *mlmmjunsub, const char *mlmmjsend,
 		const char *mlmmjbounce, const char *mailname);
 
--- a/src/listcontrol.c	Mon Sep 04 07:52:44 2006 +1000
+++ b/src/listcontrol.c	Mon Sep 04 08:04:12 2006 +1000
@@ -98,15 +98,14 @@
 
 
 int listcontrol(struct email_container *fromemails, const char *listdir,
-		const char *controladdr, const char *mlmmjsub,
+		const char *controlstr, const char *mlmmjsub,
 		const char *mlmmjunsub, const char *mlmmjsend,
 		const char *mlmmjbounce, const char *mailname)
 {
-	char *atsign, *recipdelimsign, *listdelim, *bouncenr, *tmpstr;
-	char *controlstr, *param = NULL, *conffilename, *moderatefilename;
+	char *bouncenr, *tmpstr;
+	char *param = NULL, *conffilename, *moderatefilename;
 	char *c, *archivefilename, *sendfilename;
 	const char *subswitch;
-	size_t len;
 	struct stat stbuf;
 	int closedlist, nosubconfirm, tmpfd, noget, i, closedlistsub,
 	    subonlyget = 0;
@@ -127,18 +126,6 @@
 	else
 		subswitch = "-C";
 	
-	listdelim = getlistdelim(listdir);
-	recipdelimsign = strstr(controladdr, listdelim);
-	MY_ASSERT(recipdelimsign);
-	atsign = index(controladdr, '@');
-	MY_ASSERT(atsign);
-	len = atsign - recipdelimsign;
-
-	controlstr = mymalloc(len);
-	MY_ASSERT(controlstr);
-	snprintf(controlstr, len, "%s", recipdelimsign + strlen(listdelim));
-	myfree(listdelim);
-
 #if 0
 	log_error(LOG_ARGS, "controlstr = [%s]\n", controlstr);
 	log_error(LOG_ARGS, "fromemails->emaillist[0] = [%s]\n",
@@ -182,7 +169,6 @@
 				param = NULL;
 			}
 
-			myfree(controlstr);
 			break;
 
 		}
--- a/src/mlmmj-process.c	Mon Sep 04 07:52:44 2006 +1000
+++ b/src/mlmmj-process.c	Mon Sep 04 08:04:12 2006 +1000
@@ -299,6 +299,38 @@
 }
 
 
+static char *recipient_extra(const char *listdir, const char *addr)
+{
+	char *listdelim;
+	char *delim, *atsign, *ret;
+	size_t len;
+
+	if (!addr)
+		return NULL;
+
+	listdelim = getlistdelim(listdir);
+
+	delim = strstr(addr, listdelim);
+	if (!delim) {
+		myfree(listdelim);
+		return NULL;
+	}
+	delim += strlen(listdelim);
+	myfree(listdelim);
+
+	atsign = strrchr(delim, '@');
+	if (!atsign)
+		return NULL;
+
+	len = atsign - delim;
+	ret = (char *)mymalloc(len + 1);
+	strncpy(ret, delim, len);
+	ret[len] = '\0';
+
+	return ret;
+}
+
+
 static void print_help(const char *prg)
 {
         printf("Usage: %s -L /path/to/list -m /path/to/mail [-h] [-P] [-V]\n"
@@ -323,16 +355,16 @@
 	char *mlmmjsend, *mlmmjsub, *mlmmjunsub, *mlmmjbounce;
 	char *bindir, *subjectprefix, *discardname, *listaddr, *listdelim;
 	char *listfqdn, *listname, *fromaddr;
-	char *queuefilename, *recipextra, *owner = NULL;
+	char *queuefilename, *recipextra = NULL, *owner = NULL;
 	char *maildata[2] = { "posteraddr", NULL };
+	char *envstr, *efrom;
 	struct stat st;
 	uid_t uid;
 	struct email_container fromemails = { 0, NULL };
 	struct email_container toemails = { 0, NULL };
 	struct email_container ccemails = { 0, NULL };
-	struct email_container efromemails = { 0, NULL };
-	struct email_container dtoemails = { 0, NULL };
-	struct email_container *whichto;
+	struct email_container rpemails = { 0, NULL };
+	struct email_container dtemails = { 0, NULL };
 	struct strlist *access_rules = NULL;
 	struct strlist *delheaders = NULL;
 	struct strlist allheaders;
@@ -473,60 +505,77 @@
 	if(footfd >= 0)
 		close(footfd);
 
-	if(readhdrs[0].token) { /* From: addresses */
+	/* From: addresses */
 		for(i = 0; i < readhdrs[0].valuecount; i++) {
 			find_email_adr(readhdrs[0].values[i], &fromemails);
 		}
-	}
 
-	if(readhdrs[1].token) { /* To: addresses */
+	/* To: addresses */
 		for(i = 0; i < readhdrs[1].valuecount; i++) {
 			find_email_adr(readhdrs[1].values[i], &toemails);
 		}
-	}
 
-	if(readhdrs[2].token) { /* Cc: addresses */
+	/* Cc: addresses */
 		for(i = 0; i < readhdrs[2].valuecount; i++) {
 			find_email_adr(readhdrs[2].values[i], &ccemails);
 		}
+
+	/* Return-Path: addresses */
+	for(i = 0; i < readhdrs[3].valuecount; i++) {
+		find_email_adr(readhdrs[3].values[i], &rpemails);
 	}
 
-	if(readhdrs[3].token) { /* Return-Path: (envelope from) */
-		for(i = 0; i < readhdrs[3].valuecount; i++) {
-			find_email_adr(readhdrs[3].values[i], &efromemails);
-		}
-		if(efromemails.emailcount == 0) {
-			efromemails.emaillist =
-				(char **)mymalloc(sizeof(char *));
-			efromemails.emaillist[0] = mystrdup("<>");
-		}
+	/* Delivered-To: addresses */
+	for(i = 0; i < readhdrs[4].valuecount; i++) {
+		find_email_adr(readhdrs[4].values[i], &dtemails);
 	}
 
-	if(readhdrs[4].token) { /* Delivered-To: (envelope to) */
-		for(i = 0; i < readhdrs[4].valuecount; i++) {
-			find_email_adr(readhdrs[4].values[i], &dtoemails);
-		}
+	/* envelope from */
+	if((envstr = getenv("SENDER")) != NULL) {
+		/* qmail, postfix, exim */
+		efrom = mystrdup(envstr);
+	} else if(rpemails.emailcount >= 1) {
+		/* the (first) Return-Path: header */
+		efrom = mystrdup(rpemails.emaillist[0]);
+	} else {
+		efrom = mystrdup("");
 	}
 
-	if(dtoemails.emaillist)
-		whichto = &dtoemails;
-	else if(toemails.emaillist)
-		whichto = &toemails;
-	else
-		whichto = NULL;
-
+	/* address extension (the "foo" part of "user+foo@domain.tld") */
+	if((envstr = getenv("EXT")) != NULL) {
+		/* qmail */
+		recipextra = mystrdup(envstr);
+	} else if((envstr = getenv("EXTENSION")) != NULL) {
+		/* postfix */
+		recipextra = mystrdup(envstr);
+	} else if((envstr = getenv("LOCAL_PART_SUFFIX")) != NULL) {
+		/* exim */
 	listdelim = getlistdelim(listdir);
-	if(whichto && whichto->emaillist && whichto->emaillist[0]){
-		recipextra = strstr(whichto->emaillist[0], listdelim);
-		if (recipextra)
-			recipextra += strlen(listdelim);
-	} else
+		if (strncmp(envstr, listdelim, strlen(listdelim)) == 0) {
+			recipextra = mystrdup(envstr + strlen(listdelim));
+		} else {
+			recipextra = mystrdup(envstr);
+		}
+		myfree(listdelim);
+	} else if(dtemails.emailcount >= 1) {
+		/* parse the (first) Delivered-To: header */
+		recipextra = recipient_extra(listdir, dtemails.emaillist[0]);
+	} else if(toemails.emailcount >= 1) {
+		/* parse the (first) To: header */
+		recipextra = recipient_extra(listdir, toemails.emaillist[0]);
+	} else {
 		recipextra = NULL;
-	myfree(listdelim);
+	}
 
+	if(recipextra && (strlen(recipextra) == 0)) {
+		myfree(recipextra);
+		recipextra = NULL;
+	}
+
+	/* Why is this here, and not in listcontrol() ?  -- mortenp 20060409 */
 	if(recipextra) {
 		owner = concatstr(2, listdir, "/control/owner");
-		if(owner && strncmp(recipextra, "owner@", 6) == 0) {
+		if(owner && strcmp(recipextra, "owner") == 0) {
 			/* strip envelope from before resending */
 			delheaders->count = 0;
 			delheaders->strs = NULL;
@@ -559,11 +608,11 @@
 			unlink(mailfile);
 			log_oper(listdir, OPLOGFNAME, "mlmmj-recieve: sending"
 					" mail from %s to owner",
-					efromemails.emaillist[0]);
+					efrom);
 			execlp(mlmmjsend, mlmmjsend,
 					"-l", "4",
 					"-L", listdir,
-					"-F", efromemails.emaillist[0],
+					"-F", efrom,
 					"-s", owner,
 					"-a",
 					"-m", donemailname, (char *)NULL);
@@ -575,7 +624,7 @@
 		log_error(LOG_ARGS, "listcontrol(from, %s, %s, %s, %s, %s, %s)\n", listdir, toemails.emaillist[0], mlmmjsub, mlmmjunsub, mlmmjsend, mlmmjbounce);
 #endif
 		unlink(mailfile);
-		listcontrol(&fromemails, listdir, whichto->emaillist[0],
+		listcontrol(&fromemails, listdir, recipextra,
 			    mlmmjsub, mlmmjunsub, mlmmjsend, mlmmjbounce,
 			    donemailname);
 
@@ -605,14 +654,14 @@
 
 	myfree(delheaders);
 
-	if(efromemails.emailcount != 1) { /* don't send mails with <> in From
+	if(strcmp(efrom, "") == 0) { /* don't send mails with <> in From
 					     to the list */
 		discardname = concatstr(3, listdir,
 				"/queue/discarded/",
 				randomstr);
-		log_error(LOG_ARGS, "Discarding %s due to invalid envelope"
-				" from email count (was %d, must be 1)",
-				mailfile, efromemails.emailcount);
+		errno = 0;
+		log_error(LOG_ARGS, "Discarding %s due to missing envelope"
+				" from address", mailfile);
 		rename(mailfile, discardname);
 		unlink(donemailname);
 		myfree(donemailname);