All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] misc moderation patches
@ 2007-07-05 19:57 Steve Beattie
  2007-07-05 21:13 ` Morten K. Poulsen
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Steve Beattie @ 2007-07-05 19:57 UTC (permalink / raw)
  To: mlmmj


[-- Attachment #1.1: Type: text/plain, Size: 2350 bytes --]

Here are some patches mostly related to moderating emails for
discussion. I currently admin some lists with mailman, but would like
to move to mlmmj.

mlmmj-X-List-Administrivia_header.patch

	This patch adds two headers, an "X-List_administrivia: Yes" header
	for a few of the administrative messages that mlmmj sends out, and
	a header "X-mlmmj-mod-msg-id:" with the random string that is used
	as the argument for the 'moderate' command. The former is used
	similarly by mailman, and I filter based on it; I don't strictly
	need it if I have the latter header. The latter is really useful
	for writing scripts to moderate multiple messages at a time,
	rather than requiring them to parse out the Reply-To: header.

	If it's deemed worthwhile to keep the administrivia header,
	there's likely more locations that could use it, or it should
	just be added automatically in prepstdreply(). Another
	alternative would be to add these headers in the listtexts.

mlmmj-multiple_moderation_args.patch

	This patch adds the ability to moderate multiple messages by
	sending mlmmj a single message with multiple cookies addressed
	in the form

	  	listname+moderate-COOKIE[-COOKIE...]@domain.tld

	(This is one of my gripes with mailman, that in order to reject
	multiple spam messages by email, my script has to send a message
	for each message to reject, rather than just one message per
	list.) I left the moderation of subscriptions alone.

mlmmj-reject_command.patch

	This adds a 'reject' command to support rejecting messages for
	moderation, rather than accepting them as the 'moderate' command
	does. It supports rejecting multiple messages by taking messages
	in the form

		listname+reject-COOKIE[-COOKIE...]@domain.tld

	I didn't add support for rejecting subscriptions; that should
	probably be fixed.

mlmmj-add_moderator_command.patch

	This patch converts the From: address (currently
	"listname-moderators") in moderation messages to be a real address
	supported by mlmmj and adds the corresponding 'moderators'
	command. I'm not sure proper envelope filtering is done here,
	though.

As these patches touch similar areas of code, they are expected to be
applied in the order above.

Thanks.
-- 
Steve Beattie
SUSE Labs, Novell Inc. 
<sbeattie@suse.de>
http://NxNW.org/~steve/

[-- Attachment #1.2: mlmmj-X-List-Administrivia_header.patch --]
[-- Type: text/x-patch, Size: 2685 bytes --]

---
 src/mlmmj-process.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

Index: b/src/mlmmj-process.c
===================================================================
--- a/src/mlmmj-process.c
+++ b/src/mlmmj-process.c
@@ -79,6 +79,7 @@ void newmoderated(const char *listdir, c
 	int queuefd, moderatorsfd, mailfd;
 	size_t count = 0;
 	char *maildata[4] = { "moderateaddr", NULL, "moderators", NULL };
+	char *adminhdrs = "X-List-Administrivia: Yes";
 #if 0
 	printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename,
 			                                     mailbasename);
@@ -114,6 +115,7 @@ void newmoderated(const char *listdir, c
 
 	maildata[1] = replyto;
 	maildata[3] = moderators;
+	adminhdrs = concatstr(3, adminhdrs, "\nX-mlmmj-mod-msg-id: ", mailbasename);
 
 	from = concatstr(4, listname, listdelim, "owner@", listfqdn);
 	to = concatstr(3, listname, "-moderators@", listfqdn); /* FIXME JFA: Should this be converted? Why, why not? */
@@ -123,7 +125,7 @@ void newmoderated(const char *listdir, c
 	myfree(listfqdn);
 
 	queuefilename = prepstdreply(listdir, "moderation", "$listowner$",
-				     to, replyto, 2, maildata, NULL);
+				     to, replyto, 2, maildata, adminhdrs);
 
 	if((queuefd = open(queuefilename, O_WRONLY|O_APPEND)) < 0) {
 		log_error(LOG_ARGS, "Could not open '%s'", queuefilename);
@@ -347,6 +349,7 @@ int main(int argc, char **argv)
 	char *queuefilename, *recipextra = NULL, *owner = NULL;
 	char *maxmailsizestr;
 	char *maildata[4] = { "posteraddr", NULL, "maxmailsize", NULL };
+	char *adminhdr = "X-List-Administrivia: Yes";
 	char *envstr, *efrom;
 	struct stat st;
 	uid_t uid;
@@ -657,7 +660,7 @@ int main(int argc, char **argv)
 			queuefilename = prepstdreply(listdir,
 					"maxmailsize", "$listowner$",
 					fromemails.emaillist[0],
-					NULL, 2, maildata, NULL);
+					NULL, 2, maildata, adminhdr);
 			MY_ASSERT(queuefilename)
 			myfree(listdelim);
 			myfree(listname);
@@ -768,7 +771,7 @@ int main(int argc, char **argv)
 				     listfqdn);
 		queuefilename = prepstdreply(listdir, "notintocc",
 					"$listowner$", fromemails.emaillist[0],
-					     NULL, 0, NULL, NULL);
+					     NULL, 0, NULL, adminhdr);
 		MY_ASSERT(queuefilename)
 		myfree(listdelim);
 		myfree(listname);
@@ -829,7 +832,7 @@ int main(int argc, char **argv)
 					"bounces-help@", listfqdn);
 			queuefilename = prepstdreply(listdir, "subonlypost",
 					"$listowner$", fromemails.emaillist[0],
-						     NULL, 1, maildata, NULL);
+						     NULL, 1, maildata, adminhdr);
 			MY_ASSERT(queuefilename)
 			myfree(listaddr);
 			myfree(listdelim);

[-- Attachment #1.3: mlmmj-multiple_moderation_args.patch --]
[-- Type: text/x-patch, Size: 4651 bytes --]


(Note: some mail clients like mutt have hard coded limits on the length
of a To: address; e.g. mutt has a limit of 256 characters which it will
truncate if the address is longer than that.)
---
 src/listcontrol.c |   95 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 69 insertions(+), 26 deletions(-)

Index: b/src/listcontrol.c
===================================================================
--- a/src/listcontrol.c
+++ b/src/listcontrol.c
@@ -98,6 +98,34 @@ static struct ctrl_command ctrl_commands
 	{ "list",               0 }
 };
 
+struct strlist *splitparam(const char *param, const char split)
+{
+	char *c;
+	struct strlist *params = mymalloc(sizeof(struct strlist));
+	size_t len;
+
+	params->count = 0;
+	params->strs = NULL;
+
+	if (!param)
+		return params;
+
+	while (*param && (c = strchr(param, split)) != NULL) {
+		len = c - param;
+		params->strs = myrealloc(params->strs, sizeof(c) * (params->count + 1));
+		params->strs[params->count] = mymalloc(len + 1);
+		strncpy(params->strs[params->count], param, len);
+		params->strs[params->count++][len] = '\0';
+		param = c + 1;
+	}
+
+	/* handle last param */
+	if (*param) {
+		params->strs = myrealloc(params->strs, sizeof(c) * (params->count + 1));
+		params->strs[params->count++] = mystrdup(param);
+	}
+	return params;
+}
 
 int listcontrol(struct email_container *fromemails, const char *listdir,
 		const char *controlstr, const char *mlmmjsub,
@@ -114,7 +142,9 @@ int listcontrol(struct email_container *
 	size_t cmdlen;
 	unsigned int ctrl;
 	struct strlist *owners;
-	int owner_idx;
+	struct strlist *params;
+	int owner_idx, rc;
+	pid_t childpid;
 	
 	/* A closed list doesn't allow subscribtion and unsubscription */
 	closedlist = statctrl(listdir, "closedlist");
@@ -588,13 +618,13 @@ int listcontrol(struct email_container *
 		exit(EXIT_FAILURE);
 		break;
 
-	/* listname+moderate-COOKIE@domain.tld */
+	/* listname+moderate-COOKIE[-COOKIE...]@domain.tld */
 	case CTRL_MODERATE:
 		/* TODO Add accept/reject parameter to moderate */
-		moderatefilename = concatstr(3, listdir, "/moderation/", param);
 
 		/* Subscriber moderation */
 		if(strncmp(param, "subscribe", 9) == 0) {
+			moderatefilename = concatstr(3, listdir, "/moderation/", param);
 			log_oper(listdir, OPLOGFNAME, "%s moderated %s",
 				fromemails->emaillist[0], moderatefilename);
 			execlp(mlmmjsub, mlmmjsub,
@@ -603,32 +633,45 @@ int listcontrol(struct email_container *
 					"-c", (char *)NULL);
 		}
 
-		sendfilename = concatstr(2, moderatefilename, ".sending");
+		rc = EXIT_SUCCESS;
+		params = splitparam(param, '-');
+		for (i = 0; i < params->count; i++) {
+			moderatefilename = concatstr(3, listdir, "/moderation/", params->strs[i]);
+
+			sendfilename = concatstr(2, moderatefilename, ".sending");
+
+			if (stat(moderatefilename, &stbuf) < 0) {
+				myfree(moderatefilename);
+				/* no mail to moderate */
+				errno = 0;
+				log_error(LOG_ARGS, "A moderate request was"
+					" sent with a mismatching cookie."
+					" Ignoring mail");
+				continue;
+			}
+			/* Rename it to avoid mail being sent twice */
+			if (rename(moderatefilename, sendfilename) < 0) {
+				log_error(LOG_ARGS, "Could not rename to .sending");
+				rc = EXIT_FAILURE;
+			}
 
-		if(stat(moderatefilename, &stbuf) < 0) {
+			log_oper(listdir, OPLOGFNAME, "%s moderated %s",
+				fromemails->emaillist[0], moderatefilename);
 			myfree(moderatefilename);
-			/* no mail to moderate */
-			errno = 0;
-			log_error(LOG_ARGS, "A moderate request was"
-				" sent with a mismatching cookie."
-				" Ignoring mail");
-			return -1;
-		}
-		/* Rename it to avoid mail being sent twice */
-		if(rename(moderatefilename, sendfilename) < 0) {
-			log_error(LOG_ARGS, "Could not rename to .sending");
-			exit(EXIT_FAILURE);
-		}
+			childpid = fork();
+			if (childpid < 0)
+				log_error(LOG_ARGS, "fork() failed!  Proceeding anyway");
 
-		log_oper(listdir, OPLOGFNAME, "%s moderated %s",
-				fromemails->emaillist[0], moderatefilename);
-		myfree(moderatefilename);
-		execlp(mlmmjsend, mlmmjsend,
-				"-L", listdir,
-				"-m", sendfilename, (char *)NULL);
-		log_error(LOG_ARGS, "execlp() of '%s' failed",
-					mlmmjsend);
-		exit(EXIT_FAILURE);
+			if (!childpid) {
+				execlp(mlmmjsend, mlmmjsend,
+					"-L", listdir,
+					"-m", sendfilename, (char *)NULL);
+				log_error(LOG_ARGS, "execlp() of '%s' failed",
+						mlmmjsend);
+				exit(EXIT_FAILURE);
+			}
+		}
+		exit(rc);
 		break;
 
 	/* listname+help@domain.tld */

[-- Attachment #1.4: mlmmj-reject_command.patch --]
[-- Type: text/x-patch, Size: 1915 bytes --]

---
 src/listcontrol.c |   26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

Index: b/src/listcontrol.c
===================================================================
--- a/src/listcontrol.c
+++ b/src/listcontrol.c
@@ -62,6 +62,7 @@ enum ctrl_e {
 	CTRL_CONFUNSUB,
 	CTRL_BOUNCES,
 	CTRL_MODERATE,
+	CTRL_REJECT,
 	CTRL_HELP,
 	CTRL_FAQ,
 	CTRL_GET,
@@ -92,6 +93,7 @@ static struct ctrl_command ctrl_commands
 	{ "confunsub",          1 },
 	{ "bounces",            1 },
 	{ "moderate",           1 },
+	{ "reject",             1 },
 	{ "help",               0 },
 	{ "faq",                0 },
 	{ "get",                1 },
@@ -620,8 +622,6 @@ int listcontrol(struct email_container *
 
 	/* listname+moderate-COOKIE[-COOKIE...]@domain.tld */
 	case CTRL_MODERATE:
-		/* TODO Add accept/reject parameter to moderate */
-
 		/* Subscriber moderation */
 		if(strncmp(param, "subscribe", 9) == 0) {
 			moderatefilename = concatstr(3, listdir, "/moderation/", param);
@@ -674,6 +674,28 @@ int listcontrol(struct email_container *
 		exit(rc);
 		break;
 
+	/* listname+reject-COOKIE[-COOKIE...]@domain.tld */
+	case CTRL_REJECT:
+		params = splitparam(param, '-');
+		for (i = 0; i < params->count; i++) {
+			moderatefilename = concatstr(3, listdir, "/moderation/", params->strs[i]);
+
+			if (stat(moderatefilename, &stbuf) < 0) {
+				/* no mail to moderate */
+				errno = 0;
+				log_error(LOG_ARGS, "A reject request was"
+					" sent with a mismatching cookie."
+					" Ignoring mail");
+			} else {
+				unlink(moderatefilename);
+				log_oper(listdir, OPLOGFNAME, "%s rejected %s",
+					fromemails->emaillist[0], moderatefilename);
+			}
+			myfree(moderatefilename);
+		}
+		exit(EXIT_SUCCESS);
+		break;
+
 	/* listname+help@domain.tld */
 	case CTRL_HELP:
 		if(!strchr(fromemails->emaillist[0], '@')) {

[-- Attachment #1.5: mlmmj-add_moderator_command.patch --]
[-- Type: text/x-patch, Size: 3779 bytes --]

---
 src/listcontrol.c   |   29 +++++++++++++++++++++++++++--
 src/mlmmj-process.c |    2 +-
 src/mlmmj-sub.c     |    2 +-
 3 files changed, 29 insertions(+), 4 deletions(-)

Index: b/src/mlmmj-sub.c
===================================================================
--- a/src/mlmmj-sub.c
+++ b/src/mlmmj-sub.c
@@ -131,7 +131,7 @@ void moderate_sub(const char *listdir, c
 	modfilebase = mybasename(modfilename);
 
 	from = concatstr(4, listname, listdelim, "owner@", listfqdn);
-	to = concatstr(3, listname, "-moderators@", listfqdn);
+	to = concatstr(4, listname, listdelim, "moderators@", listfqdn);
 	replyto = concatstr(6, listname, listdelim, "moderate-", modfilebase,
 			"@", listfqdn);
 	myfree(modfilebase);
Index: b/src/mlmmj-process.c
===================================================================
--- a/src/mlmmj-process.c
+++ b/src/mlmmj-process.c
@@ -118,7 +118,7 @@ void newmoderated(const char *listdir, c
 	adminhdrs = concatstr(3, adminhdrs, "\nX-mlmmj-mod-msg-id: ", mailbasename);
 
 	from = concatstr(4, listname, listdelim, "owner@", listfqdn);
-	to = concatstr(3, listname, "-moderators@", listfqdn); /* FIXME JFA: Should this be converted? Why, why not? */
+	to = concatstr(4, listname, listdelim, "moderators@", listfqdn); /* FIXME JFA: Should this be converted? Why, why not? */
 
 	myfree(listdelim);
 	myfree(listname);
Index: b/src/listcontrol.c
===================================================================
--- a/src/listcontrol.c
+++ b/src/listcontrol.c
@@ -35,6 +35,7 @@
 #include "listcontrol.h"
 #include "find_email_adr.h"
 #include "getlistdelim.h"
+#include "getlistaddr.h"
 #include "strgen.h"
 #include "send_help.h"
 #include "send_list.h"
@@ -62,6 +63,7 @@ enum ctrl_e {
 	CTRL_CONFUNSUB,
 	CTRL_BOUNCES,
 	CTRL_MODERATE,
+	CTRL_MODERATORS,
 	CTRL_REJECT,
 	CTRL_HELP,
 	CTRL_FAQ,
@@ -93,6 +95,7 @@ static struct ctrl_command ctrl_commands
 	{ "confunsub",          1 },
 	{ "bounces",            1 },
 	{ "moderate",           1 },
+	{ "moderators",         0 },
 	{ "reject",             1 },
 	{ "help",               0 },
 	{ "faq",                0 },
@@ -137,6 +140,7 @@ int listcontrol(struct email_container *
 	char *bouncenr, *tmpstr;
 	char *param = NULL, *conffilename, *moderatefilename;
 	char *c, *archivefilename, *sendfilename;
+	char *listfqdn, *listname, *listaddr = getlistaddr(listdir), *listdelim;
 	const char *subswitch;
 	struct stat stbuf;
 	int closedlist, nosubconfirm, tmpfd, noget, i, closedlistsub,
@@ -216,8 +220,9 @@ int listcontrol(struct email_container *
 		return -1;
 	}
 
-	/* We only need the control mail when bouncing, to save bounced msg */
-	if(ctrl != CTRL_BOUNCES)
+	/* We only need the control mail when bouncing, to save
+	   bounced msg, and when sending to moderators */
+	if(ctrl != CTRL_BOUNCES && ctrl != CTRL_MODERATORS)
 		unlink(mailname);
 
 	switch (ctrl) {
@@ -696,6 +701,26 @@ int listcontrol(struct email_container *
 		exit(EXIT_SUCCESS);
 		break;
 
+	/* listname+moderators@domain.tld */
+	case CTRL_MODERATORS:
+		listfqdn = genlistfqdn(listaddr);
+		listname = genlistname(listaddr);
+		listdelim = getlistdelim(listdir);
+		tmpstr = concatstr(4, listname, listdelim, "owner@", listfqdn);
+		log_oper(listdir, OPLOGFNAME, "mlmmj-recieve: sending"
+				" mail from %s to moderators",
+				fromemails->emaillist[0]);
+		execlp(mlmmjsend, mlmmjsend,
+				"-l", "2",
+				"-L", listdir,
+				"-m", mailname,
+				"-F", tmpstr,
+				"-a", (char *)NULL);
+		log_error(LOG_ARGS, "execlp() of '%s' failed",
+					mlmmjsend);
+		exit(EXIT_FAILURE);
+		break;
+
 	/* listname+help@domain.tld */
 	case CTRL_HELP:
 		if(!strchr(fromemails->emaillist[0], '@')) {

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2007-11-12 21:41 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-05 19:57 [RFC] misc moderation patches Steve Beattie
2007-07-05 21:13 ` Morten K. Poulsen
2007-07-09 21:11 ` Steve Beattie
2007-07-11 17:28 ` Morten K. Poulsen
2007-11-11 20:29 ` Morten K. Poulsen
2007-11-12 10:00 ` Alexander Kardailsky
2007-11-12 20:11 ` Morten K. Poulsen
2007-11-12 20:34 ` Alexander Kardailsky
2007-11-12 20:40 ` Steve Beattie
2007-11-12 20:48 ` Morten K. Poulsen
2007-11-12 21:41 ` Morten K. Poulsen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.