]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
This is post crash commit of working copy mmj. Will test compile etc.
authormmj <none@none>
Thu, 23 Sep 2004 14:29:31 +0000 (00:29 +1000)
committermmj <none@none>
Thu, 23 Sep 2004 14:29:31 +0000 (00:29 +1000)
in a minute.

--- ChangeLog   14 Sep 2004 11:06:43 -0000      1.82
+++ ChangeLog   23 Sep 2004 14:25:13 -0000
@@ -1,6 +1,9 @@
- o Avoid message about changing uid in mlmmj-sub by only saying so when doing
-   so
+ o Add support for not archiving the list by touching listdir/control/noarchive
+ o Add 'nomail' version of lists. Subscribers to the nomail version are
+   subscribed, but does not get any mail
+ o Don't talk about changing uid in mlmmj-sub when we're not really doing it
  o Add sanity checks to disallow denial mails going to the list
+ o Add digest functionality
  o Implement -d option for mlmmj-maintd to be able to supply it with a directory
    containing several listdirs, where mlmmj-maintd then will run maintenance
  o Chown option and a fix for mlmmj-make-ml.sh. Thanks Ingo Lameter

21 files changed:
ChangeLog
TUNABLES
VERSION
include/mlmmj-sub.h
include/mlmmj-unsub.h
include/mlmmj.h
include/subscriberfuncs.h
listtexts/notifysub-nomail [new file with mode: 0644]
listtexts/notifyunsub-nomail [new file with mode: 0644]
listtexts/sub-confirm-nomail [new file with mode: 0644]
listtexts/sub-ok-nomail [new file with mode: 0644]
listtexts/unsub-confirm-nomail [new file with mode: 0644]
listtexts/unsub-ok-nomail [new file with mode: 0644]
man/mlmmj-sub.1
man/mlmmj-unsub.1
src/listcontrol.c
src/mlmmj-make-ml.sh
src/mlmmj-send.c
src/mlmmj-sub.c
src/mlmmj-unsub.c
src/subscriberfuncs.c

index 59af172227a8c674c94ab7082c8c2d3656ec7fe6..00ad7bbb742a65d323e6da1aeffce8271d9dad87 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
- o Avoid message about changing uid in mlmmj-sub by only saying so when doing
-   so
+ o Add support for not archiving the list by touching listdir/control/noarchive
+ o Add 'nomail' version of lists. Subscribers to the nomail version are
+   subscribed, but does not get any mail
+ o Don't talk about changing uid in mlmmj-sub when we're not really doing it
  o Add sanity checks to disallow denial mails going to the list
+ o Add digest functionality
  o Implement -d option for mlmmj-maintd to be able to supply it with a directory
    containing several listdirs, where mlmmj-maintd then will run maintenance
  o Chown option and a fix for mlmmj-make-ml.sh. Thanks Ingo Lameter
index 0065988206b58732d9b0f4c22fff4b11dc545b35..bfc4a5236a1ac5ae2527b87144451742c980e1a1 100644 (file)
--- a/TUNABLES
+++ b/TUNABLES
@@ -93,3 +93,8 @@ to specify several entries (one pr. line), it's marked "list".
 
    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.
+
+ ยท noarchive                   (boolean)
+
+   If this file exists, the mail won't be saved in the archive but simply
+   deleted.
diff --git a/VERSION b/VERSION
index 7dea76edb3dc51b6e5e8223e9f941a35c1e364d6..3b9f2caa7b803d042b25e6d87c781c1c2a1ec0d8 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.1
+1.1-pre-09182004
index e0d0a614310332103d98c83414efdf8426bfb0b0..c17c2da724dd7773eaa523b065abe61ef62adb69 100644 (file)
 #ifndef MLMMJ_SUBSCRIBE_H
 #define MLMMJ_SUBSCRIBE_H
 
+#include <mlmmj.h>
+
 void confirm_sub(const char *listdir, const char *listaddr,
-                const char *subaddr, const char *mlmmjsend, int digest);
+                const char *subaddr, const char *mlmmjsend,
+                enum subtype typesub);
 void generate_subconfirm(const char *listdir, const char *listadr,
                const char *subaddr, const char *mlmmjsend,
-               int digest);
+               enum subtype typesub);
 
 #endif /* MLMMJ_SUBSCRIBE_H */
index 974f926bbc2cdae3a3aadee60cd80e5596ba7eca..36bc5e5ab1b38e181dac5fb540f1b9fdd6abbd42 100644 (file)
 #include <sys/types.h>
 
 void confirm_unsub(const char *listdir, const char *listaddr,
-                  const char *subaddr, const char *mlmmj, int digest);
+                  const char *subaddr, const char *mlmmj,
+                  enum subtype typesub);
 ssize_t unsubscribe(int subreadfd, int subwritefd, const char *address);
 void generate_unsubconfirm(const char *listdir, const char *listaddr,
                           const char *subaddr, const char *mlmmjsend,
-                          int digest);
+                          enum subtype typesub);
 
 #endif /* MLMMJ_UNSUBSCRIBE_H */
index eb8dd912586db6bc2ea60e299a16bb5a2f47807e..52a58d3f9ffb491ab38b34966bb0f6eb8276eb5f 100644 (file)
@@ -65,6 +65,13 @@ struct mailhdr {
        char **values;
 };
 
+/* Has to go here, since it's used in many places */
+enum subtype {
+       SUB_NORMAL,
+       SUB_DIGEST,
+       SUB_NOMAIL
+};
+
 void print_version(const char *prg);
 
 #define MY_ASSERT(expression) if (!(expression)) { \
index c70abf18a69ea224c93b552e5aea201dcb31600d..e36f2746dc74bbe3eb5f6c7128cab98d9e3e1a5a 100644 (file)
@@ -25,6 +25,7 @@
 #define SUBSCRIBERFUNC_H
 
 off_t find_subscriber(int fd, const char *address);
+int is_subbed_in(const char *subddirname, const char *address);
 int is_subbed(const char *listdir, const char *address);
 
 #endif /* SUBSCRIBERFUNC_H */
