]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
Implement modonlypost.
authorBen Schmidt <none@none>
Sun, 22 May 2016 13:16:12 +0000 (23:16 +1000)
committerBen Schmidt <none@none>
Sun, 22 May 2016 13:16:12 +0000 (23:16 +1000)
ChangeLog
README.listtexts
TUNABLES
contrib/web/perl-admin/conf/tunables.pl
contrib/web/php-admin/conf/tunables.pl
src/mlmmj-process.c

index cd7e91f3fdd0e1e7d5530cdf0724273fa6319ff9..390fdab35699dda2994ca197d084ff042c2ce34e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+ o Implement modonlypost
 1.2.19.0
  o Add README.footers and footer-related resources
  o Support ESMTP so OpenSMTPD uses 8 bits (Paul Fariello)
index 9e8a78d10fb68ecd4c4baa9d655e093a083a8e53..b2e75c5411309c46f7a4b42d469a9b7d74ae5e56 100644 (file)
@@ -90,6 +90,7 @@ is given in brackets. Those with asterisks (*) are not yet used.
 - deny-sub-obstruct *
 - deny-unsub-unsubbed-{normal|digest|nomail|all} (unsub-notsubscribed)
 - deny-post-subonlypost (subonlypost)
+- deny-post-modonlypost
 - deny-post-access (access)
 - deny-post-maxmailsize (maxmailsize)
 - deny-post-tocc (notintocc)
@@ -352,7 +353,7 @@ appropriate for use in headers. They are:
 - %originalmail%
 - %originalmail N%
   (available only in moderate-post-*, wait-post-* and
-  deny-post-{access|maxmailsize|tocc|subonlypost})
+  deny-post-{access|maxmailsize|tocc|subonlypost|modonlypost})
   the email message being processed (usually a mail being moderated); N
   represents a number, which is how many lines of the message (including
   headers) to include: if omitted, the whole message will be included
@@ -537,8 +538,8 @@ Unformatted substitutions that are available are:
   the address to which to send mail to permit the subscription in question
 
 - $posteraddr$
-  (available only in deny-post-{access|tocc|subonlypost|maxmailsize},
-  moderate-post-* and wait-post-*)
+  (available only in deny-post-{access|tocc|subonlypost|modonlypost|
+  maxmailsize}, moderate-post-* and wait-post-*)
   the from address of the message that was received as determined by Mlmmj
 
 - $random0$
@@ -561,8 +562,8 @@ Unformatted substitutions that are available are:
   the address requested to be (un-)subscribed
 
 - $subject$
-  (available only in deny-post-{access|tocc|subonlypost|maxmailsize},
-  moderate-post-* and wait-post-*)
+  (available only in deny-post-{access|tocc|subonlypost|modonlypost|
+  maxmailsize}, moderate-post-* and wait-post-*)
   the subject line of the message in question
 
 - $text T$
index 749ff702796ee3750d443e55ed5a83782d732141..a9b05cf8ef189b7f26f1591a07b076dbb9f85224 100644 (file)
--- a/TUNABLES
+++ b/TUNABLES
@@ -45,10 +45,15 @@ entire content is used as value, it's marked "text".
    When this file is present, only people who are subscribed to the list,
    are allowed to post to it. The check is made against the "From:" header.
 
+ · modonlypost                        (boolean)
+
+   When this file is present, only people listed in listdir/control/moderators
+   are allowed to post to it. The check is made against the "From:" header.
+
  · modnonsubposts             (boolean)
 
-   When this file is present, all postings from people who are not subscribed
-   to the list will be moderated.
+   When this file is present, all postings from people who are not allowed
+   to post to the list will be moderated instead of denied.
 
  · modreqlife                 (normal)
 
@@ -171,11 +176,12 @@ entire content is used as value, it's marked "text".
  · notoccdenymails            (boolean)
  · noaccessdenymails          (boolean)
  · nosubonlydenymails         (boolean)
