From 00b5842e0c5feef345a8e69cdb501f8a4c5c8c0f Mon Sep 17 00:00:00 2001 From: Philipp Takacs Date: Mon, 29 Jun 2015 00:42:31 +0200 Subject: [PATCH] find recipients for sendmail Recipients are given as comandline arguments to sendmail. Also do aliasing on every header which contain an address. --- h/addrsbr.h | 3 + man/spost.man8 | 23 ++++-- sbr/addrsbr.c | 25 +++++++ uip/spost.c | 211 ++++++++++++++++++++++++++++---------------------------- 4 files changed, 152 insertions(+), 110 deletions(-) diff --git a/h/addrsbr.h b/h/addrsbr.h index a86a90d..93b1735 100644 --- a/h/addrsbr.h +++ b/h/addrsbr.h @@ -10,6 +10,8 @@ #define NETHOST 1 #define BADHOST 2 +#include + 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 *); +size_t getmboxes(char *, struct mailname **); diff --git a/man/spost.man8 b/man/spost.man8 index db783ef..76d10a8 100644 --- a/man/spost.man8 +++ b/man/spost.man8 @@ -43,6 +43,14 @@ searches the `To:', `Cc:', `Bcc:', `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 @@ -57,6 +65,10 @@ The `Aliasfile' profile entry 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. @@ -93,8 +105,11 @@ Note that this applies equally to `Resent\-From:' lines 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 . @@ -130,6 +145,4 @@ send(1), mh\-mail(5), mh\-alias(5), mh\-tailor(5), refile(1), None .SH BUGS -Spost does not qualify addresses. -.PP -Spost does only basic processing and checking, yet. +None diff --git a/sbr/addrsbr.c b/sbr/addrsbr.c index 53e9be4..ea017f4 100644 --- a/sbr/addrsbr.c +++ b/sbr/addrsbr.c @@ -373,3 +373,28 @@ local_test: ; 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; +} diff --git a/uip/spost.c b/uip/spost.c index 4d0b48a..3a70f36 100644 --- a/uip/spost.c +++ b/uip/spost.c @@ -19,6 +19,7 @@ #include #include #include +#include #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 */ +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 */ @@ -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 size_t do_aliasing(struct mailname *, struct mailname **); int @@ -138,7 +142,7 @@ main(int argc, char **argv) { 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, ""); @@ -265,7 +269,20 @@ main(int argc, char **argv) fclose(in); if (debug) { + struct mailname *i = recipients; /* 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); } @@ -294,16 +311,36 @@ main(int argc, char **argv) } 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++ = "-m"; /* send to me too */ - *argp++ = "-t"; /* read msg for recipients */ *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; - 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; } @@ -315,8 +352,12 @@ static void putfmt(char *name, char *str, FILE *out) { int i; - char *cp; 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') { @@ -358,64 +399,26 @@ putfmt(char *name, char *str, FILE *out) 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; } - 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 - */ - /* - ** 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; @@ -425,38 +428,28 @@ putfmt(char *name, char *str, FILE *out) /* 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; - } else { - mnfree(mp); - mp = NULL; } - } else { - mnfree(mp); - mp = NULL; } + fromcnt++; } 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; - char *cp; int namelen; fprintf(out, "%s: ", name); @@ -547,38 +539,9 @@ putadr(char *name, struct mailname *nl) 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; - mnfree(mp2); } 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; +} -- 1.7.10.4