diff --git a/listtexts/notifysub-nomail b/listtexts/notifysub-nomail
new file mode 100644 (file)
index 0000000..f263a98
--- /dev/null
@@ -0,0 +1,10 @@
+Hi, this is the mlmmj program managing the mailinglist
+
+*LSTADDR*
+
+
+The following address has just subscribed to the nomail version of the
+mailinglist:
+
+*SUBADDR*
+
diff --git a/listtexts/notifyunsub-nomail b/listtexts/notifyunsub-nomail
new file mode 100644 (file)
index 0000000..1c01b96
--- /dev/null
@@ -0,0 +1,10 @@
+Hi, this is the mlmmj program managing the mailinglist
+
+*LSTADDR*
+
+
+The following address has just unsubscribed from the nomail version of
+mailinglist:
+
+*SUBADDR*
+
diff --git a/listtexts/sub-confirm-nomail b/listtexts/sub-confirm-nomail
new file mode 100644 (file)
index 0000000..b4759fe
--- /dev/null
@@ -0,0 +1,31 @@
+Hi, this is the mlmmj program managing the mailinglist
+
+*LSTADDR*
+
+
+To confirm you want the address
+
+*SUBADDR*
+
+
+added to the nomail version of this list, please send a reply to
+
+*CNFADDR*
+
+
+You are getting this mail because of two possible scenarios:
+
+1) You want to be subscribed to the list without getting any mail from it,
+   because you have other means of reading it, and have sent an email
+   specifically to subscribe
+
+2) You have tried to post to a list that only allows posting from sub-
+   scribers. In this case simply reply to this mail, and you will be
+   able to post to the list with this emailaddress in the future
+
+Your mailer probably automatically replies to this address, when you hit
+the reply button.
+
+This confirmation serves two purposes. It tests that mail can be sent to your
+address. Second, it makes sure someone else did not try and subscribe your
+emailaddress.
diff --git a/listtexts/sub-ok-nomail b/listtexts/sub-ok-nomail
new file mode 100644 (file)
index 0000000..89a2345
--- /dev/null
@@ -0,0 +1,6 @@
+WELCOME! You have been subscribed to the nomail version of the
+
+*LSTADDR*
+
+
+mailinglist.
diff --git a/listtexts/unsub-confirm-nomail b/listtexts/unsub-confirm-nomail
new file mode 100644 (file)
index 0000000..33260de
--- /dev/null
@@ -0,0 +1,21 @@
+Hi, this is the mlmmj program managing the mailinglist
+
+*LSTADDR*
+
+
+To confirm you want the address
+
+*SUBADDR*
+
+
+removed from the nomail version of this list, please send a reply to
+
+*CNFADDR*
+
+
+Your mailer probably automatically replies to this address, when you hit
+the reply button.
+
+If you're not subscribed with this list, you will recieve no reply. You can
+see in the From header of a mail to the mailinglist which mail you're sub-
+scribed with.
diff --git a/listtexts/unsub-ok-nomail b/listtexts/unsub-ok-nomail
new file mode 100644 (file)
index 0000000..c2c44c2
--- /dev/null
@@ -0,0 +1,6 @@
+GOODBYE! You have been removed from the nomail version of the
+
+*LSTADDR*
+
+
+mailinglist.
index 63aac5cd9dc6135eb6c1c323579c42eeba3e305d..c92fec3f03ac28b035301f0d6160466865ff8b82 100644 (file)
@@ -3,19 +3,23 @@
 mlmmj-sub \- subscribe address to a mailinglist run by mlmmj
 .SH SYNOPSIS
 .B mlmmj-sub
-\fI-L /path/to/list -a john@doe.org \fR[\fI-c\fR | \fI-C\fR] [\fI-h\fR]
-[\fI-U\fR] [\fI-V\fR]
+\fI-L /path/to/list -a john@doe.org \fR[\fI-c\fR | \fI-C\fR] \fR[\fI-d\fR | \fI-n\fR]
+[\fI-h\fR] [\fI-U\fR] [\fI-V\fR]
 .HP
 \fB\-a\fR: Email address to subscribe
 .HP
 \fB\-c\fR: Send welcome mail
 .HP
+\fB\-d\fR: Subscribe to digest version of the list
+.HP
 \fB\-C\fR: Request mail confirmation
 .HP
 \fB\-h\fR: This help
 .HP
 \fB\-L\fR: Full path to list directory
 .HP
+\fB\-n\fR: Subscribe to nomail version of the list
+.HP
 \fB\-U\fR: Don't switch to the user id of the listdir owner
 .HP
 \fB\-V\fR: Print version
@@ -28,6 +32,11 @@ Unless the \fB\-U\fR switch is used it will switch its user id to the user id
 owning the list directory. This is done to make sure that new files created are
 having correct permissions.
 
+The nomail version of the list is a list version where people are subscribed
+like usual, but they won't recieve any postings to the list. This is useful for
+people who read the mailinglist through a news gateway, but want to be able to
+post to the list.
+
 When neither \fB\-c\fR nor \fB\-C\fR are specified, subscription silently
 happens.
 .SH "SEE ALSO"
index b2767eb7528c89961bf95b89869e55cff071c87c..5bf709a84fe851ceb01c7fc3a47225718d38231d 100644 (file)
@@ -4,7 +4,7 @@ mlmmj-unsub \- manual page for mlmmj-unsub
 .SH SYNOPSIS
 .B mlmmj-sub
 \fI-L /path/to/list -a john@doe.org \fR[\fI-c\fR | \fI-C\fR] [\fI-h\fR]
-[\fI-V\fR]
+\fR[\fI-d\fR | \fI-n\fR] [\fI-V\fR]
 .HP
 \fB\-a\fR: Email address to unsubscribe
 .HP
@@ -12,10 +12,14 @@ mlmmj-unsub \- manual page for mlmmj-unsub
 .HP
 \fB\-C\fR: Request mail confirmation
 .HP
+\fB\-d\fR: Unsubscribe from the digest version of the list
+.HP
 \fB\-h\fR: This help
 .HP
 \fB\-L\fR: Full path to list directory
 .HP
