find recipients for sendmail
authorPhilipp Takacs <philipp@bureaucracy.de>
Sun, 28 Jun 2015 22:42:31 +0000 (00:42 +0200)
committerPhilipp Takacs <philipp@bureaucracy.de>
Sat, 5 Sep 2015 17:18:58 +0000 (19:18 +0200)
Recipients are given as comandline arguments to sendmail.
Also do aliasing on every header which contain an address.

h/addrsbr.h
man/spost.man8
sbr/addrsbr.c
uip/spost.c

index a86a90d..93b1735 100644 (file)
@@ -10,6 +10,8 @@
 #define NETHOST      1
 #define BADHOST      2
 
 #define NETHOST      1
 #define BADHOST      2
 
+#include <stddef.h>
+
 struct mailname {
        struct mailname *m_next;
        char *m_text;
 struct mailname {
        struct mailname *m_next;
        char *m_text;
@@ -34,3 +36,4 @@ int ismymbox(struct mailname *);
 char *getname(char *);
 char *adrformat(struct mailname *);
 struct mailname *getm(char *, char *, int, int, char *);
 char *getname(char *);
 char *adrformat(struct mailname *);
 struct mailname *getm(char *, char *, int, int, char *);
+size_t getmboxes(char *, struct mailname **);
index db783ef..76d10a8 100644 (file)
@@ -43,6 +43,14 @@ searches the `To:', `Cc:', `Bcc:',
 `Fcc:', and `Resent\-xxx:' header lines of the specified
 message for destination addresses,
 .PP
 `Fcc:', and `Resent\-xxx:' header lines of the specified
 message for destination addresses,
 .PP
+.B Sendmail
+is called witch all recipients, expect these from Bcc-field
+.br
+.B sendmail
+.B \-i
+.RB [ \-v ]
+.I recipients ...
+.PP
 If a `Bcc:' field is encountered, its addresses will be used for
 delivery, and the `Bcc:' field will be removed from the message
 sent to sighted recipients.  The blind recipients will receive a newly
 If a `Bcc:' field is encountered, its addresses will be used for
 delivery, and the `Bcc:' field will be removed from the message
 sent to sighted recipients.  The blind recipients will receive a newly
@@ -57,6 +65,10 @@ The `Aliasfile' profile entry
 can be used to specify one or more files that spost
 should take aliases from.
 .PP
 can be used to specify one or more files that spost
 should take aliases from.
 .PP
+Aliasing is done on any address-field will.
+The address-fields are `From:', `To:', `Bcc:',
+or rather the `Resent\-xxx:' versions of this fields.
+.PP
 The
 .B \-verbose
 switch enables informational messages.
 The
 .B \-verbose
 switch enables informational messages.
@@ -93,8 +105,11 @@ Note that this applies equally to `Resent\-From:' lines
 in messages sent with
 .BR dist .
 .PP
 in messages sent with
 .BR dist .
 .PP
-Your MTA is supposed to care to fully qualitfy the addresses
-with the correct domain name.
+.B Spost
+takes care about full qualitfy addresses,
+in every address-field.
+Your MTA is supposed to care to add the correct domain,
+if there is no after aliasing.
 .PP
 The draft is filed to the folders in the Fcc headers by
 .BR refile .
 .PP
 The draft is filed to the folders in the Fcc headers by
 .BR refile .
@@ -130,6 +145,4 @@ send(1), mh\-mail(5), mh\-alias(5), mh\-tailor(5), refile(1),
 None
 
 .SH BUGS
 None
 
 .SH BUGS
-Spost does not qualify addresses.
-.PP
-Spost does only basic processing and checking, yet.
+None
index 53e9be4..ea017f4 100644 (file)
@@ -373,3 +373,28 @@ local_test: ;
 
        return 0;
 }
 
        return 0;
 }
+
+/*
+ * Insert mailname after element and returns the
+ * number of parsed addresses. element is set to
+ * the last parsed addresse.
+ */
+size_t
+getmboxes(char *line, struct mailname **element)
+{
+       struct mailname *mp, *next;
+       char *cp;
+       size_t i = 0;
+
+       next = (*element)->m_next;
+
+       while ((cp = getname(line))) {
+               mp = getm(cp, NULL, 0, AD_HOST, NULL);
+               (*element)->m_next = mp;
+               *element = mp;
+               i++;
+       }
+
+       (*element)->m_next = next;
+       return i;
+}
index 4d0b48a..3a70f36 100644 (file)
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <locale.h>
 #include <sysexits.h>
 #include <unistd.h>
 #include <locale.h>
 #include <sysexits.h>
+#include <errno.h>
 
 #define MAX_SM_FIELD 1476  /* < largest hdr field sendmail will accept */
 
 
 #define MAX_SM_FIELD 1476  /* < largest hdr field sendmail will accept */
 
@@ -115,6 +116,8 @@ static char *tmpfil;
 static char *subject = NULL;  /* the subject field for BCC'ing */
 static char fccs[BUFSIZ] = "";
 struct mailname *bccs = NULL;  /* list of the bcc recipients */
 static char *subject = NULL;  /* the subject field for BCC'ing */
 static char fccs[BUFSIZ] = "";
 struct mailname *bccs = NULL;  /* list of the bcc recipients */
+struct mailname *recipients = NULL;  /* list of the recipients */
+size_t recipientsc = 0;
 struct mailname *sender = NULL;
 
 static struct headers *hdrtab;  /* table for the message we're doing */
 struct mailname *sender = NULL;
 
 static struct headers *hdrtab;  /* table for the message we're doing */
@@ -131,6 +134,7 @@ static int putone(char *, int, int);
 static void process_fcc(char *);
 static void fcc(char *, char *);
 static void process_bccs(char *);
 static void process_fcc(char *);
 static void fcc(char *, char *);
 static void process_bccs(char *);
+static size_t do_aliasing(struct mailname *, struct mailname **);
 
 
 int
 
 
 int
@@ -138,7 +142,7 @@ main(int argc, char **argv)
 {
        int state, compnum;
        char *cp, *msg = NULL, **argp, **arguments;
 {
        int state, compnum;
        char *cp, *msg = NULL, **argp, **arguments;
-       char *sargv[16], buf[BUFSIZ], name[NAMESZ];
+       char **sargv, buf[BUFSIZ], name[NAMESZ];
        FILE *in;
 
        setlocale(LC_ALL, "");
        FILE *in;
 
        setlocale(LC_ALL, "");
@@ -265,7 +269,20 @@ main(int argc, char **argv)
        fclose(in);
 
        if (debug) {
        fclose(in);
 
        if (debug) {
+               struct mailname *i = recipients;
                /* stop here */
                /* stop here */
+               puts("----EOM----");
+               while (i) {
+                       fputs(i->m_mbox, stdout);
+                       if (i->m_host) {
+                               fputs("@", stdout);
+                               fputs(i->m_host, stdout);
+                       }
+                       fputs("\n", stdout);
+                       i = i->m_next;
+                       mnfree(recipients);
+                       recipients = i;
+               }
                exit(EX_OK);
        }
 
                exit(EX_OK);
        }
 
@@ -294,16 +311,36 @@ main(int argc, char **argv)
        }
        unlink(tmpfil);
 
        }
        unlink(tmpfil);
 
+       if (recipientsc == 0) {
+               adios(EX_DATAERR, NULL, "message has no recipients");
+       }
+
+       sargv = mh_xmalloc(sizeof(char **) * (recipientsc + 4));
+
        argp = sargv;
        *argp++ = "send-mail";
        argp = sargv;
        *argp++ = "send-mail";
-       *argp++ = "-m";  /* send to me too */
-       *argp++ = "-t";  /* read msg for recipients */
        *argp++ = "-i";  /* don't stop on "." */
        if (verbose) {
                *argp++ = "-v";
        }
        *argp++ = "-i";  /* don't stop on "." */
        if (verbose) {
                *argp++ = "-v";
        }
+
+       while (recipients != NULL) {
+               cp = getcpy(recipients->m_mbox);
+               if (recipients->m_host) {
+                       cp = add("@", cp);
+                       cp = add(recipients->m_host, cp);
+               }
+               *argp++ = cp;
+               cp = NULL;
+               recipients = recipients->m_next;
+       }
        *argp = NULL;
        *argp = NULL;
-       execv(sendmail, sargv);
+       execvp(sendmail, sargv);
+
+       if (errno == E2BIG) {
+               adios(EX_DATAERR, sendmail, "too much arguments, probably to much recipients");
+       }
+
        adios(EX_OSERR, sendmail, "can't exec");
        return -1;
 }
        adios(EX_OSERR, sendmail, "can't exec");
        return -1;
 }
@@ -315,8 +352,12 @@ static void
 putfmt(char *name, char *str, FILE *out)
 {
        int i;
 putfmt(char *name, char *str, FILE *out)
 {
        int i;
-       char *cp;
        struct headers *hdr;
        struct headers *hdr;
+       struct mailname addr_start, *addr_end;
+       size_t addrc;
+
+       addr_end = &addr_start;
+       addr_end->m_next = NULL;
 
        /* remove leading whitespace */
        while (*str==' ' || *str=='\t') {
 
        /* remove leading whitespace */
        while (*str==' ' || *str=='\t') {
@@ -358,64 +399,26 @@ putfmt(char *name, char *str, FILE *out)
                return;
        }
 
                return;
        }
 
-       if (hdr->flags & HBCC) {
-               struct mailname *mp = NULL;
+       if (hdr->flags & HSUB) {
+               subject = getcpy(str);
+       }
 
 
-               /* Create list of Bcc addrs. */
-               while ((cp = getname(str))) {
-                       mp = getm(cp, NULL, 0, AD_HOST, NULL);
-                       mp->m_next = bccs;  /* push */
-                       bccs = mp;
-               }
+       if (!(hdr->flags & HADR)) {
+               fprintf(out, "%s: %s", name, str);
                return;
        }
 
                return;
        }
 
-       if (aliasflg && hdr->flags & HTRY) {
-               /*
-               ** This header contains address(es) that we have to do
-               ** alias expansion on.  Because of the saved state in
-               ** getname we have to put all the addresses into a list.
-               **/
-               struct mailname *f = NULL;
-               struct mailname *mp = NULL;
+       addrc = getmboxes(str, &addr_end);
 
 
-               while ((cp = getname(str))) {
-                       mp = getm(cp, NULL, 0, AD_HOST, NULL);
-                       if (!f) {
-                               f = mp;
-                               mp->m_next = mp;
-                       } else {
-                               mp->m_next = f->m_next;
-                               f->m_next = mp;
-                               f = mp;
-                       }
-               }
-               f = mp->m_next;
-               mp->m_next = NULL;
-               /* Now munch on the list, possibly expanding aliases */
-               putadr(name, f);
-               return;
+       if (aliasflg) {
+               addrc += do_aliasing(&addr_start, &addr_end);
        }
 
        }
 
-       /*
-       ** The author(s) of spost decided that alias substitution wasn't
-       ** necessary for the non-HTRY headers.  Unfortunately, one of
-       ** those headers is "From:", and having alias substitution work on
-       ** that is extremely useful for someone with a lot of POP3 email
-       ** accounts or aliases.  post supports aliasing of "From:"...
-       **
-       ** Since "From:"-processing is incompletely implemented in this
-       ** unsupported and undocumented spost backend, I'm not going
-       ** to take the time to implement my new draft-From:-based email
-       ** address masquerading.  If I do ever implement it here, I'd almost
-       ** certainly want to implement "From:" line alias processing as well.
-       ** -- Dan Harkless <dan-nmh@dilvish.speed.net>
-       */
-       /*
-       ** Although there is no masquerading anymore in mmh, we might want
-       ** to have aliasing of From: addresses. Think about it.
-       ** -- meillo@marmaro.de  2012-02
-       */
+       if (hdr->flags & HBCC) {
+               addr_end->m_next = bccs;
+               bccs = addr_start.m_next;
+               return;
+       }
 
        if (hdr->set & MFRM) {
                struct mailname *mp = NULL;
 
        if (hdr->set & MFRM) {
                struct mailname *mp = NULL;
@@ -425,38 +428,28 @@ putfmt(char *name, char *str, FILE *out)
                /* needed because the address parser holds global state */
                ismymbox(NULL);
 
                /* needed because the address parser holds global state */
                ismymbox(NULL);
 
-               while ((cp = getname(str)) != NULL) {
-                       fromcnt++;
-                       mp = getm(cp, NULL, 0, AD_NAME, NULL);
+               for ( mp = addr_start.m_next; mp; mp = mp->m_next) {
                        if (ismymbox(mp)) {
                                msgflags |= MFMM;
                                if (my == NULL) {
                                        my = mp;
                        if (ismymbox(mp)) {
                                msgflags |= MFMM;
                                if (my == NULL) {
                                        my = mp;
-                               } else {
-                                       mnfree(mp);
-                                       mp = NULL;
                                }
                                }
-                       } else {
-                               mnfree(mp);
-                               mp = NULL;
                        }
                        }
+                       fromcnt++;
                }
 
                if (fromcnt > 1) {
                        sender = my;
                }
 
                if (fromcnt > 1) {
                        sender = my;
-               } else {
-                       mnfree(my);
                }
                }
-
-               free(cp);
-               cp = NULL;
-
        }
 
        }
 
-       if (hdr->flags & HSUB) {
-               subject = getcpy(str);
+       putadr(name, addr_start.m_next);
+
+       if (hdr->flags & HTRY) {
+               addr_end->m_next = recipients;
+               recipients = addr_start.m_next;
+               recipientsc += i;
        }
        }
-       fprintf(out, "%s: %s", name, str);
 }
 
 
 }
 
 
@@ -535,7 +528,6 @@ putadr(char *name, struct mailname *nl)
 {
        struct mailname *mp, *mp2;
        int linepos;
 {
        struct mailname *mp, *mp2;
        int linepos;
-       char *cp;
        int namelen;
 
        fprintf(out, "%s: ", name);
        int namelen;
 
        fprintf(out, "%s: ", name);
@@ -547,38 +539,9 @@ putadr(char *name, struct mailname *nl)
                        fprintf(out, "\n%s: ", name);
                        linepos = namelen;
                }
                        fprintf(out, "\n%s: ", name);
                        linepos = namelen;
                }
-               if (mp->m_nohost) {
-                       /* a local name - see if it's an alias */
-                       cp = akvalue(mp->m_mbox);
-                       if (cp == mp->m_mbox) {
-                               /* wasn't an alias - use it unchanged */
-                               linepos = putone(mp->m_text, linepos, namelen);
-                       } else {
-                               /* an alias - expand it */
-                               while ((cp = getname(cp))) {
-                                       if (linepos > MAX_SM_FIELD) {
-                                               fprintf(out, "\n%s: ", name);
-                                               linepos = namelen;
-                                       }
-                                       mp2 = getm(cp, NULL, 0, AD_HOST, NULL);
-                                       if (akvisible()) {
-                                               mp2->m_pers = getcpy(mp->m_mbox);
-                                               linepos = putone(adrformat(mp2), linepos, namelen);
-                                       } else {
-                                               linepos = putone(mp2->m_text,
-                                                               linepos,
-                                                               namelen);
-                                       }
-                                       mnfree(mp2);
-                               }
-                       }
-               } else {
-                       /* not a local name - use it unchanged */
-                       linepos = putone(mp->m_text, linepos, namelen);
-               }
+               linepos = putone(mp->m_text, linepos, namelen);
                mp2 = mp;
                mp = mp->m_next;
                mp2 = mp;
                mp = mp->m_next;
-               mnfree(mp2);
        }
        putc('\n', out);
 }
        }
        putc('\n', out);
 }
@@ -698,3 +661,41 @@ process_bccs(char *origmsg)
                }
        }
 }
                }
        }
 }
+
+/*
+ * Do aliasing on a mailname linked list
+ * Begin at start->m_next
+ * End if m_next == NULL
+ * **end is set to the new end.
+ * Return the number of new mainames in the list
+ */
+
+static size_t
+do_aliasing(struct mailname *start, struct mailname **end)
+{
+       struct mailname *prev, *cur;
+       char *cp;
+       size_t i = 0;
+
+       prev = start;
+       cur = prev->m_next;
+
+       while (cur != NULL) {
+               if (cur->m_nohost) {
+                       cp = akvalue(cur->m_mbox);
+                       if (strcmp(cp, cur->m_mbox) != 0) {
+                               prev->m_next = cur->m_next;
+                               i += getmboxes(cp, &prev);
+                               i -= 1;
+                               mnfree(cur);
+                       } else {
+                               prev = cur;
+                       }
+               } else {
+                       prev = cur;
+               }
+               cur = prev->m_next;
+       }
+       *end = prev;
+       return i;
+}