+ · nomodonlydenymails         (boolean)
 
    These switches turns off whether mlmmj sends out notification about postings
    being denied due to the listaddress not being in To: or Cc: (see 'tocc'),
    when it was rejected due to an access rule (see 'access') or whether it's a
-   subscribers only posting list (see 'subonlypost').
+   subscribers/moderators only posting list (see 'subonlypost/modonlypost').
 
  · nosubmodmails              (boolean)
 
index d72a055ee82eda2bdd7d273d21731ca4743c20a5..77cf2fe14d9d803158e4ee6ce9550464066b2aaf 100644 (file)
@@ -43,10 +43,20 @@ mlmmj_boolean("subonlypost",
                          "If this option is set, only people who are subscribed to the list, are allowed to post to it. ".
                          "The check is made against the \"From:\" header.");
 
+mlmmj_boolean("modonlypost",
+                         "Moderators only post",
+                         "When this file is present, only people listed in listdir/control/moderators ".
+                         "are allowed to post to it. The check is made against the "From:" header.");
+
 mlmmj_boolean("modnonsubposts",
-                         "Moderate non-subscriber posts",
-                         "If this option is set and subonlypost is enabled, all postings from ".
-                         "people who are not subscribed to the list will be moderated.");
+                         "Moderate non-allowed posts",
+                         "If this option is set, postings from people who are not allowed to post ".
+                         "to the list will be moderated instead of denied.");
+
+mlmmj_string("modreqlife",
+                        "Moderation request lifetime",
+                        "This specifies how long in seconds a mail awaits moderation before it's ".
+                        "discarded. Defaults to 604800 seconds, which is 7 days.");
 
 mlmmj_string("prefix",
                         "Prefix",
@@ -120,8 +130,8 @@ mlmmj_string("digestmaxmails",
 
 mlmmj_string("bouncelife",
                         "Bouncing lifetime",
-                        "Here is specified for how long time in seconds an address can bounce before it's unsubscribed. Defaults ".
-                        "to 432000 seconds, which is 5 days.");
+                        "This specifies how long in seconds an address can bounce before it's ".
+                        "unsubscribed. Defaults to 432000 seconds, which is 5 days.");
 
 mlmmj_boolean("noarchive",
                          "No archive",
@@ -161,6 +171,11 @@ mlmmj_boolean("nosubonlydenymails",
                          "This switch turns off whether mlmmj sends out notification about postings ".
                          "being rejected due to a subscribers only posting list (see 'subonlypost').");
 
+mlmmj_boolean("nomodonlydenymails",
+                         "No moderators only deny mails",
+                         "This switch turns off whether mlmmj sends out notification about postings ".
+                         "being rejected due to a moderators only posting list (see 'modonlypost').");
+
 mlmmj_boolean("nosubmodmails",
                          "No subscription moderated mails",
                          "This switch turns off whether mlmmj sends out notification about ".
index f4592d25d861f27a75616aead4442bd1f29f6dbf..dcb0ba388a35cbaf9a71c0c6c9d9e63aebc14142 100644 (file)
@@ -43,10 +43,20 @@ mlmmj_boolean("subonlypost",
                          "If this option is set, only people who are subscribed to the list, are allowed to post to it. ".
                          "The check is made against the \"From:\" header.");
 
+mlmmj_boolean("modonlypost",
+                         "Moderators only post",
+                         "When this file is present, only people listed in listdir/control/moderators ".
+                         "are allowed to post to it. The check is made against the "From:" header.");
+
 mlmmj_boolean("modnonsubposts",
-                         "Moderate non-subscriber posts",
-                         "If this option is set and subonlypost is enabled, all postings from ".
-                         "people who are not subscribed to the list will be moderated.");
+                         "Moderate non-allowed posts",
+                         "If this option is set, postings from people who are not allowed to post ".
+                         "to the list will be moderated instead of denied.");
+
+mlmmj_string("modreqlife",
+                        "Moderation request lifetime",
+                        "This specifies how long in seconds a mail awaits moderation before it's ".
+                        "discarded. Defaults to 604800 seconds, which is 7 days.");
 
 mlmmj_string("prefix",
                         "Prefix",
@@ -120,8 +130,8 @@ mlmmj_string("digestmaxmails",
 
 mlmmj_string("bouncelife",
                         "Bouncing lifetime",
-                        "Here is specified for how long time in seconds an address can bounce before it's unsubscribed. Defaults ".
-                        "to 432000 seconds, which is 5 days.");
+                        "This specifies how long in seconds an address can bounce before it's ".
+                        "unsubscribed. Defaults to 432000 seconds, which is 5 days.");
 
 mlmmj_boolean("noarchive",
                          "No archive",
@@ -161,6 +171,11 @@ mlmmj_boolean("nosubonlydenymails",
                          "This switch turns off whether mlmmj sends out notification about postings ".
                          "being rejected due to a subscribers only posting list (see 'subonlypost').");
 
+mlmmj_boolean("nomodonlydenymails",
+                         "No moderators only deny mails",
+                         "This switch turns off whether mlmmj sends out notification about postings ".
+                         "being rejected due to a moderators only posting list (see 'modonlypost').");
+
 mlmmj_boolean("nosubmodmails",
                          "No subscription moderated mails",
                          "This switch turns off whether mlmmj sends out notification about ".
index 4c8e959570c2b9b67ba639c682a922fe68e61ae9..264236731c378e1ef3a938d4996c92856f60215a 100644 (file)
@@ -53,6 +53,7 @@
 #include "memory.h"
 #include "log_oper.h"
 #include "unistr.h"
+#include "chomp.h"
 
 enum action {
        ALLOW,
@@ -74,6 +75,7 @@ static char *action_strs[] = {
 
 enum modreason {
        MODNONSUBPOSTS,
+       MODNONMODPOSTS,
        ACCESS,
        MODERATED
 };
@@ -81,23 +83,61 @@ enum modreason {
 
 static char *modreason_strs[] = {
        "modnonsubposts",
+       "modnonmodposts",
        "access",
        "moderated"
 };
 
 
+static int is_moderator(const char *listdir, const char *address,
+               char **moderators) {
+       char *buf, *tmp, *moderatorsfilename;
+       int moderatorsfd, foundaddr = 0;
+
+       moderatorsfilename = concatstr(2, listdir, "/control/moderators");
+       if((moderatorsfd = open(moderatorsfilename, O_RDONLY)) < 0) {
+               log_error(LOG_ARGS, "Could not open '%s'", moderatorsfilename);
+               myfree(moderatorsfilename);
+               exit(EXIT_FAILURE);
+       }
+       myfree(moderatorsfilename);
+
+       while((buf = mygetline(moderatorsfd))) {
+               chomp(buf);
+               if(address && strcasecmp(buf, address) == 0) {
+                       foundaddr = 1;
+                       if (!moderators) {
+                               close(moderatorsfd);
+                               myfree(buf);
+                               return foundaddr;
+                       }
+               }
+               if (moderators) {
+                       tmp = *moderators;
+                       *moderators = concatstr(3, *moderators, buf, "\n");
+                       myfree(tmp);
+               }
+               myfree(buf);
+       }
+
+       close(moderatorsfd);
+       return foundaddr;
+}
+
+
 static void newmoderated(const char *listdir, const char *mailfilename,
                  const char *mlmmjsend, const char *efromsender,
                  const char *subject, const char *posteraddr,
                  enum modreason modreason)
 {
        char *from, *listfqdn, *listname, *moderators = NULL;
-       char *buf, *replyto, *listaddr = getlistaddr(listdir), *listdelim;
+       char *replyto, *listaddr = getlistaddr(listdir), *listdelim;
        text *txt;
        memory_lines_state *mls;
-       char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL;
-       char *mailbasename = mybasename(mailfilename), *tmp, *to, *reject;
-       int moderatorsfd, foundaddr = 0, notifymod = 0, status;
+       char *queuefilename = NULL;
+       const char *efromismod = NULL;
+       char *mailbasename = mybasename(mailfilename), *to, *reject;
+       int notifymod = 0, status;
        pid_t childpid, pid;
 #if 0
        printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename,
@@ -106,35 +146,15 @@ static void newmoderated(const char *listdir, const char *mailfilename,
        listfqdn = genlistfqdn(listaddr);
        listname = genlistname(listaddr);
 
-       moderatorsfilename = concatstr(2, listdir, "/control/moderators");
-       if((moderatorsfd = open(moderatorsfilename, O_RDONLY)) < 0) {
-               log_error(LOG_ARGS, "Could not open '%s'", moderatorsfilename);
-               myfree(moderatorsfilename);
-               exit(EXIT_FAILURE);
-       }
-       myfree(moderatorsfilename);
-
        if(statctrl(listdir, "ifmodsendonlymodmoderate"))
-               efromismod = concatstr(2, efromsender, "\n");
+               efromismod = efromsender;
 
-       while((buf = mygetline(moderatorsfd))) {
-               if(efromismod && strcmp(buf, efromismod) == 0)
-                       foundaddr = 1;
-               tmp = moderators;
-               moderators = concatstr(2, moderators, buf);
-               myfree(buf);
-               myfree(tmp);
-       }
-
-       if(!foundaddr) {
-               myfree(efromismod);
+       if(!is_moderator(listdir, efromismod, &moderators))
                efromismod = NULL;
-       }
 
        if(efromismod) mls = init_memory_lines(efromismod);
        else mls = init_memory_lines(moderators);
 
-       close(moderatorsfd);
        myfree(moderators);
 
        listdelim = getlistdelim(listdir);
@@ -421,6 +441,7 @@ int main(int argc, char **argv)
        int addrtocc = 1, intocc = 0;
        int maxmailsize = 0;
        int notmetoo = 0;
+       int subonlypost = 0, modonlypost = 0, modnonsubposts = 0, foundaddr = 0;
        char *listdir = NULL, *mailfile = NULL, *headerfilename = NULL;
        char *footerfilename = NULL, *donemailname = NULL;
        char *randomstr = NULL, *mqueuename, *omitfilename;
@@ -972,65 +993,86 @@ int main(int argc, char **argv)
                }
        }
 
-       if(!send && (statctrl(listdir, "subonlypost") ||
-                       statctrl(listdir, "modnonsubposts"))) {
+       subonlypost = statctrl(listdir, "subonlypost");
+       modonlypost = statctrl(listdir, "modonlypost");
+       modnonsubposts = statctrl(listdir, "modnonsubposts");
+       /* modnonsubposts implies subonlypost if modonlypost is not set */
+       if (modnonsubposts && !modonlypost) subonlypost = 1;
+
+       if(!send && (subonlypost || modonlypost || modnonsubposts)) {
                /* Don't send a mail about denial to the list, but silently
                 * discard and exit. */
                if (strcasecmp(listaddr, posteraddr) == 0) {
                        log_error(LOG_ARGS, "Discarding %s because"
-                                       " subonlypost was set and From: was"
-                                       " the list address",
+                                       " there are sender restrictions but"
+                                       " From: was the list address",
                                        mailfile);
                        myfree(listaddr);
                        unlink(donemailname);
                        myfree(donemailname);
                        exit(EXIT_SUCCESS);
                }
-               if(is_subbed(listdir, posteraddr, 0) == SUB_NONE) {
-                       if(statctrl(listdir, "modnonsubposts")) {
-                               moderated = 1;
+               if(subonlypost) {
+                       foundaddr = (is_subbed(listdir, posteraddr, 0) !=
+                                       SUB_NONE);
+               } else if (modonlypost) {
+                       foundaddr = is_moderator(listdir, posteraddr, NULL);
+               }
+               if(!foundaddr) {
+                       if(modnonsubposts) {
+                           moderated = 1;
+                           if (subonlypost)
                                modreason = MODNONSUBPOSTS;
+                           else if (modonlypost)
+                               modreason = MODNONMODPOSTS;
                        } else {
-                               if(statctrl(listdir, "nosubonlydenymails")) {
-                                   log_error(LOG_ARGS, "Discarding %s because"
-                                           " subonlypost and"
-                                           " nosubonlydenymails was set",
-                                           mailfile);
-                                   myfree(listaddr);
-                                   unlink(donemailname);
-                                   myfree(donemailname);
-                                   exit(EXIT_SUCCESS);
-                               }
-                               listdelim = getlistdelim(listdir);
-                               listname = genlistname(listaddr);
-                               listfqdn = genlistfqdn(listaddr);
-                               fromaddr = concatstr(4, listname, listdelim,
-                                       "bounces-help@", listfqdn);
-                               txt = open_text(listdir, "deny", "post",
-                                       "subonlypost", NULL, "subonlypost");
-                               MY_ASSERT(txt);
-                               register_unformatted(txt, "subject", subject);
-                               register_unformatted(txt, "posteraddr", posteraddr);
-                               register_originalmail(txt, donemailname);
-                               queuefilename = prepstdreply(txt, listdir,
-                                       "$listowner$", posteraddr, NULL);
-                               MY_ASSERT(queuefilename)
-                               close_text(txt);
+                           if((subonlypost &&
+                                   statctrl(listdir, "nosubonlydenymails")) ||
+                                   (modonlypost &&
+                                   statctrl(listdir, "nomodonlydenymails"))) {
+                               log_error(LOG_ARGS, "Discarding %s because"
+                                       " no{sub|mod}onlydenymails was set",
+                                       mailfile);
                                myfree(listaddr);
-                               myfree(listdelim);
-                               myfree(listname);
-                               myfree(listfqdn);
                                unlink(donemailname);
                                myfree(donemailname);
-                               execlp(mlmmjsend, mlmmjsend,
-                                       "-L", listdir,
-                                       "-l", "1",
-                                       "-T", posteraddr,
-                                       "-F", fromaddr,
-                                       "-m", queuefilename, (char *)NULL);
-
-                               log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend);
-                               exit(EXIT_FAILURE);
+                               exit(EXIT_SUCCESS);
+                           }
+                           listdelim = getlistdelim(listdir);
+                           listname = genlistname(listaddr);
+                           listfqdn = genlistfqdn(listaddr);
+                           fromaddr = concatstr(4, listname, listdelim,
+                                   "bounces-help@", listfqdn);
+                           if (subonlypost) {
+                               txt = open_text(listdir, "deny", "post",
+                                       "subonlypost", NULL, "subonlypost");
+                           } else if (modonlypost) {
+                               txt = open_text(listdir, "deny", "post",
+                                       "modonlypost", NULL, NULL);
+                           }
+                           MY_ASSERT(txt);
+                           register_unformatted(txt, "subject", subject);
+                           register_unformatted(txt, "posteraddr", posteraddr);
+                           register_originalmail(txt, donemailname);
+                           queuefilename = prepstdreply(txt, listdir,
+                                   "$listowner$", posteraddr, NULL);
+                           MY_ASSERT(queuefilename)
+                           close_text(txt);
+                           myfree(listaddr);
+                           myfree(listdelim);
+                           myfree(listname);
+                           myfree(listfqdn);
+                           unlink(donemailname);
+                           myfree(donemailname);
+                           execlp(mlmmjsend, mlmmjsend,
+                                   "-L", listdir,
+                                   "-l", "1",
+                                   "-T", posteraddr,
+                                   "-F", fromaddr,
+                                   "-m", queuefilename, (char *)NULL);
+
+                           log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend);
+                           exit(EXIT_FAILURE);
                        }
                }
        }