📄 headers.c
字号:
{
if (tTd(32, 1))
dprintf("%s: ", h->h_field);
if (h->h_value == NULL)
{
if (tTd(32, 1))
dprintf("<NULL>\n");
continue;
}
/* do early binding */
if (bitset(H_DEFAULT, h->h_flags) &&
!bitset(H_BINDLATE, h->h_flags))
{
if (tTd(32, 1))
{
dprintf("(");
xputs(h->h_value);
dprintf(") ");
}
expand(h->h_value, buf, sizeof buf, e);
if (buf[0] != '\0')
{
if (bitset(H_FROM, h->h_flags))
expand(crackaddr(buf), buf, sizeof buf, e);
h->h_value = newstr(buf);
h->h_flags &= ~H_DEFAULT;
}
}
if (tTd(32, 1))
{
xputs(h->h_value);
dprintf("\n");
}
/* count the number of times it has been processed */
if (bitset(H_TRACE, h->h_flags))
hopcnt++;
/* send to this person if we so desire */
if (GrabTo && bitset(H_RCPT, h->h_flags) &&
!bitset(H_DEFAULT, h->h_flags) &&
(!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
{
#if 0
int saveflags = e->e_flags;
#endif /* 0 */
(void) sendtolist(h->h_value, NULLADDR,
&e->e_sendqueue, 0, e);
#if 0
/*
** Change functionality so a fatal error on an
** address doesn't affect the entire envelope.
*/
/* delete fatal errors generated by this address */
if (!bitset(EF_FATALERRS, saveflags))
e->e_flags &= ~EF_FATALERRS;
#endif /* 0 */
}
/* save the message-id for logging */
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))
msgid++;
}
}
if (tTd(32, 1))
dprintf("----------------------------\n");
/* if we are just verifying (that is, sendmail -t -bv), drop out now */
if (OpMode == MD_VERIFY)
return;
/* store hop count */
if (hopcnt > e->e_hopcount)
e->e_hopcount = hopcnt;
/* message priority */
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") == 0)
e->e_timeoutclass = TOC_URGENT;
else if (strcasecmp(p, "normal") == 0)
e->e_timeoutclass = TOC_NORMAL;
else if (strcasecmp(p, "non-urgent") == 0)
e->e_timeoutclass = TOC_NONURGENT;
}
/* date message originated */
p = hvalue("posted-date", e->e_header);
if (p == NULL)
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)
*/
if (OpMode == MD_ARPAFTP)
{
register struct hdrinfo *hi;
for (hi = HdrInfo; hi->hi_field != NULL; hi++)
{
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->e_header)) != NULL)
break;
}
if (hi->hi_field != NULL)
{
if (tTd(32, 2))
dprintf("eatheader: setsender(*%s == %s)\n",
hi->hi_field, p);
setsender(p, e, NULL, '\0', TRUE);
}
}
/*
** Log collection information.
*/
if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
logsender(e, msgid);
e->e_flags &= ~EF_LOGSENDER;
}
/*
** LOGSENDER -- log sender information
**
** Parameters:
** e -- the envelope to log
** msgid -- the message id
**
** Returns:
** none
*/
void
logsender(e, msgid)
register ENVELOPE *e;
char *msgid;
{
char *name;
register char *sbp;
register char *p;
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;
memmove(mbuf, msgid, l);
mbuf[l] = '\0';
p = mbuf;
while ((p = strchr(p, '\n')) != NULL)
*p++ = ' ';
}
if (bitset(EF_RESPONSE, e->e_flags))
name = "[RESPONSE]";
else if ((name = macvalue('_', e)) != NULL)
/* EMPTY */
;
else if (RealHostName == NULL)
name = "localhost";
else if (RealHostName[0] == '[')
name = RealHostName;
else
{
name = hbuf;
(void) snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName);
if (RealHostAddr.sa.sa_family != 0)
{
p = &hbuf[strlen(hbuf)];
(void) snprintf(p, SPACELEFT(hbuf, p), " (%.100s)",
anynet_ntoa(&RealHostAddr));
}
}
/* some versions of syslog only take 5 printf args */
#if (SYSLOG_BUFSIZE) >= 256
sbp = sbuf;
snprintf(sbp, SPACELEFT(sbuf, sbp),
"from=%.200s, size=%ld, class=%d, nrcpts=%d",
e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
e->e_msgsize, e->e_class, e->e_nrcpts);
sbp += strlen(sbp);
if (msgid != NULL)
{
snprintf(sbp, SPACELEFT(sbuf, sbp), ", msgid=%.100s", mbuf);
sbp += strlen(sbp);
}
if (e->e_bodytype != NULL)
{
(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", bodytype=%.20s",
e->e_bodytype);
sbp += strlen(sbp);
}
p = macvalue('r', e);
if (p != NULL)
{
(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p);
sbp += strlen(sbp);
}
p = macvalue(macid("{daemon_name}", NULL), e);
if (p != NULL)
{
(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", daemon=%.20s", p);
sbp += strlen(sbp);
}
# if SASL
p = macvalue(macid("{auth_type}", NULL), e);
if (p != NULL)
{
(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", mech=%.12s", p);
sbp += strlen(sbp);
}
p = macvalue(macid("{auth_author}", NULL), e);
if (p != NULL)
{
(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", auth=%.30s", p);
sbp += strlen(sbp);
}
# endif /* SASL */
sm_syslog(LOG_INFO, e->e_id,
"%.850s, relay=%.100s",
sbuf, name);
#else /* (SYSLOG_BUFSIZE) >= 256 */
sm_syslog(LOG_INFO, e->e_id,
"from=%s",
e->e_from.q_paddr == NULL ? "<NONE>"
: shortenstring(e->e_from.q_paddr, 83));
sm_syslog(LOG_INFO, e->e_id,
"size=%ld, class=%ld, nrcpts=%d",
e->e_msgsize, e->e_class, e->e_nrcpts);
if (msgid != NULL)
sm_syslog(LOG_INFO, e->e_id,
"msgid=%s",
shortenstring(mbuf, 83));
sbp = sbuf;
*sbp = '\0';
if (e->e_bodytype != NULL)
{
snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype);
sbp += strlen(sbp);
}
p = macvalue('r', e);
if (p != NULL)
{
snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p);
sbp += strlen(sbp);
}
sm_syslog(LOG_INFO, e->e_id,
"%.400srelay=%.100s", sbuf, name);
#endif /* (SYSLOG_BUFSIZE) >= 256 */
}
/*
** PRIENCODE -- encode external priority names into internal values.
**
** Parameters:
** p -- priority in ascii.
**
** Returns:
** priority as a numeric level.
**
** Side Effects:
** none.
*/
static int
priencode(p)
char *p;
{
register int i;
for (i = 0; i < NumPriorities; i++)
{
if (strcasecmp(p, Priorities[i].pri_name) == 0)
return Priorities[i].pri_val;
}
/* unknown priority */
return 0;
}
/*
** CRACKADDR -- parse an address and turn it into a macro
**
** This doesn't actually parse the address -- it just extracts
** it and replaces it with "$g". The parse is totally ad hoc
** and isn't even guaranteed to leave something syntactically
** identical to what it started with. However, it does leave
** something semantically identical.
**
** This algorithm has been cleaned up to handle a wider range
** of cases -- notably quoted and backslash escaped strings.
** This modification makes it substantially better at preserving
** the original syntax.
**
** Parameters:
** addr -- the address to be cracked.
**
** Returns:
** a pointer to the new version.
**
** Side Effects:
** none.
**
** Warning:
** The return value is saved in local storage and should
** be copied if it is to be reused.
*/
char *
crackaddr(addr)
register char *addr;
{
register char *p;
register char c;
int cmtlev;
int realcmtlev;
int anglelev, realanglelev;
int copylev;
int bracklev;
bool qmode;
bool realqmode;
bool skipping;
bool putgmac = FALSE;
bool quoteit = FALSE;
bool gotangle = FALSE;
bool gotcolon = FALSE;
register char *bp;
char *buflim;
char *bufhead;
char *addrhead;
static char buf[MAXNAME + 1];
if (tTd(33, 1))
dprintf("crackaddr(%s)\n", addr);
/* strip leading spaces */
while (*addr != '\0' && isascii(*addr) && isspace(*addr))
addr++;
/*
** Start by assuming we have no angle brackets. This will be
** adjusted later if we find them.
*/
bp = bufhead = buf;
buflim = &buf[sizeof buf - 7];
p = addrhead = addr;
copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
bracklev = 0;
qmode = realqmode = FALSE;
while ((c = *p++) != '\0')
{
/*
** If the buffer is overful, go into a special "skipping"
** mode that tries to keep legal syntax but doesn't actually
** output things.
*/
skipping = bp >= buflim;
if (copylev > 0 && !skipping)
*bp++ = c;
/* check for backslash escapes */
if (c == '\\')
{
/* arrange to quote the address */
if (cmtlev <= 0 && !qmode)
quoteit = TRUE;
if ((c = *p++) == '\0')
{
/* too far */
p--;
goto putg;
}
if (copylev > 0 && !skipping)
*bp++ = c;
goto putg;
}
/* check for quoted strings */
if (c == '"' && cmtlev <= 0)
{
qmode = !qmode;
if (copylev > 0 && !skipping)
realqmode = !realqmode;
continue;
}
if (qmode)
goto putg;
/* check for comments */
if (c == '(')
{
cmtlev++;
/* allow space for closing paren */
if (!skipping)
{
buflim--;
realcmtlev++;
if (copylev++ <= 0)
{
if (bp != bufhead)
*bp++ = ' ';
*bp++ = c;
}
}
}
if (cmtlev > 0)
{
if (c == ')')
{
cmtlev--;
copylev--;
if (!skipping)
{
realcmtlev--;
buflim++;
}
}
continue;
}
else if (c == ')')
{
/* syntax error: unmatched ) */
if (copylev > 0 && !skipping)
bp--;
}
/* count nesting on [ ... ] (for IPv6 domain literals) */
if (c == '[')
bracklev++;
else if (c == ']')
bracklev--;
/* check for group: list; syntax */
if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
!gotcolon && !ColonOkInAddr)
{
register char *q;
/*
** Check for DECnet phase IV ``::'' (host::user)
** or ** DECnet phase V ``:.'' syntaxes. The latter
** covers ``user@DEC:.tay.myhost'' and
** ``DEC:.tay.myhost::user'' syntaxes (bletch).
*/
if (*p == ':' || *p == '.')
{
if (cmtlev <= 0 && !qmode)
quoteit = TRUE;
if (copylev > 0 && !skipping)
{
*bp++ = c;
*bp++ = *p;
}
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(MustQuoteChars, c) != NULL)
{
/*
** If these occur as the phrase part of a <>
** construct, but are not inside of () or already
** quoted, they will have to be quoted. Note that
** now (but don't actually do the quoting).
*/
if (cmtlev <= 0 && !qmode)
quoteit = TRUE;
}
/* check for angle brackets */
if (c == '<')
{
register char *q;
/* assume first of two angles is bogus */
if (gotangle)
quoteit = TRUE;
gotangle = TRUE;
/* oops -- have to change our mind */
anglelev = 1;
if (!skipping)
realanglelev = 1;
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -