diff options
author | peter <peter@FreeBSD.org> | 1995-12-02 18:17:40 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-12-02 18:17:40 +0000 |
commit | a531c1a15720076e696b7ecb296c53191cf906c6 (patch) | |
tree | a0e24bbe1b4263b12bb5a33862e1d9f0272e8ef8 /usr.sbin/sendmail/src/headers.c | |
parent | 91b3d1fef5f70cc06d726f635e7a187744eb869d (diff) | |
download | FreeBSD-src-a531c1a15720076e696b7ecb296c53191cf906c6.zip FreeBSD-src-a531c1a15720076e696b7ecb296c53191cf906c6.tar.gz |
Initial round of conflict resolutions.. I need to do another
pass over this and check it more closely, but my initial concern was
to get it to all compile again. Some of the obsoleted files 'cvs rm'ed.
Diffstat (limited to 'usr.sbin/sendmail/src/headers.c')
-rw-r--r-- | usr.sbin/sendmail/src/headers.c | 435 |
1 files changed, 360 insertions, 75 deletions
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c index a55ba95..9bad1f8 100644 --- a/usr.sbin/sendmail/src/headers.c +++ b/usr.sbin/sendmail/src/headers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)headers.c 8.32 (Berkeley) 4/14/94"; +static char sccsid[] = "@(#)headers.c 8.82 (Berkeley) 10/28/95"; #endif /* not lint */ # include <errno.h> @@ -47,6 +47,7 @@ static char sccsid[] = "@(#)headers.c 8.32 (Berkeley) 4/14/94"; ** Parameters: ** line -- header as a text line. ** def -- if set, this is a default value. +** hdrp -- a pointer to the place to save the header. ** e -- the envelope including this header. ** ** Returns: @@ -57,9 +58,11 @@ static char sccsid[] = "@(#)headers.c 8.32 (Berkeley) 4/14/94"; ** Contents of 'line' are destroyed. */ -chompheader(line, def, e) +int +chompheader(line, def, hdrp, e) char *line; bool def; + HDR **hdrp; register ENVELOPE *e; { register char *p; @@ -69,11 +72,20 @@ chompheader(line, def, e) char *fvalue; struct hdrinfo *hi; bool cond = FALSE; + bool headeronly; BITMAP mopts; - char buf[MAXNAME]; + char buf[MAXNAME + 1]; if (tTd(31, 6)) - printf("chompheader: %s\n", line); + { + printf("chompheader: "); + xputs(line); + printf("\n"); + } + + headeronly = hdrp != NULL; + if (!headeronly) + hdrp = &e->e_header; /* strip off options */ clrbitmap(mopts); @@ -91,7 +103,7 @@ chompheader(line, def, e) p = q; } else - usrerr("553 header syntax error, line \"%s\"", line); + syserr("553 header syntax error, line \"%s\"", line); cond = TRUE; } @@ -114,6 +126,10 @@ chompheader(line, def, e) if (*fvalue == ' ') fvalue++; + /* security scan: long field names are end-of-header */ + if (strlen(fname) > 100) + return H_EOH; + /* see if it is a known type */ for (hi = HdrInfo; hi->hi_field != NULL; hi++) { @@ -126,17 +142,38 @@ chompheader(line, def, e) if (hi->hi_field == NULL) printf("no header match\n"); else - printf("header match, hi_flags=%o\n", hi->hi_flags); + printf("header match, hi_flags=%x\n", hi->hi_flags); } /* see if this is a resent message */ - if (!def && bitset(H_RESENT, hi->hi_flags)) + if (!def && !headeronly && bitset(H_RESENT, hi->hi_flags)) e->e_flags |= EF_RESENT; + /* if this is an Errors-To: header keep track of it now */ + if (UseErrorsTo && !def && !headeronly && + bitset(H_ERRORSTO, hi->hi_flags)) + (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e); + /* if this means "end of header" quit now */ if (bitset(H_EOH, hi->hi_flags)) return (hi->hi_flags); +#ifdef LOTUS_NOTES_HACK + /* + ** Horrible hack to work around problem with Lotus Notes SMTP + ** mail gateway, which generates From: headers with newlines in + ** them and the <address> on the second line. Although this is + ** legal RFC 822, many MUAs don't handle this properly and thus + ** never find the actual address. + */ + + if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader) + { + while ((p = strchr(fvalue, '\n')) != NULL) + *p = ' '; + } +#endif + /* ** Drop explicit From: if same as what we would generate. ** This is to make MH (which doesn't always give a full name) @@ -146,7 +183,8 @@ chompheader(line, def, e) p = "resent-from"; if (!bitset(EF_RESENT, e->e_flags)) p += 7; - if (!def && !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0) + if (!def && !headeronly && !bitset(EF_QUEUERUN, e->e_flags) && + strcasecmp(fname, p) == 0) { if (tTd(31, 2)) { @@ -158,7 +196,7 @@ chompheader(line, def, e) strcmp(fvalue, e->e_from.q_user) == 0)) return (hi->hi_flags); #ifdef MAYBENEXTRELEASE /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */ -#ifdef USERDB +#if USERDB else { auto ADDRESS a; @@ -183,13 +221,13 @@ chompheader(line, def, e) SuprErrs = TRUE; fancy = crackaddr(fvalue); if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL && - a.q_mailer == LocalMailer && + bitnset(M_CHECKUDB, a.q_mailer->m_flags) && (p = udbsender(a.q_user)) != NULL) { char *oldg = macvalue('g', e); define('g', p, e); - expand(fancy, buf, &buf[sizeof buf], e); + expand(fancy, buf, sizeof buf, e); define('g', oldg, e); fvalue = buf; } @@ -200,12 +238,20 @@ chompheader(line, def, e) } /* delete default value for this header */ - for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link) + for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link) { if (strcasecmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) && !bitset(H_FORCE, h->h_flags)) + { h->h_value = NULL; + if (!cond) + { + /* copy conditions from default case */ + bcopy((char *)h->h_mflags, (char *)mopts, + sizeof mopts); + } + } } /* create a new node */ @@ -222,7 +268,7 @@ chompheader(line, def, e) h->h_flags |= H_CHECK; /* hack to see if this is a new format message */ - if (!def && bitset(H_RCPT|H_FROM, h->h_flags) && + if (!def && !headeronly && bitset(H_RCPT|H_FROM, h->h_flags) && (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL || strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL)) { @@ -239,7 +285,7 @@ chompheader(line, def, e) ** Parameters: ** field -- the name of the header field. ** value -- the value of the field. -** e -- the envelope to add them to. +** hp -- an indirect pointer to the header structure list. ** ** Returns: ** none. @@ -248,10 +294,11 @@ chompheader(line, def, e) ** adds the field on the list of headers for this envelope. */ -addheader(field, value, e) +void +addheader(field, value, hdrlist) char *field; char *value; - ENVELOPE *e; + HDR **hdrlist; { register HDR *h; register struct hdrinfo *hi; @@ -265,7 +312,7 @@ addheader(field, value, e) } /* find current place in list -- keep back pointer? */ - for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link) + for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link) { if (strcasecmp(field, h->h_field) == 0) break; @@ -288,7 +335,7 @@ addheader(field, value, e) ** ** Parameters: ** field -- the field name. -** e -- the envelope containing the header. +** header -- the header list. ** ** Returns: ** pointer to the value part. @@ -299,13 +346,13 @@ addheader(field, value, e) */ char * -hvalue(field, e) +hvalue(field, header) char *field; - register ENVELOPE *e; + HDR *header; { register HDR *h; - for (h = e->e_header; h != NULL; h = h->h_link) + for (h = header; h != NULL; h = h->h_link) { if (!bitset(H_DEFAULT, h->h_flags) && strcasecmp(h->h_field, field) == 0) @@ -319,11 +366,17 @@ hvalue(field, e) ** A line is a header if it has a single word followed by ** optional white space followed by a colon. ** +** Header fields beginning with two dashes, although technically +** permitted by RFC822, are automatically rejected in order +** to make MIME work out. Without this we could have a technically +** legal header such as ``--"foo:bar"'' that would also be a legal +** MIME separator. +** ** Parameters: -** s -- string to check for possible headerness. +** h -- string to check for possible headerness. ** ** Returns: -** TRUE if s is a header. +** TRUE if h is a header. ** FALSE otherwise. ** ** Side Effects: @@ -331,12 +384,20 @@ hvalue(field, e) */ bool -isheader(s) - register char *s; +isheader(h) + char *h; { + register char *s = h; + + if (s[0] == '-' && s[1] == '-') + return FALSE; + while (*s > ' ' && *s != ':' && *s != '\0') s++; + if (h == s) + return FALSE; + /* following technically violates RFC822 */ while (isascii(*s) && isspace(*s)) s++; @@ -349,7 +410,9 @@ isheader(s) ** Parameters: ** e -- the envelope to process. ** full -- if set, do full processing (e.g., compute -** message priority). +** message priority). This should not be set +** when reading a queue file because some info +** needed to compute the priority is wrong. ** ** Returns: ** none. @@ -360,6 +423,7 @@ isheader(s) ** Aborts the message if the hop count is exceeded. */ +void eatheader(e, full) register ENVELOPE *e; bool full; @@ -382,28 +446,42 @@ eatheader(e, full) define('u', NULL, e); /* full name of from person */ - p = hvalue("full-name", e); + p = hvalue("full-name", e->e_header); if (p != NULL) define('x', p, e); if (tTd(32, 1)) printf("----- collected header -----\n"); - msgid = "<none>"; + msgid = NULL; for (h = e->e_header; h != NULL; h = h->h_link) { + if (tTd(32, 1)) + printf("%s: ", h->h_field); if (h->h_value == NULL) { if (tTd(32, 1)) - printf("%s: <NULL>\n", h->h_field); + printf("<NULL>\n"); continue; } /* do early binding */ if (bitset(H_DEFAULT, h->h_flags)) { - expand(h->h_value, buf, &buf[sizeof buf], e); + if (tTd(32, 1)) + { + printf("("); + xputs(h->h_value); + printf(") "); + } + expand(h->h_value, buf, sizeof buf, e); if (buf[0] != '\0') { + if (bitset(H_FROM, h->h_flags)) + { + extern char *crackaddr(); + + expand(crackaddr(buf), buf, sizeof buf, e); + } h->h_value = newstr(buf); h->h_flags &= ~H_DEFAULT; } @@ -411,7 +489,6 @@ eatheader(e, full) if (tTd(32, 1)) { - printf("%s: ", h->h_field); xputs(h->h_value); printf("\n"); } @@ -428,7 +505,7 @@ eatheader(e, full) int saveflags = e->e_flags; (void) sendtolist(h->h_value, NULLADDR, - &e->e_sendqueue, e); + &e->e_sendqueue, 0, e); /* delete fatal errors generated by this address */ if (!GrabTo && !bitset(EF_FATALERRS, saveflags)) @@ -436,7 +513,10 @@ eatheader(e, full) } /* save the message-id for logging */ - if (full && strcasecmp(h->h_field, "message-id") == 0) + p = "resent-message-id"; + if (!bitset(EF_RESENT, e->e_flags)) + p += 7; + if (strcasecmp(h->h_field, p) == 0) { msgid = h->h_value; while (isascii(*msgid) && isspace(*msgid)) @@ -446,11 +526,6 @@ eatheader(e, full) /* see if this is a return-receipt header */ if (bitset(H_RECEIPTTO, h->h_flags)) e->e_receiptto = h->h_value; - - /* see if this is an errors-to header */ - if (UseErrorsTo && bitset(H_ERRORSTO, h->h_flags)) - (void) sendtolist(h->h_value, NULLADDR, - &e->e_errorqueue, e); } if (tTd(32, 1)) printf("----------------------------\n"); @@ -464,21 +539,60 @@ eatheader(e, full) e->e_hopcount = hopcnt; /* message priority */ - p = hvalue("precedence", e); + p = hvalue("precedence", e->e_header); if (p != NULL) e->e_class = priencode(p); + if (e->e_class < 0) + e->e_timeoutclass = TOC_NONURGENT; + else if (e->e_class > 0) + e->e_timeoutclass = TOC_URGENT; if (full) + { e->e_msgpriority = e->e_msgsize - e->e_class * WkClassFact + e->e_nrcpts * WkRecipFact; + } + + /* message timeout priority */ + p = hvalue("priority", e->e_header); + if (p != NULL) + { + /* (this should be in the configuration file) */ + if (strcasecmp(p, "urgent")) + e->e_timeoutclass = TOC_URGENT; + else if (strcasecmp(p, "normal")) + e->e_timeoutclass = TOC_NORMAL; + else if (strcasecmp(p, "non-urgent")) + e->e_timeoutclass = TOC_NONURGENT; + } /* date message originated */ - p = hvalue("posted-date", e); + p = hvalue("posted-date", e->e_header); if (p == NULL) - p = hvalue("date", e); + p = hvalue("date", e->e_header); if (p != NULL) define('a', p, e); + /* check to see if this is a MIME message */ + if ((e->e_bodytype != NULL && + strcasecmp(e->e_bodytype, "8BITMIME") == 0) || + hvalue("MIME-Version", e->e_header) != NULL) + { + e->e_flags |= EF_IS_MIME; + if (HasEightBits) + e->e_bodytype = "8BITMIME"; + } + else if ((p = hvalue("Content-Type", e->e_header)) != NULL) + { + /* this may be an RFC 1049 message */ + p = strpbrk(p, ";/"); + if (p == NULL || *p == ';') + { + /* yep, it is */ + e->e_flags |= EF_DONT_MIME; + } + } + /* ** From person in antiquated ARPANET mode ** required by UK Grey Book e-mail gateways (sigh) @@ -493,7 +607,7 @@ eatheader(e, full) if (bitset(H_FROM, hi->hi_flags) && (!bitset(H_RESENT, hi->hi_flags) || bitset(EF_RESENT, e->e_flags)) && - (p = hvalue(hi->hi_field, e)) != NULL) + (p = hvalue(hi->hi_field, e->e_header)) != NULL) break; } if (hi->hi_field != NULL) @@ -510,7 +624,7 @@ eatheader(e, full) */ # ifdef LOG - if (full && LogLevel > 4) + if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) logsender(e, msgid); # endif /* LOG */ e->e_flags &= ~EF_LOGSENDER; @@ -526,6 +640,7 @@ eatheader(e, full) ** none */ +void logsender(e, msgid) register ENVELOPE *e; char *msgid; @@ -534,8 +649,23 @@ logsender(e, msgid) char *name; register char *sbp; register char *p; - char hbuf[MAXNAME]; - char sbuf[MAXLINE]; + int l; + char hbuf[MAXNAME + 1]; + char sbuf[MAXLINE + 1]; + char mbuf[MAXNAME + 1]; + + /* don't allow newlines in the message-id */ + if (msgid != NULL) + { + l = strlen(msgid); + if (l > sizeof mbuf - 1) + l = sizeof mbuf - 1; + bcopy(msgid, mbuf, l); + mbuf[l] = '\0'; + p = mbuf; + while ((p = strchr(p, '\n')) != NULL) + *p++ = ' '; + } if (bitset(EF_RESPONSE, e->e_flags)) name = "[RESPONSE]"; @@ -552,7 +682,7 @@ logsender(e, msgid) if (RealHostAddr.sa.sa_family != 0) { p = &hbuf[strlen(hbuf)]; - (void) sprintf(p, " (%s)", + (void) sprintf(p, " (%.100s)", anynet_ntoa(&RealHostAddr)); } } @@ -561,12 +691,12 @@ logsender(e, msgid) # if (SYSLOG_BUFSIZE) >= 256 sbp = sbuf; sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d", - e->e_from.q_paddr, e->e_msgsize, e->e_class, - e->e_msgpriority, e->e_nrcpts); + e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr, + e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); sbp += strlen(sbp); if (msgid != NULL) { - sprintf(sbp, ", msgid=%.100s", msgid); + sprintf(sbp, ", msgid=%.100s", mbuf); sbp += strlen(sbp); } if (e->e_bodytype != NULL) @@ -577,33 +707,35 @@ logsender(e, msgid) p = macvalue('r', e); if (p != NULL) (void) sprintf(sbp, ", proto=%.20s", p); - syslog(LOG_INFO, "%s: %s, relay=%s", + syslog(LOG_INFO, "%s: %.850s, relay=%.100s", e->e_id, sbuf, name); # else /* short syslog buffer */ syslog(LOG_INFO, "%s: from=%s", - e->e_id, shortenstring(e->e_from.q_paddr, 83)); + e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" : + shortenstring(e->e_from.q_paddr, 83)); syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d", e->e_id, e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); if (msgid != NULL) - syslog(LOG_INFO, "%s: msgid=%s", e->e_id, msgid); + syslog(LOG_INFO, "%s: msgid=%s", + e->e_id, shortenstring(mbuf, 83)); sbp = sbuf; sprintf(sbp, "%s:", e->e_id); sbp += strlen(sbp); if (e->e_bodytype != NULL) { - sprintf(sbp, " bodytype=%s,", e->e_bodytype); + sprintf(sbp, " bodytype=%.20s,", e->e_bodytype); sbp += strlen(sbp); } p = macvalue('r', e); if (p != NULL) { - sprintf(sbp, " proto=%s,", p); + sprintf(sbp, " proto=%.20s,", p); sbp += strlen(sbp); } - syslog(LOG_INFO, "%s relay=%s", sbuf, name); + syslog(LOG_INFO, "%.400s relay=%.100s", sbuf, name); # endif # endif } @@ -620,6 +752,7 @@ logsender(e, msgid) ** none. */ +int priencode(p) char *p; { @@ -678,9 +811,12 @@ crackaddr(addr) bool putgmac = FALSE; bool quoteit = FALSE; bool gotangle = FALSE; + bool gotcolon = FALSE; register char *bp; char *buflim; - static char buf[MAXNAME]; + char *bufhead; + char *addrhead; + static char buf[MAXNAME + 1]; if (tTd(33, 1)) printf("crackaddr(%s)\n", addr); @@ -694,9 +830,9 @@ crackaddr(addr) ** adjusted later if we find them. */ - bp = buf; + bp = bufhead = buf; buflim = &buf[sizeof buf - 5]; - p = addr; + p = addrhead = addr; copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0; qmode = realqmode = FALSE; @@ -780,8 +916,80 @@ crackaddr(addr) bp--; } + /* check for group: list; syntax */ + if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr) + { + register char *q; + + if (*p == ':') + { + /* special case -- :: syntax */ + if (cmtlev <= 0 && !qmode) + quoteit = TRUE; + if (copylev > 0 && !skipping) + { + *bp++ = c; + *bp++ = c; + } + p++; + goto putg; + } + + gotcolon = TRUE; + + bp = bufhead; + if (quoteit) + { + *bp++ = '"'; + + /* back up over the ':' and any spaces */ + --p; + while (isascii(*--p) && isspace(*p)) + continue; + p++; + } + for (q = addrhead; q < p; ) + { + c = *q++; + if (bp < buflim) + { + if (quoteit && c == '"') + *bp++ = '\\'; + *bp++ = c; + } + } + if (quoteit) + { + if (bp == &bufhead[1]) + bp--; + else + *bp++ = '"'; + while ((c = *p++) != ':') + { + if (bp < buflim) + *bp++ = c; + } + *bp++ = c; + } + + /* any trailing white space is part of group: */ + while (isascii(*p) && isspace(*p) && bp < buflim) + *bp++ = *p++; + copylev = 0; + putgmac = quoteit = FALSE; + bufhead = bp; + addrhead = p; + continue; + } + + if (c == ';' && copylev <= 0 && !ColonOkInAddr) + { + if (bp < buflim) + *bp++ = c; + } + /* check for characters that may have to be quoted */ - if (strchr(".'@,;:\\()[]", c) != NULL) + if (strchr(MustQuoteChars, c) != NULL) { /* ** If these occur as the phrase part of a <> @@ -809,7 +1017,7 @@ crackaddr(addr) if (!skipping) realanglelev = 1; - bp = buf; + bp = bufhead; if (quoteit) { *bp++ = '"'; @@ -820,7 +1028,7 @@ crackaddr(addr) continue; p++; } - for (q = addr; q < p; ) + for (q = addrhead; q < p; ) { c = *q++; if (bp < buflim) @@ -901,6 +1109,7 @@ crackaddr(addr) ** ** Parameters: ** mci -- the connection information. +** h -- the header to put. ** e -- envelope to use. ** ** Returns: @@ -917,27 +1126,45 @@ crackaddr(addr) # define MAX(a,b) (((a)>(b))?(a):(b)) #endif -putheader(mci, e) +void +putheader(mci, h, e) register MCI *mci; + register HDR *h; register ENVELOPE *e; { char buf[MAX(MAXLINE,BUFSIZ)]; - register HDR *h; char obuf[MAXLINE]; if (tTd(34, 1)) printf("--- putheader, mailer = %s ---\n", mci->mci_mailer->m_name); - for (h = e->e_header; h != NULL; h = h->h_link) + mci->mci_flags |= MCIF_INHEADER; + for (; h != NULL; h = h->h_link) { - register char *p; + register char *p = h->h_value; extern bool bitintersect(); if (tTd(34, 11)) { printf(" %s: ", h->h_field); - xputs(h->h_value); + xputs(p); + } + + /* suppress Content-Transfer-Encoding: if we are MIMEing */ + if (bitset(H_CTE, h->h_flags) && + bitset(MCIF_CVT8TO7|MCIF_INMIME, mci->mci_flags)) + { + if (tTd(34, 11)) + printf(" (skipped (content-transfer-encoding))\n"); + continue; + } + + if (bitset(MCIF_INMIME, mci->mci_flags)) + { + if (tTd(34, 11)) + printf("\n"); + goto vanilla; } if (bitset(H_CHECK|H_ACHECK, h->h_flags) && @@ -966,10 +1193,9 @@ putheader(mci, e) } /* macro expand value if generated internally */ - p = h->h_value; if (bitset(H_DEFAULT, h->h_flags)) { - expand(p, buf, &buf[sizeof buf], e); + expand(p, buf, sizeof buf, e); p = buf; if (p == NULL || *p == '\0') { @@ -979,6 +1205,23 @@ putheader(mci, e) } } + if (bitset(H_BCC, h->h_flags)) + { + /* Bcc: field -- either truncate or delete */ + if (bitset(EF_DELETE_BCC, e->e_flags)) + { + if (tTd(34, 11)) + printf(" (skipped -- bcc)\n"); + } + else + { + /* no other recipient headers: truncate value */ + (void) sprintf(obuf, "%s:", h->h_field); + putline(obuf, mci); + } + continue; + } + if (tTd(34, 11)) printf("\n"); @@ -995,21 +1238,51 @@ putheader(mci, e) { /* vanilla header line */ register char *nlp; + register char *obp; - (void) sprintf(obuf, "%s: ", h->h_field); +vanilla: + (void) sprintf(obuf, "%.200s: ", h->h_field); + obp = obuf + strlen(obuf); while ((nlp = strchr(p, '\n')) != NULL) { + *nlp = '\0'; - (void) strcat(obuf, p); + sprintf(obp, "%.*s", + sizeof obuf - (obp - obuf) - 1, p); *nlp = '\n'; putline(obuf, mci); p = ++nlp; - obuf[0] = '\0'; + obp = obuf; } - (void) strcat(obuf, p); + sprintf(obp, "%.*s", sizeof obuf - (obp - obuf) - 1, p); + putline(obuf, mci); + } + } + + /* + ** If we are converting this to a MIME message, add the + ** MIME headers. + */ + +#if MIME8TO7 + if (bitset(MM_MIME8BIT, MimeMode) && + bitset(EF_HAS8BIT, e->e_flags) && + !bitset(EF_DONT_MIME, e->e_flags) && + !bitnset(M_8BITS, mci->mci_mailer->m_flags) && + !bitset(MCIF_CVT8TO7, mci->mci_flags)) + { + if (hvalue("MIME-Version", e->e_header) == NULL) + putline("MIME-Version: 1.0", mci); + if (hvalue("Content-Type", e->e_header) == NULL) + { + sprintf(obuf, "Content-Type: text/plain; charset=%s", + defcharset(e)); putline(obuf, mci); } + if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL) + putline("Content-Transfer-Encoding: 8bit", mci); } +#endif } /* ** COMMAIZE -- output a header field, making a comma-translated list. @@ -1051,7 +1324,7 @@ commaize(h, p, oldstyle, mci, e) printf("commaize(%s: %s)\n", h->h_field, p); obp = obuf; - (void) sprintf(obp, "%s: ", h->h_field); + (void) sprintf(obp, "%.200s: ", h->h_field); opos = strlen(h->h_field) + 2; obp += opos; omax = mci->mci_mailer->m_linelimit - 2; @@ -1088,7 +1361,7 @@ commaize(h, p, oldstyle, mci, e) char pvpbuf[PSBUFSIZE]; (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, - sizeof pvpbuf, &oldp); + sizeof pvpbuf, &oldp, NULL); p = oldp; /* look to see if we have an at sign */ @@ -1119,6 +1392,18 @@ commaize(h, p, oldstyle, mci, e) flags = RF_HEADERADDR|RF_ADDDOMAIN; if (bitset(H_FROM, h->h_flags)) flags |= RF_SENDERADDR; +#if USERDB + else if (e->e_from.q_mailer != NULL && + bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags)) + { + extern char *udbsender(); + char *q; + + q = udbsender(name); + if (q != NULL) + name = q; + } +#endif stat = EX_OK; name = remotename(name, mci->mci_mailer, flags, &stat, e); if (*name == '\0') |