+\fB\-n\fR: Unsubscribe from the nomail version of the list
+.HP
 \fB\-V\fR: Print version
 .SH DESCRIPTION
 This utility is used to unsubscribe people from the specified mailinglist. It
index 62b9e16b615010b663cbdedc55acb4cc5595bb1b..8682fa9216ffc56e31c06ed551b0e34c82527f9f 100644 (file)
 
 enum ctrl_e {
        CTRL_SUBSCRIBE_DIGEST,
+       CTRL_SUBSCRIBE_NOMAIL,
        CTRL_SUBSCRIBE,
        CTRL_CONFSUB_DIGEST,
+       CTRL_CONFSUB_NOMAIL,
        CTRL_CONFSUB,
        CTRL_UNSUBSCRIBE_DIGEST,
+       CTRL_UNSUBSCRIBE_NOMAIL,
        CTRL_UNSUBSCRIBE,
        CTRL_CONFUNSUB_DIGEST,
+       CTRL_CONFUNSUB_NOMAIL,
        CTRL_CONFUNSUB,
        CTRL_BOUNCES,
        CTRL_MODERATE,
@@ -70,12 +74,16 @@ struct ctrl_command {
  * first to match correctly. */
 static struct ctrl_command ctrl_commands[] = {
        { "subscribe-digest",   0 },
+       { "subscribe-nomail",   0 },
        { "subscribe",          0 },
        { "confsub-digest",     1 },
+       { "confsub-nomail",     1 },
        { "confsub",            1 },
        { "unsubscribe-digest", 0 },
+       { "unsubscribe-nomail", 0 },
        { "unsubscribe",        0 },
        { "confunsub-digest",   1 },
+       { "confunsub-nomail",   1 },
        { "confunsub",          1 },
        { "bounces",            1 },
        { "moderate",           1 },
@@ -167,6 +175,24 @@ int listcontrol(struct email_container *fromemails, const char *listdir,
                exit(EXIT_FAILURE);
                break;
 
+       /* listname+subscribe-nomail@domain.tld */
+       case CTRL_SUBSCRIBE_NOMAIL:
+               unlink(mailname);
+               if (closedlist)
+                       exit(EXIT_SUCCESS);
+               if (!strchr(fromemails->emaillist[0], '@'))
+                       /* Not a valid From: address, silently ignore */
+                       exit(EXIT_SUCCESS);
+               execlp(mlmmjsub, mlmmjsub,
+                               "-L", listdir,
+                               "-a", fromemails->emaillist[0],
+                               "-n",
+                               "-C", NULL);
+               log_error(LOG_ARGS, "execlp() of '%s' failed",
+                                       mlmmjsub);
+               exit(EXIT_FAILURE);
+               break;
+
        /* listname+subscribe@domain.tld */
        case CTRL_SUBSCRIBE:
                unlink(mailname);
@@ -209,6 +235,31 @@ int listcontrol(struct email_container *fromemails, const char *listdir,
                exit(EXIT_FAILURE);
                break;
 
+       /* listname+subconf-nomail-COOKIE@domain.tld */
+       case CTRL_CONFSUB_NOMAIL:
+               unlink(mailname);
+               if (closedlist)
+                       exit(EXIT_SUCCESS);
+               conffilename = concatstr(3, listdir, "/subconf/", param);
+               myfree(param);
+               if((tmpfd = open(conffilename, O_RDONLY)) < 0) {
+                       /* invalid COOKIE, silently ignore */
+                       exit(EXIT_SUCCESS);
+               }
+               tmpstr = mygetline(tmpfd);
+               chomp(tmpstr);
+               close(tmpfd);
+               unlink(conffilename);
+               execlp(mlmmjsub, mlmmjsub,
+                               "-L", listdir,
+                               "-a", tmpstr,
+                               "-n",
+                               "-c", NULL);
+               log_error(LOG_ARGS, "execlp() of '%s' failed",
+                               mlmmjsub);
+               exit(EXIT_FAILURE);
+               break;
+
        /* listname+subconf-COOKIE@domain.tld */
        case CTRL_CONFSUB:
                unlink(mailname);
@@ -251,6 +302,24 @@ int listcontrol(struct email_container *fromemails, const char *listdir,
                exit(EXIT_FAILURE);
                break;
 
+       /* listname+unsubscribe-nomail@domain.tld */
+       case CTRL_UNSUBSCRIBE_NOMAIL:
+               unlink(mailname);
+               if (closedlist)
+                       exit(EXIT_SUCCESS);
+               if (!strchr(fromemails->emaillist[0], '@'))
+                       /* Not a valid From: address, silently ignore */
+                       exit(EXIT_SUCCESS);
+               execlp(mlmmjunsub, mlmmjunsub,
+                               "-L", listdir,
+                               "-a", fromemails->emaillist[0],
+                               "-n",
+                               "-C", NULL);
+               log_error(LOG_ARGS, "execlp() of '%s' failed",
+                               mlmmjunsub);
+               exit(EXIT_FAILURE);
+               break;
+
        /* listname+unsubscribe@domain.tld */
        case CTRL_UNSUBSCRIBE:
                unlink(mailname);
@@ -293,6 +362,31 @@ int listcontrol(struct email_container *fromemails, const char *listdir,
                exit(EXIT_FAILURE);
                break;
 
+       /* listname+unsubconf-nomail-COOKIE@domain.tld */
+       case CTRL_CONFUNSUB_NOMAIL:
+               unlink(mailname);
+               if (closedlist)
+                       exit(EXIT_SUCCESS);
+               conffilename = concatstr(3, listdir, "/unsubconf/", param);
+               myfree(param);
+               if((tmpfd = open(conffilename, O_RDONLY)) < 0) {
+                       /* invalid COOKIE, silently ignore */
+                       exit(EXIT_SUCCESS);
+               }
+               tmpstr = mygetline(tmpfd);
+               close(tmpfd);
+               chomp(tmpstr);
+               unlink(conffilename);
+               execlp(mlmmjunsub, mlmmjunsub,
+                               "-L", listdir,
+                               "-a", tmpstr,
+                               "-n",
+                               "-c", NULL);
+               log_error(LOG_ARGS, "execlp() of '%s' failed",
+                               mlmmjunsub);
+               exit(EXIT_FAILURE);
+               break;
+
        /* listname+unsubconf-COOKIE@domain.tld */
        case CTRL_CONFUNSUB:
                unlink(mailname);
index 55d8a2e2ceba359c70a1c190ea60cbd16bac49e2..04b5d7c011413dbb7c9cfeb5f4002ccc0fa7a87a 100755 (executable)
@@ -67,7 +67,8 @@ LISTDIR="$SPOOLDIR/$LISTNAME"
 mkdir -p $LISTDIR
 
 for DIR in incoming queue queue/discarded archive text subconf unsubconf \
-          bounce control moderation subscribers.d digesters.d requeue
+          bounce control moderation subscribers.d digesters.d requeue \
+          nomailsubs.d
 do
        mkdir "$LISTDIR"/"$DIR"
 done
index 80e722049bce38e62f34ae475b3fd7e06bcb0f63..9e12fac02cc2b279b79efe7feb14215dd4da107d 100644 (file)
@@ -472,6 +472,7 @@ int main(int argc, char **argv)
        size_t len = 0, hdrslen, bodylen;
        int sockfd = 0, mailfd = 0, opt, mindex, subfd, tmpfd;
        int deletewhensent = 1, sendres, archive = 1, digest = 0;
+       int ctrlarchive;
        char *listaddr, *mailfilename = NULL, *subfilename = NULL;
        char *replyto = NULL, *bounceaddr = NULL, *to_addr = NULL;
        char *relayhost = NULL, *archivefilename = NULL, *tmpstr;
@@ -611,6 +612,7 @@ int main(int argc, char **argv)
 
        addtohdr = statctrl(listdir, "addtohdr");
        memmailsizestr = ctrlvalue(listdir, "memorymailsize");
+       ctrlarchive = statctrl(listdir, "noarchive");
        if(memmailsizestr) {
                memmailsize = strtol(memmailsizestr, NULL, 10);
                myfree(memmailsizestr);
@@ -865,7 +867,10 @@ int main(int argc, char **argv)
        close(mailfd);
        
        if(archive) {
-               rename(mailfilename, archivefilename);
+               if(!ctrlarchive)
+                       rename(mailfilename, archivefilename);
+               else
+                       unlink(mailfilename);
                myfree(archivefilename);
        } else if(deletewhensent)
                unlink(mailfilename);
index aef205f9093f79f738d202ab6c9e127e1a3fb48b..4f01c65c7d0aa769834848bd9e4670cf0521e4ec 100644 (file)
 
 void confirm_sub(const char *listdir, const char *listaddr,
                const char *subaddr, const char *mlmmjsend,
-               int digest)
+               enum subtype typesub)
 {
        int subtextfd, queuefd;
        char *buf, *subtextfilename, *randomstr, *queuefilename = NULL;
-       char *fromaddr, *listname, *listfqdn, *s1;
+       char *fromaddr, *listname, *listfqdn, *s1, *subject;
 
-       if (!digest) {
-               subtextfilename = concatstr(2, listdir, "/text/sub-ok");
-       } else {
-               subtextfilename = concatstr(2, listdir, "/text/sub-ok-digest");
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-ok");
+                       break;
+               case SUB_DIGEST:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-ok-digest");
+                       break;
+               case SUB_NOMAIL:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-ok-nomail");
+                       break;
        }
 
        if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) {
@@ -89,16 +98,23 @@ void confirm_sub(const char *listdir, const char *listaddr,
 
        fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
 
-       if (!digest) {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                               "\nTo: ", subaddr, "\nSubject: Welcome to ",
-                               listaddr, "\n\n");
-       } else {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                               "\nTo: ", subaddr, "\nSubject: Welcome to "
-                               "digest of ", listaddr, "\n\n");
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subject = mystrdup("to ");
+                       break;
+               case SUB_DIGEST:
+                       subject = mystrdup("to digest of ");
+                       break;
+               case SUB_NOMAIL:
+                       subject = mystrdup("to nomail version of ");
+                       break;
        }
 
+       s1 = concatstr(10, "From: ", listname, "+help@", listfqdn, "\nTo: ",
+                          subaddr, "\nSubject: Welcome ", subject, listaddr,
+                          "\n\n");
+       myfree(subject);
+
        if(writen(queuefd, s1, strlen(s1)) < 0) {
                log_error(LOG_ARGS, "Could not write welcome mail");
                exit(EXIT_FAILURE);
@@ -138,11 +154,11 @@ void confirm_sub(const char *listdir, const char *listaddr,
 
 void notify_sub(const char *listdir, const char *listaddr,
                const char *subaddr, const char *mlmmjsend,
-               int digest)
+               enum subtype typesub)
 {
        char *maildata[4] = { "*LSTADDR*", NULL, "*SUBADDR*", NULL };
        char *listfqdn, *listname, *fromaddr, *fromstr, *subject;
-       char *queuefilename = NULL;
+       char *queuefilename = NULL, *listtext;
 
        listname = genlistname(listaddr);
        listfqdn = genlistfqdn(listaddr);
@@ -150,19 +166,31 @@ void notify_sub(const char *listdir, const char *listaddr,
        maildata[3] = mystrdup(subaddr);
        fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
        fromstr = concatstr(3, listname, "+owner@", listfqdn);
-       if (!digest) {
-               subject = concatstr(2, "New subscription to ", listaddr);
-               queuefilename = prepstdreply(listdir, "notifysub", fromstr,
-                                               fromstr, NULL, subject, 2,
-                                               maildata);
-       } else {
-               subject = concatstr(2, "New subscription to digest of ",
+
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subject  = concatstr(2,
+                                       "New subscription to ", listaddr);
+                       listtext = mystrdup("notifysub");
+                       break;
+               case SUB_DIGEST:
+                       subject = concatstr(2,
+                                       "New subscription to digest of ",
+                                       listaddr);
+                       listtext = mystrdup("notifysub-digest");
+                       break;
+               case SUB_NOMAIL:
+                       subject = concatstr(2,
+                                       "New subscription to nomail of ",
                                        listaddr);
-               queuefilename = prepstdreply(listdir, "notifysub-digest",
-                                               fromstr, fromstr, NULL,
-                                               subject, 2, maildata);
+                       listtext = mystrdup("notifysub-nomail");
+                       break;
        }
+
+       queuefilename = prepstdreply(listdir, listtext, fromstr, fromstr,
+                                    NULL, subject, 2, maildata);
        MY_ASSERT(queuefilename)
+       myfree(listtext);
        myfree(listname);
        myfree(listfqdn);
        myfree(subject);
@@ -182,12 +210,12 @@ void notify_sub(const char *listdir, const char *listaddr,
 
 void generate_subconfirm(const char *listdir, const char *listaddr,
                         const char *subaddr, const char *mlmmjsend,
-                        int digest)
+                        enum subtype typesub)
 {
        int subconffd, subtextfd, queuefd;
        char *confirmaddr, *listname, *listfqdn, *confirmfilename = NULL;
        char *subtextfilename, *queuefilename = NULL, *fromaddr;
-       char *buf, *s1, *randomstr = NULL;
+       char *buf, *s1, *randomstr = NULL, *tmpstr, *subject;
 
        listname = genlistname(listaddr);
        listfqdn = genlistfqdn(listaddr);
@@ -224,18 +252,29 @@ void generate_subconfirm(const char *listdir, const char *listaddr,
 
        fromaddr = concatstr(5, listname, "+bounces-confsub-", randomstr,
                                "@", listfqdn);
-
-       if (!digest) {
-               subtextfilename = concatstr(2, listdir, "/text/sub-confirm");
-               confirmaddr = concatstr(5, listname, "+confsub-",
-                                       randomstr, "@", listfqdn);
-       } else {
-               subtextfilename = concatstr(2, listdir, "/text/sub-confirm-digest");
-               confirmaddr = concatstr(5, listname, "+confsub-digest-",
-                                       randomstr, "@", listfqdn);
+       
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-confirm");
+                       tmpstr = mystrdup("+confsub-");
+                       break;
+               case SUB_DIGEST:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-confirm-digest");
+                       tmpstr = mystrdup("+confsub-digest-");
+                       break;
+               case SUB_NOMAIL:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-confirm-nomail");
+                       tmpstr = mystrdup("+confsub-nomail-");
+                       break;
        }
 
+       confirmaddr = concatstr(5, listname, tmpstr, randomstr, "@", listfqdn);
+
        myfree(randomstr);
+       myfree(tmpstr);
 
        if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) {
                log_error(LOG_ARGS, "Could not open '%s'", subtextfilename);
@@ -262,16 +301,23 @@ void generate_subconfirm(const char *listdir, const char *listaddr,
                exit(EXIT_FAILURE);
        }
 
-       if (!digest) {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                       "\nTo: ", subaddr, "\nSubject: Confirm subscribe to ",
-                       listaddr, "\n\n");
-       } else {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                       "\nTo: ", subaddr, "\nSubject: Confirm subscribe to "
-                       "digest of ", listaddr, "\n\n");
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subject = mystrdup("to ");
+                       break;
+               case SUB_DIGEST:
+                       subject = mystrdup("to digest of ");
+                       break;
+               case SUB_NOMAIL:
+                       subject = mystrdup("to nomail version of ");
+                       break;
        }
 
+       s1 = concatstr(10, "From: ", listname, "+help@", listfqdn, "\nTo: ",
+                          subaddr, "\nSubject: Confirm subscribe ", subject,
+                          listaddr, "\n\n");
+       myfree(subject);
+
        if(writen(queuefd, s1, strlen(s1)) < 0) {
                log_error(LOG_ARGS, "Could not write subconffile");
                exit(EXIT_FAILURE);
@@ -326,13 +372,14 @@ void generate_subconfirm(const char *listdir, const char *listaddr,
 static void print_help(const char *prg)
 {
        printf("Usage: %s -L /path/to/list -a john@doe.org "
-              "[-c] [-C] [-h]\n       [-L] [-U] [-V]\n"
+              "[-c] [-C] [-h]\n       [-L] [-d | -n] [-U] [-V]\n"
               " -a: Email address to subscribe \n"
               " -c: Send welcome mail\n"
               " -C: Request mail confirmation\n"
               " -d: Subscribe to digest of list\n"
               " -h: This help\n"
               " -L: Full path to list directory\n"
+              " -n: Subscribe to no mail version of list\n"
               " -U: Don't switch to the user id of the listdir owner\n"
               " -V: Print version\n"
               "When no options are specified, subscription silently "
@@ -343,14 +390,15 @@ static void print_help(const char *prg)
 int main(int argc, char **argv)
 {
        char *listaddr, *listdir = NULL, *address = NULL, *subfilename = NULL;
-       char *mlmmjsend, *bindir, chstr[2];
+       char *mlmmjsend, *bindir, chstr[2], *subdir;
        int subconfirm = 0, confirmsub = 0, opt, subfilefd, lock, notifysub;
-       int changeuid = 1, status, digest = 0;
+       int changeuid = 1, status, digest = 0, nomail = 0;
        size_t len;
        off_t suboff;
        struct stat st;
        pid_t pid, childpid;
        uid_t uid;
+       enum subtype typesub = SUB_NORMAL;
 
        CHECKFULLPATH(argv[0]);
 
@@ -360,7 +408,7 @@ int main(int argc, char **argv)
        mlmmjsend = concatstr(2, bindir, "/mlmmj-send");
        myfree(bindir);
 
-       while ((opt = getopt(argc, argv, "hcCdVL:a:")) != -1) {
+       while ((opt = getopt(argc, argv, "hcCdnVL:a:")) != -1) {
                switch(opt) {
                case 'a':
                        address = optarg;
@@ -380,6 +428,9 @@ int main(int argc, char **argv)
                case 'L':
                        listdir = optarg;
                        break;
+               case 'n':
+                       nomail = 1;
+                       break;
                case 'U':
                        changeuid = 0;
                        break;
@@ -388,12 +439,24 @@ int main(int argc, char **argv)
                        exit(0);
                }
        }
+       
        if(listdir == 0 || address == 0) {
                fprintf(stderr, "You have to specify -L and -a\n");
                fprintf(stderr, "%s -h for help\n", argv[0]);
                exit(EXIT_FAILURE);
        }
 
+       if(digest && nomail) {
+               fprintf(stderr, "Specify either -d or -n, not both\n");
+               fprintf(stderr, "%s -h for help\n", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       if(digest)
+               typesub = SUB_DIGEST;
+       if(nomail)
+               typesub = SUB_NOMAIL;
+
        if(confirmsub && subconfirm) {
                fprintf(stderr, "Cannot specify both -C and -c\n");
                fprintf(stderr, "%s -h for help\n", argv[0]);
@@ -422,11 +485,21 @@ int main(int argc, char **argv)
 
        chstr[0] = address[0];
        chstr[1] = '\0';
-       if (!digest) {
-               subfilename = concatstr(3, listdir, "/subscribers.d/", chstr);
-       } else {
-               subfilename = concatstr(3, listdir, "/digesters.d/", chstr);
+       
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subdir = mystrdup("/subscribers.d/");
+                       break;
+               case SUB_DIGEST:
+                       subdir = mystrdup("/digesters.d/");
+                       break;
+               case SUB_NOMAIL:
+                       subdir = mystrdup("/nomailsubs.d/");
+                       break;
        }
+               
+       subfilename = concatstr(3, listdir, subdir, chstr);
+       myfree(subdir);
 
        subfilefd = open(subfilename, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
        if(subfilefd == -1) {
@@ -444,7 +517,7 @@ int main(int argc, char **argv)
        if(suboff == -1) {
                if(subconfirm)
                        generate_subconfirm(listdir, listaddr, address,
-                                           mlmmjsend, digest);
+                                           mlmmjsend, typesub);
                else {
                        lseek(subfilefd, 0L, SEEK_END);
                        len = strlen(address);
@@ -466,7 +539,7 @@ int main(int argc, char **argv)
                if(childpid < 0) {
                        log_error(LOG_ARGS, "Could not fork");
                        confirm_sub(listdir, listaddr, address, mlmmjsend,
-                                       digest);
+                                       typesub);
                }
                
                if(childpid > 0) {
@@ -478,14 +551,14 @@ int main(int argc, char **argv)
                /* child confirms subscription */
                if(childpid == 0)
                        confirm_sub(listdir, listaddr, address, mlmmjsend,
-                                       digest);
+                                       typesub);
        }
 
        notifysub = statctrl(listdir, "notifysub");
 
        /* Notify list owner about subscription */
        if (notifysub)
-               notify_sub(listdir, listaddr, address, mlmmjsend, digest);
+               notify_sub(listdir, listaddr, address, mlmmjsend, typesub);
 
        myfree(listaddr);
 
index 9721fd864adf7553dbb1ff77632764d92502acac..0b336b0d4722033a2aa74dec989b86f04d33343f 100644 (file)
 #include "prepstdreply.h"
 
 void confirm_unsub(const char *listdir, const char *listaddr,
-                  const char *subaddr, const char *mlmmjsend, int digest)
+                  const char *subaddr, const char *mlmmjsend,
+                  enum subtype typesub)
 {
        int subtextfd, queuefd;
        char *buf, *subtextfilename, *randomstr, *queuefilename = NULL;
-       char *fromaddr, *listname, *listfqdn, *s1;
+       char *fromaddr, *listname, *listfqdn, *s1, *subject;
 
-       if (!digest) {
-               subtextfilename = concatstr(2, listdir, "/text/unsub-ok");
-       } else {
-               subtextfilename = concatstr(2, listdir,
-                                           "/text/unsub-ok-digest");
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-ok");
+                       break;
+               case SUB_DIGEST:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-ok-digest");
+                       break;
+               case SUB_NOMAIL:
+                       subtextfilename = concatstr(2, listdir,
+                                       "/text/sub-ok-nomail");
+                       break;
        }
 
        if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) {
@@ -89,16 +98,23 @@ void confirm_unsub(const char *listdir, const char *listaddr,
 
        fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
 
-       if (!digest) {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                       "\nTo: ", subaddr, "\nSubject: Goodbye from ",
-                       listaddr, "\n\n");
-       } else {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                       "\nTo: ", subaddr, "\nSubject: Goodbye from "
-                       "digest of ", listaddr, "\n\n");
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subject = mystrdup("from ");
+                       break;
+               case SUB_DIGEST:
+                       subject = mystrdup("from digest of ");
+                       break;
+               case SUB_NOMAIL:
+                       subject = mystrdup("from nomail version of ");
+                       break;
        }
 
+       s1 = concatstr(10, "From: ", listname, "+help@", listfqdn, "\nTo: ",
+                          subaddr, "\nSubject: Goodbye ", subject, listaddr,
+                          "\n\n");
+       myfree(subject);
+
        if(writen(queuefd, s1, strlen(s1)) < 0) {
                log_error(LOG_ARGS, "Could not write subconffile");
                exit(EXIT_FAILURE);
@@ -137,11 +153,12 @@ void confirm_unsub(const char *listdir, const char *listaddr,
 }
 
 void notify_unsub(const char *listdir, const char *listaddr,
-                 const char *subaddr, const char *mlmmjsend, int digest)
+                 const char *subaddr, const char *mlmmjsend,
+                 enum subtype typesub)
 {
         char *maildata[4] = { "*LSTADDR*", NULL, "*SUBADDR*", NULL };
         char *listfqdn, *listname, *fromaddr, *fromstr, *subject;
-        char *queuefilename = NULL;
+        char *queuefilename = NULL, *listtext;
 
         listname = genlistname(listaddr);
         listfqdn = genlistfqdn(listaddr);
@@ -149,30 +166,44 @@ void notify_unsub(const char *listdir, const char *listaddr,
         maildata[3] = mystrdup(subaddr);
         fromaddr = concatstr(3, listname, "+bounces-help@", listfqdn);
         fromstr = concatstr(3, listname, "+owner@", listfqdn);
-       if (!digest) {
-               subject = concatstr(2, "Unsubscription from ", listaddr);
-               queuefilename = prepstdreply(listdir, "notifyunsub", fromstr,
-                                     fromstr, NULL, subject, 2, maildata);
-       } else {
-               subject = concatstr(2, "Unsubscription from digest of ",
+
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subject = concatstr(2,
+                                       "Unsubscription from ", listaddr);
+                       listtext = mystrdup("notifyunsub");
+                       break;
+               case SUB_DIGEST:
+                       subject = concatstr(2,
+                                       "Unsubscription from digest of ",
                                        listaddr);
-               queuefilename = prepstdreply(listdir, "notifyunsub-digest",
-                                     fromstr, fromstr, NULL, subject, 2,
-                                     maildata);
+                       listtext = mystrdup("notifyunsub-digest");
+                       break;
+               case SUB_NOMAIL:
+                       subject = concatstr(2,
+                                       "Unsubscription from nomail of ",
+                                       listaddr);
+                       listtext = mystrdup("notifyunsub-nomail");
+                       break;
        }
-        MY_ASSERT(queuefilename)
-        myfree(listname);
-        myfree(listfqdn);
-        myfree(subject);
-        myfree(maildata[1]);
-        myfree(maildata[3]);
-        execlp(mlmmjsend, mlmmjsend,
-                        "-l", "1",
-                        "-T", fromstr,
-                        "-F", fromaddr,
-                        "-m", queuefilename, NULL);
-
-        myfree(fromstr);
+
+       
+       queuefilename = prepstdreply(listdir, listtext, fromstr, fromstr,
+                                    NULL, subject, 2, maildata);
+       MY_ASSERT(queuefilename);
+       myfree(listtext);
+       myfree(listname);
+       myfree(listfqdn);
+       myfree(subject);
+       myfree(maildata[1]);
+       myfree(maildata[3]);
+       execlp(mlmmjsend, mlmmjsend,
+                       "-l", "1",
+                       "-T", fromstr,
+                       "-F", fromaddr,
+                       "-m", queuefilename, NULL);
+
+       myfree(fromstr);
 
         log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend);
         exit(EXIT_FAILURE);
@@ -181,11 +212,11 @@ void notify_unsub(const char *listdir, const char *listaddr,
 
 void generate_unsubconfirm(const char *listdir, const char *listaddr,
                           const char *subaddr, const char *mlmmjsend,
-                          int digest)
+                          enum subtype typesub)
 {
-       char *confirmaddr, *buf, *listname, *listfqdn;
+       char *confirmaddr, *buf, *listname, *listfqdn, *tmpstr;
        char *subtextfilename, *queuefilename = NULL, *fromaddr, *s1;
-       char *randomstr = NULL, *confirmfilename = NULL;
+       char *randomstr = NULL, *confirmfilename = NULL, *subject;
        int subconffd, subtextfd, queuefd;
 
        listname = genlistname(listaddr);
@@ -224,18 +255,28 @@ void generate_unsubconfirm(const char *listdir, const char *listaddr,
        fromaddr = concatstr(5, listname, "+bounces-confunsub-", randomstr,
                                "@", listfqdn);
 
-       if (!digest) {
-               subtextfilename = concatstr(2, listdir, "/text/unsub-confirm");
-               confirmaddr = concatstr(5, listname, "+confunsub-", randomstr,
-                                       "@", listfqdn);
-       } else {
-               subtextfilename = concatstr(2, listdir,
-                                       "/text/unsub-confirm-digest");
-               confirmaddr = concatstr(5, listname, "+confunsub-digest-",
-                                       randomstr, "@", listfqdn);
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subtextfilename = concatstr(2, listdir,
+                                               "/text/unsub-confirm");
+                       tmpstr = mystrdup("+confunsub-");
+                       break;
+               case SUB_DIGEST:
+                       subtextfilename = concatstr(2, listdir,
+                                               "/text/unsub-confirm-digest");
+                       tmpstr = mystrdup("+confunsub-digest-");
+                       break;
+               case SUB_NOMAIL:
+                       subtextfilename = concatstr(2, listdir,
+                                               "/text/unsub-confirm-nomail");
+                       tmpstr = mystrdup("+confunsub-nomail-");
+                       break;
        }
 
+       confirmaddr = concatstr(5, listname, tmpstr, randomstr, "@", listfqdn);
+
        myfree(randomstr);
+       myfree(tmpstr);
 
        if((subtextfd = open(subtextfilename, O_RDONLY)) < 0) {
                log_error(LOG_ARGS, "Could not open '%s'", subtextfilename);
@@ -261,17 +302,22 @@ void generate_unsubconfirm(const char *listdir, const char *listaddr,
                exit(EXIT_FAILURE);
        }
 
-       if (!digest) {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                               "\nTo: ", subaddr, "\nSubject: Confirm "
-                               "unsubscribe from ", listaddr, "\n\n");
-       } else {
-               s1 = concatstr(9, "From: ", listname, "+help@", listfqdn,
-                               "\nTo: ", subaddr, "\nSubject: Confirm "
-                               "unsubscribe from digest of ", listaddr,
-                               "\n\n");
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subject = mystrdup("from ");
+                       break;
+               case SUB_DIGEST:
+                       subject = mystrdup("from digest of ");
+                       break;
+               case SUB_NOMAIL:
+                       subject = mystrdup("from nomail version of ");
+                       break;
        }
 
+       s1 = concatstr(10, "From: ", listname, "+help@", listfqdn, "\nTo: ",
+                          subaddr, "\nSubject: Confirm unsubscribe ", subject,
+                          listaddr, "\n\n");
+
        if(writen(queuefd, s1, strlen(s1)) < 0) {
                log_error(LOG_ARGS, "Could not write subconffile");
                exit(EXIT_FAILURE);
@@ -362,13 +408,14 @@ ssize_t unsubscribe(int subreadfd, int subwritefd, const char *address)
 static void print_help(const char *prg)
 {
        printf("Usage: %s -L /path/to/list -a john@doe.org "
-              "[-c] [-C] [-h] [-L] [-V]\n"
+              "[-c] [-C] [-h] [-L] [-d | -n] [-V]\n"
               " -a: Email address to unsubscribe \n"
               " -c: Send goodbye mail\n"
               " -C: Request mail confirmation\n"
               " -d: Subscribe to digest of list\n"
               " -h: This help\n"
               " -L: Full path to list directory\n"
+              " -n: Subscribe to no mail version of list\n"
               " -V: Print version\n"
               "When no options are specified, unsubscription silently "
               "happens\n", prg);
@@ -377,15 +424,16 @@ static void print_help(const char *prg)
 
 int main(int argc, char **argv)
 {
-       int subread, subwrite, rlock, wlock, opt, unsubres, status;
+       int subread, subwrite, rlock, wlock, opt, unsubres, status, nomail = 0;
        int confirmunsub = 0, unsubconfirm = 0, notifysub = 0, digest = 0;
        char *listaddr, *listdir = NULL, *address = NULL, *subreadname = NULL;
-       char *subwritename, *mlmmjsend, *bindir;
+       char *subwritename, *mlmmjsend, *bindir, *subdir;
        char *subddirname;
        off_t suboff;
        DIR *subddir;
        struct dirent *dp;
        pid_t pid, childpid;
+       enum subtype typesub = SUB_NORMAL;
 
        CHECKFULLPATH(argv[0]);
        
@@ -395,11 +443,14 @@ int main(int argc, char **argv)
        mlmmjsend = concatstr(2, bindir, "/mlmmj-send");
        myfree(bindir);
 
-       while ((opt = getopt(argc, argv, "hcCdVL:a:")) != -1) {
+       while ((opt = getopt(argc, argv, "hcCdnVL:a:")) != -1) {
                switch(opt) {
                case 'L':
                        listdir = optarg;
                        break;
+               case 'n':
+                       nomail = 1;
+                       break;
                case 'a':
                        address = optarg;
                        break;
@@ -426,6 +477,17 @@ int main(int argc, char **argv)
                exit(EXIT_FAILURE);
        }
 
+       if(digest && nomail) {
+               fprintf(stderr, "Specify either -d or -n, not both\n");
+               fprintf(stderr, "%s -h for help\n", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       if(digest)
+               typesub = SUB_DIGEST;
+       if(nomail)
+               typesub = SUB_NOMAIL;
+
        if(confirmunsub && unsubconfirm) {
                fprintf(stderr, "Cannot specify both -C and -c\n");
                fprintf(stderr, "%s -h for help\n", argv[0]);
@@ -435,34 +497,50 @@ int main(int argc, char **argv)
        /* get the list address */
        listaddr = getlistaddr(listdir);
 
+       switch(typesub) {
+               case SUB_NORMAL:
+                       subdir = mystrdup("/subscribers.d/");
+                       break;
+               case SUB_DIGEST:
+                       subdir = mystrdup("/digesters.d/");
+                       break;
+               case SUB_NOMAIL:
+                       subdir = mystrdup("/nomailsubs.d/");
+                       break;
+       }
+               
+       subddirname = concatstr(2, listdir, subdir);
+
+       if(is_subbed_in(subddirname, address)) {
+               /* Address is not subscribed, so exit silently */
+               myfree(subddirname);
+               myfree(subdir);
+               myfree(listaddr);
+               exit(EXIT_SUCCESS);
+       }
+
        if(unsubconfirm)
                generate_unsubconfirm(listdir, listaddr, address, mlmmjsend,
-                               digest);
+                               typesub);
 
-       if (!digest) {
-               subddirname = concatstr(2, listdir, "/subscribers.d/");
-       } else {
-               subddirname = concatstr(2, listdir, "/digesters.d/");
-       }
        if((subddir = opendir(subddirname)) == NULL) {
                log_error(LOG_ARGS, "Could not opendir(%s)",
                                    subddirname);
                myfree(subddirname);
+               myfree(subdir);
+               myfree(listaddr);
                exit(EXIT_FAILURE);
        }
+
        myfree(subddirname);
+
        while((dp = readdir(subddir)) != NULL) {
                if(!strcmp(dp->d_name, "."))
                        continue;
                if(!strcmp(dp->d_name, ".."))
                        continue;
-               if (!digest) {
-                       subreadname = concatstr(3, listdir, "/subscribers.d/",
-                               dp->d_name);
-               } else {
-                       subreadname = concatstr(3, listdir, "/digesters.d/",
-                               dp->d_name);
-               }
+               
+               subreadname = concatstr(3, listdir, subdir, dp->d_name);
 
                subread = open(subreadname, O_RDWR);
                if(subread == -1) {
@@ -574,12 +652,13 @@ int main(int argc, char **argv)
                }
         }
 
+       myfree(subdir);
 
         notifysub = statctrl(listdir, "notifysub");
 
         /* Notify list owner about subscription */
         if (notifysub)
-                notify_unsub(listdir, listaddr, address, mlmmjsend, digest);
+                notify_unsub(listdir, listaddr, address, mlmmjsend, typesub);
 
        myfree(listaddr);
 
index 1000c2b4bb72534d174df1b16cdc7b991ebbe479..401105a1698c296381758a4acd2ecc63e2eca689 100644 (file)
@@ -87,7 +87,7 @@ off_t find_subscriber(int fd, const char *address)
        return (off_t)-1;
 }
 
-static int is_subbed_in(const char *subddirname, const char *address)
+int is_subbed_in(const char *subddirname, const char *address)
 {
        int retval = 1, subread;
        char *subreadname;
@@ -148,5 +148,11 @@ int is_subbed(const char *listdir, const char *address)
        if (retval == 0)
                return 0;
 
+       subddirname = concatstr(2, listdir, "/nomailsubs.d/");
+       retval = is_subbed_in(subddirname, address);
+       myfree(subddirname);
+       if (retval == 0)
+               return 0;
+
        return 1;
 }