X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fspost.c;h=48f97978dbd3319f66df156cd91c494a0687c2d4;hp=4a8ffdc5693d7e2132eb15d88e913e5b63bc4d0c;hb=eda302e1f049eae6b429a12c5526600eea6a02e1;hpb=4c513fd6ebd0f1b08b8f9504b6d6c8aef2351d4a diff --git a/uip/spost.c b/uip/spost.c index 4a8ffdc..48f9797 100644 --- a/uip/spost.c +++ b/uip/spost.c @@ -16,37 +16,25 @@ #include #include #include +#include +#include +#include #define MAX_SM_FIELD 1476 /* < largest hdr field sendmail will accept */ -#define FCCS 10 /* max number of fccs allowed */ -struct swit switches[] = { +static struct swit switches[] = { #define VERBSW 0 { "verbose", 0 }, #define NVERBSW 1 - { "noverbose", 0 }, -#define WATCSW 2 - { "watch", 0 }, -#define NWATCSW 3 - { "nowatch", 0 }, -#define ALIASW 4 - { "alias aliasfile", 0 }, -#define NALIASW 5 - { "noalias", 0 }, -#define VERSIONSW 6 - { "version", 0 }, -#define HELPSW 7 + { "noverbose", 2 }, +#define VERSIONSW 2 + { "Version", 0 }, +#define HELPSW 3 { "help", 0 }, -#define DEBUGSW 8 +#define DEBUGSW 4 { "debug", -5 }, -#define DISTSW 9 +#define DISTSW 5 { "dist", -4 }, /* interface from dist */ -#define PUSHSW 10 /* fork to sendmail then exit */ - { "push", -4 }, -#define NPUSHSW 11 /* exec sendmail */ - { "nopush", -6 }, -#define LIBSW 12 - { "library directory", -7 }, { NULL, 0 } }; @@ -68,6 +56,7 @@ struct swit switches[] = { #define MVIS 0x0008 /* we've seen sighted addrs */ #define MINV 0x0010 /* we've seen blind addrs */ #define MRDT 0x0020 /* we've seen a Resent-Date: */ +#define MFMM 0x0040 /* The Mail is From a Alternative-Mailbox Addresse */ struct headers { char *value; @@ -75,7 +64,6 @@ struct headers { unsigned int set; }; - static struct headers NHeaders[] = { { "Return-Path", HBAD, 0 }, { "Received", HBAD, 0 }, @@ -89,6 +77,7 @@ static struct headers NHeaders[] = { { "Bcc", HADR|HTRY|HBCC, MINV }, { "Message-Id", HBAD, 0 }, { "Fcc", HFCC, 0 }, + { "Envelope-From", HIGN, 0 }, { NULL, 0, 0 } }; @@ -105,15 +94,14 @@ static struct headers RHeaders[] = { { "Resent-Fcc", HFCC, 0 }, { "Reply-To", HADR, 0 }, { "Fcc", HIGN, 0 }, + { "Envelope-From", HIGN, 0 }, { NULL, 0, 0 } }; -static int badmsg = 0; /* message has bad semantics */ -static int verbose = 0; /* spell it out */ -static int debug = 0; /* debugging post */ -static int watch = 0; /* watch the delivery process */ -static int pushflg = 0; /* if going to fork to sendmail */ +static int badmsg = 0; +static int verbose = 0; +static int debug = 0; static int aliasflg = 0; /* if going to process aliases */ static unsigned msgflags = 0; /* what we've seen */ @@ -122,18 +110,15 @@ static enum { normal, resent } msgstate = normal; -static char tmpfil[] = "/tmp/spost-XXXXXX"; -static char bccfil[] = "/tmp/spost-bcc-XXXXXX"; +static char *tmpfil; static char *subject = NULL; /* the subject field for BCC'ing */ static char fccs[BUFSIZ] = ""; -struct mailname *bccs = NULL; +struct mailname *bccs = NULL; /* list of the bcc recipients */ static struct headers *hdrtab; /* table for the message we're doing */ static FILE *out; /* output (temp) file */ -extern char *sendmail; - /* ** static prototypes */ @@ -144,25 +129,21 @@ static void putadr(char *, struct mailname *); static int putone(char *, int, int); static void process_fcc(char *); static void fcc(char *, char *); -static void make_bcc_draft(char *); +static void process_bccs(char *); int main(int argc, char **argv) { - int state, i, pid, compnum; + int state, compnum; char *cp, *msg = NULL, **argp, **arguments; char *sargv[16], buf[BUFSIZ], name[NAMESZ]; FILE *in; -#ifdef LOCALE setlocale(LC_ALL, ""); -#endif invo_name = mhbasename(argv[0]); - /* foil search of user profile/context */ - if (context_foil(NULL) == -1) - done(1); + context_read(); arguments = getarguments(invo_name, argc, argv, 0); argp = arguments; @@ -172,19 +153,19 @@ main(int argc, char **argv) switch (smatch(++cp, switches)) { case AMBIGSW: ambigsw(cp, switches); - done(1); + exit(EX_USAGE); case UNKWNSW: - adios(NULL, "-%s unknown", cp); + adios(EX_USAGE, NULL, "-%s unknown", cp); case HELPSW: snprintf(buf, sizeof(buf), "%s [switches] file", invo_name); print_help(buf, switches, 1); - done(1); + exit(argc == 2 ? EX_OK : EX_USAGE); case VERSIONSW: print_version(invo_name); - done(1); + exit(argc == 2 ? EX_OK : EX_USAGE); case DEBUGSW: debug++; @@ -200,70 +181,42 @@ main(int argc, char **argv) case NVERBSW: verbose = 0; continue; - - case WATCSW: - watch++; - continue; - case NWATCSW: - watch = 0; - continue; - - case PUSHSW: - pushflg++; - continue; - case NPUSHSW: - pushflg = 0; - continue; - - case ALIASW: - if (!(cp = *argp++) || *cp == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - aliasflg = 1; - if ((state = alias(cp)) != AK_OK) - adios(NULL, "aliasing error in file %s - %s", cp, akerror(state)); - continue; - case NALIASW: - aliasflg = 0; - continue; - - case LIBSW: - if (!(cp = *argp++) || *cp == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - /* create a minimal context */ - if (context_foil(cp) == -1) - done(1); - continue; } } if (msg) - adios(NULL, "only one message at a time!"); + adios(EX_USAGE, NULL, "only one message at a time!"); else msg = cp; } if (!msg) - adios(NULL, "usage: %s [switches] file", invo_name); + adios(EX_USAGE, NULL, "usage: %s [switches] file", invo_name); if ((in = fopen(msg, "r")) == NULL) - adios(msg, "unable to open"); + adios(EX_IOERR, msg, "unable to open"); if (debug) { verbose++; out = stdout; } else { -#ifdef HAVE_MKSTEMP - if ((out = fdopen(mkstemp(tmpfil), "w")) == NULL) - adios(tmpfil, "unable to create"); -#else - mktemp(tmpfil); - if ((out = fopen(tmpfil, "w")) == NULL) - adios(tmpfil, "unable to create"); - chmod(tmpfil, 0600); -#endif + tmpfil = getcpy(m_mktemp2("/tmp/", invo_name, NULL, &out)); + } + + /* check for "Aliasfile:" profile entry */ + if ((cp = context_find("Aliasfile"))) { + char *dp, **ap; + + aliasflg = 1; + for (ap=brkstring(dp=getcpy(cp), " ", "\n"); ap && *ap; + ap++) { + if ((state = alias(etcpath(*ap))) != AK_OK) { + adios(EX_IOERR, NULL, "aliasing error in file %s: %s", + *ap, akerror(state)); + } + } } + hdrtab = (msgstate == normal) ? NHeaders : RHeaders; for (compnum = 1, state = FLD;;) { @@ -301,11 +254,11 @@ main(int argc, char **argv) case LENERR: case FMTERR: - adios(NULL, "message format error in component #%d", + adios(EX_DATAERR, NULL, "message format error in component #%d", compnum); default: - adios(NULL, "getfld() returned %d", state); + adios(EX_SOFTWARE, NULL, "getfld() returned %d", state); } break; } @@ -313,7 +266,7 @@ main(int argc, char **argv) if (debug) { /* stop here */ - done(0); + exit(EX_OK); } fclose(out); @@ -323,9 +276,13 @@ main(int argc, char **argv) fcc(tmpfil, fccs); } - /* process Bcc */ if (bccs) { - make_bcc_draft(tmpfil); + process_bccs(tmpfil); + if (!(msgflags & MVIS)) { + /* only Bcc rcpts: we're finished here */ + unlink(tmpfil); + exit(EX_OK); + } } /* @@ -333,7 +290,7 @@ main(int argc, char **argv) ** the msg temp file as std in. */ if (!freopen(tmpfil, "r", stdin)) { - adios(tmpfil, "can't reopen for sendmail"); + adios(EX_IOERR, tmpfil, "can't reopen for sendmail"); } unlink(tmpfil); @@ -342,53 +299,16 @@ main(int argc, char **argv) *argp++ = "-m"; /* send to me too */ *argp++ = "-t"; /* read msg for recipients */ *argp++ = "-i"; /* don't stop on "." */ - if (watch || verbose) { + if (verbose) { *argp++ = "-v"; - pushflg = 0; } *argp = NULL; - - if (pushflg) { - /* fork to a child to run sendmail */ - for (i=0; (pid = fork()) == NOTOK && i < 5; i++) - sleep(5); - switch (pid) { - case NOTOK: - fprintf(verbose ? stdout : stderr, - "%s: can't fork to %s\n", - invo_name, sendmail); - exit(-1); - case OK: - /* we're the child .. */ - break; - default: - exit(0); - } - } - - if (0 /*bccs*/) { - /* fork to a child to run sendmail */ - for (i=0; (pid = fork()) == NOTOK && i < 5; i++) - sleep(5); - switch (pid) { - case NOTOK: - fprintf(verbose ? stdout : stderr, - "%s: can't fork to %s\n", - invo_name, sendmail); - exit(-1); - case OK: - /* we're the child .. */ - exit(0); - default: - exit(0); - } - } - execv(sendmail, sargv); - adios(sendmail, "can't exec"); - return 0; /* dead code to satisfy the compiler */ + adios(EX_OSERR, sendmail, "can't exec"); + return -1; } + /* DRAFT GENERATION */ static void @@ -398,20 +318,25 @@ putfmt(char *name, char *str, FILE *out) char *cp; struct headers *hdr; - /* remove all leading whitespace (even newlines) */ - while (*str==' ' || *str=='\t' || *str=='\n') { + /* remove leading whitespace */ + while (*str==' ' || *str=='\t') { str++; } if ((i = get_header(name, hdrtab)) == NOTOK) { - /* no header we would care for: push it through */ - fprintf(out, "%s: %s", name, str); + /* no header we would care for */ + if (mh_strcasecmp(name, attach_hdr)!=0 && + mh_strcasecmp(name, sign_hdr)!=0 && + mh_strcasecmp(name, enc_hdr)!=0) { + /* push it through */ + fprintf(out, "%s: %s", name, str); + } return; } /* it's one of the interesting headers */ hdr = &hdrtab[i]; - if (hdr->flags & HIGN || !*str) { + if (hdr->flags & HIGN || strcmp(str, "\n")==0) { return; } @@ -487,6 +412,21 @@ putfmt(char *name, char *str, FILE *out) ** -- meillo@marmaro.de 2012-02 */ + if (hdr->set & MFRM) { + + struct mailname *mp = NULL; + + /* This is need because the addresse parser hold global state */ + ismymbox(NULL); + + while ((cp = getname(str)) != NULL) { + mp = getm(cp, NULL, 0, AD_NAME, NULL); + if (ismymbox(mp)) { + msgflags |= MFMM; + } + } + } + if (hdr->flags & HSUB) { subject = getcpy(str); } @@ -506,26 +446,36 @@ finish_headers(FILE *out) char *resentstr = (msgstate == resent) ? "Resent-" : ""; if (!(msgflags & MDAT)) { - fprintf(out, "%sDate: %s\n", resentstr, dtimenow(0)); + fprintf(out, "%sDate: %s\n", resentstr, dtimenow()); } - strncpy(from, getusername(), sizeof(from)); - if ((cp = getfullname()) && *cp) { - snprintf(signature, sizeof(signature), "%s <%s>", cp, from); + if ((cp = context_find("Default-From")) != NULL) { + snprintf(signature, sizeof(signature), "%s", cp); } else { - snprintf(signature, sizeof(signature), "%s", from); + snprintf(from, sizeof(from), "%s@%s", getusername(), LocalName()); + if ((cp = getfullname()) && *cp) { + snprintf(signature, sizeof(signature), "%s <%s>", cp, from); + } else { + snprintf(signature, sizeof(signature), "%s", from); + } } if (!(msgflags & MFRM)) { fprintf(out, "%sFrom: %s\n", resentstr, signature); } else { - /* In case the From: header contains multiple addresses. */ - fprintf(out, "%sSender: %s\n", resentstr, from); + /* + ** Add a Sender: header because the From: header could + ** be fake or contain multiple addresses. + */ + if (!(msgflags & MFMM)) { + fprintf(out, "%sSender: %s\n", resentstr, signature); + } } if (!(msgflags & MVIS)) { - fprintf(out, "%sBcc: Blind Distribution List: ;\n", resentstr); + fprintf(out, "%sBcc: undisclosed-recipients:;\n", resentstr); } if (badmsg) { - adios(NULL, "re-format message and try again"); + unlink(tmpfil); + adios(EX_DATAERR, NULL, "re-format message and try again"); } } @@ -638,7 +588,7 @@ process_fcc(char *str) int state = 0; if (strlen(str)+strlen(fccs) > sizeof fccs /2) { - adios(NULL, "Too much Fcc data"); + adios(EX_DATAERR, NULL, "Too much Fcc data"); } /* todo: better have three states: SEPARATOR, PLUS, WORD */ for (cp=pp=str; *cp; cp++) { @@ -680,12 +630,12 @@ fcc(char *file, char *folders) folders); fflush(stdout); } - if (strlen(fileproc)+strlen(file)+strlen(folders)+100 > sizeof cmd) { - adios(NULL, "Too much Fcc data"); + if (100+strlen(file)+strlen(folders) > sizeof cmd) { + adios(EX_DATAERR, NULL, "Too much Fcc data"); } /* hack: read from /dev/null and refile(1) won't question us */ - snprintf(cmd, sizeof cmd, "m_next) { + bccdraft = getcpy(m_mktemp2("/tmp/", invo_name, NULL, &out)); + fprintf(out, "To: %s\n", mp->m_text); + fprintf(out, "Subject: [BCC] %s", subject ? subject : ""); + fprintf(out, "%s: %s\n", attach_hdr, origmsg); + fprintf(out, "------------\n"); + fclose(out); + + if (execprogl("send", "send", bccdraft, (char *)NULL) != 0) { + admonish(invo_name, "Problems to send Bcc to %s", + mp->m_text); + unlink(bccdraft); + } } - fprintf(out, "%s: %s\n", attach_hdr, draft); - fprintf(out, "------------\n"); - fclose(out); }