summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sendmail/src/headers.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/headers.c')
-rw-r--r--usr.sbin/sendmail/src/headers.c435
1 files changed, 360 insertions, 75 deletions
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c
index 8493e79c..ae242b1 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')
OpenPOWER on IntegriCloud