+ o Add rejection of posts and obstruction of subscriptions.
o Avoid bogus error messages when logging that the list address has been
found in To: or CC: headers.
o Escape dashes in man pages.
.HP
\fB\-L\fR: Full path to list directory
.HP
-\fB\-m\fR: Subscriber moderation string
+\fB\-m\fR: Moderation string
.HP
\fB\-n\fR: Subscribe to nomail version of the list
.HP
CTRL_CONFUNSUB_NOMAIL,
CTRL_CONFUNSUB,
CTRL_BOUNCES,
+ CTRL_RELEASE,
+ CTRL_REJECT,
+ CTRL_PERMIT,
+ CTRL_OBSTRUCT,
CTRL_MODERATE,
CTRL_HELP,
CTRL_FAQ,
{ "confunsub-nomail", 1 },
{ "confunsub", 1 },
{ "bounces", 1 },
+ { "release", 1 },
+ { "reject", 1 },
+ { "permit", 1 },
+ { "obstruct", 1 },
{ "moderate", 1 },
{ "help", 0 },
{ "faq", 0 },
const char *mlmmjbounce, const char *mailname)
{
char *bouncenr, *tmpstr;
- char *param = NULL, *conffilename, *moderatefilename, *omitfilename;
+ char *param = NULL, *conffilename, *moderatefilename, *gatekeepfilename;
+ char *omitfilename;
char *omit = NULL;
char *c, *archivefilename, *sendfilename;
const char *subswitch;
exit(EXIT_FAILURE);
break;
- /* listname+moderate-COOKIE@domain.tld */
+ /* listname+release-COOKIE@domain.tld */
+ case CTRL_RELEASE:
+ /* DEPRECATED: listname+moderate-COOKIE@domain.tld */
+ /* DEPRECATED: listname+moderate-subscribeCOOKIE@domain.tld */
case CTRL_MODERATE:
- /* TODO Add accept/reject parameter to moderate */
- moderatefilename = concatstr(3, listdir, "/moderation/", param);
-
- /* Subscriber moderation */
+ /* Subscriber moderation; DEPRECATED */
if(strncmp(param, "subscribe", 9) == 0) {
- log_oper(listdir, OPLOGFNAME, "%s moderated %s",
- fromemails->emaillist[0], moderatefilename);
- execlp(mlmmjsub, mlmmjsub,
- "-L", listdir,
- "-m", param,
- "-c", (char *)NULL);
+ tmpstr = mystrdup(param + 9);
+ myfree(param);
+ param = tmpstr;
+ goto permit;
}
- sendfilename = concatstr(2, moderatefilename, ".sending");
+ moderatefilename = concatstr(3, listdir, "/moderation/", param);
if(stat(moderatefilename, &stbuf) < 0) {
myfree(moderatefilename);
/* no mail to moderate */
errno = 0;
- log_error(LOG_ARGS, "A moderate request was"
+ log_error(LOG_ARGS, "A release request was"
" sent with a mismatching cookie."
" Ignoring mail");
return -1;
}
+
+ sendfilename = concatstr(2, moderatefilename, ".sending");
/* Rename it to avoid mail being sent twice */
if(rename(moderatefilename, sendfilename) < 0) {
log_error(LOG_ARGS, "Could not rename to .sending");
myfree(omitfilename);
}
- log_oper(listdir, OPLOGFNAME, "%s moderated %s",
- fromemails->emaillist[0], moderatefilename);
myfree(moderatefilename);
+
+ log_oper(listdir, OPLOGFNAME, "%s released %s",
+ fromemails->emaillist[0], param);
+
if (omit != NULL)
execlp(mlmmjsend, mlmmjsend,
"-L", listdir,
exit(EXIT_FAILURE);
break;
+ /* listname+reject-COOKIE@domain.tld */
+ case CTRL_REJECT:
+ moderatefilename = concatstr(3, listdir, "/moderation/", param);
+ if(stat(moderatefilename, &stbuf) < 0) {
+ myfree(moderatefilename);
+ /* no mail to moderate */
+ errno = 0;
+ log_error(LOG_ARGS, "A reject request was"
+ " sent with a mismatching cookie."
+ " Ignoring mail");
+ return -1;
+ }
+ log_oper(listdir, OPLOGFNAME, "%s rejected %s",
+ fromemails->emaillist[0], param);
+ myfree(param);
+ if (unlink(moderatefilename) != 0) {
+ log_error(LOG_ARGS, "Could not unlink %s",
+ moderatefilename);
+ myfree(moderatefilename);
+ exit(EXIT_FAILURE);
+ }
+ myfree(moderatefilename);
+ break;
+
+ /* listname+permit-COOKIE@domain.tld */
+ case CTRL_PERMIT:
+permit:
+ gatekeepfilename = concatstr(3, listdir,
+ "/moderation/subscribe", param);
+ if(stat(gatekeepfilename, &stbuf) < 0) {
+ myfree(gatekeepfilename);
+ /* no mail to moderate */
+ errno = 0;
+ log_error(LOG_ARGS, "A permit request was"
+ " sent with a mismatching cookie."
+ " Ignoring mail");
+ return -1;
+ }
+ log_oper(listdir, OPLOGFNAME, "%s permitted %s",
+ fromemails->emaillist[0], param);
+ execlp(mlmmjsub, mlmmjsub,
+ "-L", listdir,
+ "-m", param,
+ "-c", (char *)NULL);
+ log_error(LOG_ARGS, "execlp() of '%s' failed",
+ mlmmjsub);
+ exit(EXIT_FAILURE);
+ break;
+
+ /* listname+obstruct-COOKIE@domain.tld */
+ case CTRL_OBSTRUCT:
+ gatekeepfilename = concatstr(3, listdir,
+ "/moderation/subscribe", param);
+ if(stat(gatekeepfilename, &stbuf) < 0) {
+ myfree(gatekeepfilename);
+ /* no mail to moderate */
+ errno = 0;
+ log_error(LOG_ARGS, "An obstruct request was"
+ " sent with a mismatching cookie."
+ " Ignoring mail");
+ return -1;
+ }
+ log_oper(listdir, OPLOGFNAME, "%s obstructed %s",
+ fromemails->emaillist[0], param);
+ myfree(param);
+ if (unlink(gatekeepfilename) != 0) {
+ log_error(LOG_ARGS, "Could not unlink %s",
+ gatekeepfilename);
+ myfree(gatekeepfilename);
+ exit(EXIT_FAILURE);
+ }
+ myfree(gatekeepfilename);
+ break;
+
/* listname+help@domain.tld */
case CTRL_HELP:
if(!strchr(fromemails->emaillist[0], '@')) {
text *txt;
memory_lines_state *mls;
char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL;
- char *mailbasename = mybasename(mailfilename), *tmp, *to;
+ char *mailbasename = mybasename(mailfilename), *tmp, *to, *reject;
int moderatorsfd, foundaddr = 0, notifymod = 0, status;
pid_t childpid, pid;
#if 0
myfree(moderators);
listdelim = getlistdelim(listdir);
- replyto = concatstr(6, listname, listdelim, "moderate-", mailbasename,
+ replyto = concatstr(6, listname, listdelim, "release-", mailbasename,
+ "@", listfqdn);
+ reject = concatstr(6, listname, listdelim, "reject-", mailbasename,
"@", listfqdn);
from = concatstr(4, listname, listdelim, "owner@", listfqdn);
register_unformatted(txt, "posteraddr", posteraddr);
register_unformatted(txt, "moderateaddr", replyto); /* DEPRECATED */
register_unformatted(txt, "releaseaddr", replyto);
+ register_unformatted(txt, "rejectaddr", reject);
register_unformatted(txt, "moderators", "%moderators%"); /* DEPRECATED */
register_formatted(txt, "moderators",
rewind_memory_lines, get_memory_line, mls);
text *txt;
memory_lines_state *mls;
char *a = NULL, *queuefilename, *from, *listname, *listfqdn, *str;
- char *modfilename, *randomstr, *mods, *to, *replyto, *moderators = NULL;
- char *modfilebase;
+ char *modfilename, *mods, *to, *replyto, *moderators = NULL;
+ char *cookie, *obstruct;
struct strlist *submods;
pid_t childpid, pid;
break;
}
- randomstr = random_str();
- modfilename = concatstr(3, listdir, "/moderation/subscribe",
- randomstr);
- myfree(randomstr);
-
- fd = open(modfilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
- while(fd < 0 && errno == EEXIST) {
- myfree(modfilename);
- randomstr = random_str();
+ for (;;) {
+ cookie = random_str();
modfilename = concatstr(3, listdir, "/moderation/subscribe",
- randomstr);
- myfree(randomstr);
+ cookie);
fd = open(modfilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
+ if (fd < 0) {
+ if (errno == EEXIST) {
+ myfree(cookie);
+ myfree(modfilename);
+ continue;
+ }
+ log_error(LOG_ARGS, "could not create %s"
+ "ignoring request: %s", str);
+ exit(EXIT_FAILURE);
+ }
+ break;
}
- if(fd < 0) {
- log_error(LOG_ARGS, "could not create %s"
- "ignoring request: %s", str);
- exit(EXIT_FAILURE);
- }
+
if(writen(fd, str, strlen(str)) < 0) {
log_error(LOG_ARGS, "could not write to %s"
"ignoring request: %s", str);
listdelim = getlistdelim(listdir);
listfqdn = genlistfqdn(listaddr);
listname = genlistname(listaddr);
- modfilebase = mybasename(modfilename);
from = concatstr(4, listname, listdelim, "owner@", listfqdn);
to = concatstr(3, listname, "-moderators@", listfqdn);
- replyto = concatstr(6, listname, listdelim, "moderate-", modfilebase,
+ replyto = concatstr(6, listname, listdelim, "permit-", cookie,
"@", listfqdn);
- myfree(modfilebase);
+ obstruct = concatstr(6, listname, listdelim, "obstruct-", cookie,
+ "@", listfqdn);
+ myfree(cookie);
for(i = 0; i < submods->count; i++) {
printf("%s", submods->strs[i]);
str = moderators;
register_unformatted(txt, "subaddr", subaddr);
register_unformatted(txt, "moderateaddr", replyto); /* DEPRECATED */
register_unformatted(txt, "permitaddr", replyto);
- register_unformatted(txt, "moderators", "%gatekeepers"); /* DEPRECATED */
+ register_unformatted(txt, "obstructaddr", obstruct);
+ register_unformatted(txt, "moderators", "%gatekeepers%"); /* DEPRECATED */
register_formatted(txt, "gatekeepers",
rewind_memory_lines, get_memory_line, mls);
queuefilename = prepstdreply(txt, listdir, "$listowner$", to, replyto);
{
int fd;
char *readaddr, *readtype, *modfilename;
-
- modfilename = concatstr(3, listdir, "/moderation/", modstr);
+
+ if (strncmp(modstr, "subscribe", 9) == 0)
+ modstr += 9;
+
+ modfilename = concatstr(3, listdir, "/moderation/subscribe", modstr);
fd = open(modfilename, O_RDONLY);
if(fd < 0) {