⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recipient.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
 * Copyright (c) 1988, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 */

#ifndef lint
static char id[] = "@(#)$Id: recipient.c,v 8.231.14.8 2000/09/14 23:32:27 gshapiro Exp $";
#endif /* ! lint */

#include <sendmail.h>


static void	includetimeout __P((void));
static ADDRESS	*self_reference __P((ADDRESS *));

/*
**  SENDTOLIST -- Designate a send list.
**
**	The parameter is a comma-separated list of people to send to.
**	This routine arranges to send to all of them.
**
**	Parameters:
**		list -- the send list.
**		ctladdr -- the address template for the person to
**			send to -- effective uid/gid are important.
**			This is typically the alias that caused this
**			expansion.
**		sendq -- a pointer to the head of a queue to put
**			these people into.
**		aliaslevel -- the current alias nesting depth -- to
**			diagnose loops.
**		e -- the envelope in which to add these recipients.
**
**	Returns:
**		The number of addresses actually on the list.
**
**	Side Effects:
**		none.
*/

/* q_flags bits inherited from ctladdr */
#define QINHERITEDBITS	(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY)

int
sendtolist(list, ctladdr, sendq, aliaslevel, e)
	char *list;
	ADDRESS *ctladdr;
	ADDRESS **sendq;
	int aliaslevel;
	register ENVELOPE *e;
{
	register char *p;
	register ADDRESS *al;	/* list of addresses to send to */
	char delimiter;		/* the address delimiter */
	int naddrs;
	int i;
	char *oldto = e->e_to;
	char *bufp;
	char buf[MAXNAME + 1];

	if (list == NULL)
	{
		syserr("sendtolist: null list");
		return 0;
	}

	if (tTd(25, 1))
	{
		dprintf("sendto: %s\n   ctladdr=", list);
		printaddr(ctladdr, FALSE);
	}

	/* heuristic to determine old versus new style addresses */
	if (ctladdr == NULL &&
	    (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
	     strchr(list, '<') != NULL || strchr(list, '(') != NULL))
		e->e_flags &= ~EF_OLDSTYLE;
	delimiter = ' ';
	if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
		delimiter = ',';

	al = NULL;
	naddrs = 0;

	/* make sure we have enough space to copy the string */
	i = strlen(list) + 1;
	if (i <= sizeof buf)
	{
		bufp = buf;
		i = sizeof buf;
	}
	else
		bufp = xalloc(i);
	(void) strlcpy(bufp, denlstring(list, FALSE, TRUE), i);

#if _FFR_ADDR_TYPE
	define(macid("{addr_type}", NULL), "e r", e);
#endif /* _FFR_ADDR_TYPE */
	for (p = bufp; *p != '\0'; )
	{
		auto char *delimptr;
		register ADDRESS *a;

		/* parse the address */
		while ((isascii(*p) && isspace(*p)) || *p == ',')
			p++;
		a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);
		p = delimptr;
		if (a == NULL)
			continue;
		a->q_next = al;
		a->q_alias = ctladdr;

		/* arrange to inherit attributes from parent */
		if (ctladdr != NULL)
		{
			ADDRESS *b;

			/* self reference test */
			if (sameaddr(ctladdr, a))
			{
				if (tTd(27, 5))
				{
					dprintf("sendtolist: QSELFREF ");
					printaddr(ctladdr, FALSE);
				}
				ctladdr->q_flags |= QSELFREF;
			}

			/* check for address loops */
			b = self_reference(a);
			if (b != NULL)
			{
				b->q_flags |= QSELFREF;
				if (tTd(27, 5))
				{
					dprintf("sendtolist: QSELFREF ");
					printaddr(b, FALSE);
				}
				if (a != b)
				{
					if (tTd(27, 5))
					{
						dprintf("sendtolist: QS_DONTSEND ");
						printaddr(a, FALSE);
					}
					a->q_state = QS_DONTSEND;
					b->q_flags |= a->q_flags & QNOTREMOTE;
					continue;
				}
			}

			/* full name */
			if (a->q_fullname == NULL)
				a->q_fullname = ctladdr->q_fullname;

			/* various flag bits */
			a->q_flags &= ~QINHERITEDBITS;
			a->q_flags |= ctladdr->q_flags & QINHERITEDBITS;

			/* original recipient information */
			a->q_orcpt = ctladdr->q_orcpt;
		}

		al = a;
	}

	/* arrange to send to everyone on the local send list */
	while (al != NULL)
	{
		register ADDRESS *a = al;

		al = a->q_next;
		a = recipient(a, sendq, aliaslevel, e);
		naddrs++;
	}

	e->e_to = oldto;
	if (bufp != buf)
		free(bufp);
#if _FFR_ADDR_TYPE
	define(macid("{addr_type}", NULL), NULL, e);
#endif /* _FFR_ADDR_TYPE */
	return naddrs;
}
/*
**  REMOVEFROMLIST -- Remove addresses from a send list.
**
**	The parameter is a comma-separated list of recipients to remove.
**	Note that it only deletes matching addresses.  If those addresses
**	have been expended already in the sendq, it won't mark the
**	expanded recipients as QS_REMOVED.
**
**	Parameters:
**		list -- the list to remove.
**		sendq -- a pointer to the head of a queue to remove
**			these addresses from.
**		e -- the envelope in which to remove these recipients.
**
**	Returns:
**		The number of addresses removed from the list.
**
*/

int
removefromlist(list, sendq, e)
	char *list;
	ADDRESS **sendq;
	ENVELOPE *e;
{
	char delimiter;		/* the address delimiter */
	int naddrs;
	int i;
	char *p;
	char *oldto = e->e_to;
	char *bufp;
	char buf[MAXNAME + 1];

	if (list == NULL)
	{
		syserr("removefromlist: null list");
		return 0;
	}

	if (tTd(25, 1))
		dprintf("removefromlist: %s\n", list);

	/* heuristic to determine old versus new style addresses */
	if (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
	    strchr(list, '<') != NULL || strchr(list, '(') != NULL)
		e->e_flags &= ~EF_OLDSTYLE;
	delimiter = ' ';
	if (!bitset(EF_OLDSTYLE, e->e_flags))
		delimiter = ',';

	naddrs = 0;

	/* make sure we have enough space to copy the string */
	i = strlen(list) + 1;
	if (i <= sizeof buf)
	{
		bufp = buf;
		i = sizeof buf;
	}
	else
		bufp = xalloc(i);
	(void) strlcpy(bufp, denlstring(list, FALSE, TRUE), i);

#if _FFR_ADDR_TYPE
	define(macid("{addr_type}", NULL), "e r", e);
#endif /* _FFR_ADDR_TYPE */
	for (p = bufp; *p != '\0'; )
	{
		ADDRESS a;		/* parsed address to be removed */
		ADDRESS *q;
		ADDRESS **pq;
		char *delimptr;

		/* parse the address */
		while ((isascii(*p) && isspace(*p)) || *p == ',')
			p++;
		if (parseaddr(p, &a, RF_COPYALL,
			      delimiter, &delimptr, e) == NULL)
		{
			p = delimptr;
			continue;
		}
		p = delimptr;
		for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
		{
			if (!QS_IS_DEAD(q->q_state) &&
			    sameaddr(q, &a))
			{
				if (tTd(25, 5))
				{
					dprintf("removefromlist: QS_REMOVED ");
					printaddr(&a, FALSE);
				}
				q->q_state = QS_REMOVED;
				naddrs++;
				break;
			}
		}
	}

	e->e_to = oldto;
	if (bufp != buf)
		free(bufp);
#if _FFR_ADDR_TYPE
	define(macid("{addr_type}", NULL), NULL, e);
#endif /* _FFR_ADDR_TYPE */
	return naddrs;
}
/*
**  RECIPIENT -- Designate a message recipient
**
**	Saves the named person for future mailing.
**
**	Parameters:
**		a -- the (preparsed) address header for the recipient.
**		sendq -- a pointer to the head of a queue to put the
**			recipient in.  Duplicate suppression is done
**			in this queue.
**		aliaslevel -- the current alias nesting depth.
**		e -- the current envelope.
**
**	Returns:
**		The actual address in the queue.  This will be "a" if
**		the address is not a duplicate, else the original address.
**
**	Side Effects:
**		none.
*/

ADDRESS *
recipient(a, sendq, aliaslevel, e)
	register ADDRESS *a;
	register ADDRESS **sendq;
	int aliaslevel;
	register ENVELOPE *e;
{
	register ADDRESS *q;
	ADDRESS **pq;
	register struct mailer *m;
	register char *p = NULL;
	bool quoted = FALSE;		/* set if the addr has a quote bit */
	int findusercount = 0;
	bool initialdontsend = QS_IS_DEAD(a->q_state);
	int i, buflen;
	char *buf;
	char buf0[MAXNAME + 1];		/* unquoted image of the user name */

	e->e_to = a->q_paddr;
	m = a->q_mailer;
	errno = 0;
	if (aliaslevel == 0)
		a->q_flags |= QPRIMARY;
	if (tTd(26, 1))
	{
		dprintf("\nrecipient (%d): ", aliaslevel);
		printaddr(a, FALSE);
	}

	/* if this is primary, add it to the original recipient list */
	if (a->q_alias == NULL)
	{
		if (e->e_origrcpt == NULL)
			e->e_origrcpt = a->q_paddr;
		else if (e->e_origrcpt != a->q_paddr)
			e->e_origrcpt = "";
	}

#if _FFR_GEN_ORCPT
	/* set ORCPT DSN arg if not already set */
	if (a->q_orcpt == NULL)
	{
		for (q = a; q->q_alias != NULL; q = q->q_alias)
			continue;

		/* check for an existing ORCPT */
		if (q->q_orcpt != NULL)
			a->q_orcpt = q->q_orcpt;
		else
		{
			/* make our own */
			bool b = FALSE;
			char *qp;
			char obuf[MAXLINE];

			if (e->e_from.q_mailer != NULL)
				p = e->e_from.q_mailer->m_addrtype;
			if (p == NULL)
				p = "rfc822";
			(void) strlcpy(obuf, p, sizeof obuf);
			(void) strlcat(obuf, ";", sizeof obuf);

			qp = q->q_paddr;

			/* FFR: Needs to strip comments from stdin addrs */

			/* strip brackets from address */
			if (*qp == '<')
			{
				b = qp[strlen(qp) - 1] == '>';
				if (b)
					qp[strlen(qp) - 1] = '\0';
				qp++;
			}

			p = xtextify(denlstring(qp, TRUE, FALSE), NULL);

			if (strlcat(obuf, p, sizeof obuf) >= sizeof obuf)
			{
				/* if too big, don't use it */
				obuf[0] = '\0';
			}

			/* undo damage */
			if (b)
				qp[strlen(qp)] = '>';

			if (obuf[0] != '\0')
				a->q_orcpt = newstr(obuf);
		}
	}
#endif /* _FFR_GEN_ORCPT */

	/* break aliasing loops */
	if (aliaslevel > MaxAliasRecursion)
	{
		a->q_state = QS_BADADDR;
		a->q_status = "5.4.6";
		usrerrenh(a->q_status,
			  "554 aliasing/forwarding loop broken (%d aliases deep; %d max)",
			  aliaslevel, MaxAliasRecursion);
		return a;
	}

	/*
	**  Finish setting up address structure.
	*/

	/* get unquoted user for file, program or user.name check */
	i = strlen(a->q_user);
	if (i >= sizeof buf0)
	{
		buflen = i + 1;
		buf = xalloc(buflen);
	}
	else
	{
		buf = buf0;
		buflen = sizeof buf0;
	}
	(void) strlcpy(buf, a->q_user, buflen);
	for (p = buf; *p != '\0' && !quoted; p++)
	{
		if (*p == '\\')
			quoted = TRUE;
	}
	stripquotes(buf);

	/* check for direct mailing to restricted mailers */
	if (m == ProgMailer)
	{
		if (a->q_alias == NULL)
		{
			a->q_state = QS_BADADDR;
			a->q_status = "5.7.1";
			usrerrenh(a->q_status,
				  "550 Cannot mail directly to programs");
		}
		else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
		{
			a->q_state = QS_BADADDR;
			a->q_status = "5.7.1";
			if (a->q_alias->q_ruser == NULL)
				usrerrenh(a->q_status,
					  "550 UID %d is an unknown user: cannot mail to programs",
					  a->q_alias->q_uid);
			else
				usrerrenh(a->q_status,
					  "550 User %s@%s doesn't have a valid shell for mailing to programs",
					  a->q_alias->q_ruser, MyHostName);
		}
		else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
		{
			a->q_state = QS_BADADDR;
			a->q_status = "5.7.1";
			a->q_rstatus = newstr("550 Unsafe for mailing to programs");
			usrerrenh(a->q_status,
				  "550 Address %s is unsafe for mailing to programs",
				  a->q_alias->q_paddr);
		}
	}

	/*
	**  Look up this person in the recipient list.
	**	If they are there already, return, otherwise continue.
	**	If the list is empty, just add it.  Notice the cute
	**	hack to make from addresses suppress things correctly:
	**	the QS_DUPLICATE state will be set in the send list.
	**	[Please note: the emphasis is on "hack."]
	*/

	for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
	{
		if (sameaddr(q, a) &&
		    (bitset(QRCPTOK, q->q_flags) ||
		     !bitset(QPRIMARY, q->q_flags)))
		{
			if (tTd(26, 1))
			{
				dprintf("%s in sendq: ", a->q_paddr);
				printaddr(q, FALSE);
			}
			if (!bitset(QPRIMARY, q->q_flags))
			{
				if (!QS_IS_DEAD(a->q_state))
					message("duplicate suppressed");
				else
					q->q_state = QS_DUPLICATE;
				q->q_flags |= a->q_flags;
			}
			else if (bitset(QSELFREF, q->q_flags)
#if _FFR_MILTER
				 || q->q_state == QS_REMOVED
#endif /* _FFR_MILTER */
				 )
			{
#if _FFR_MILTER
				/*
				**  If an earlier milter removed the address,
				**  a later one can still add it back.
				*/
#endif /* _FFR_MILTER */
				q->q_state = a->q_state;
				q->q_flags |= a->q_flags;
			}
			a = q;
			goto done;
		}
	}

	/* add address on list */
	if (pq != NULL)
	{
		*pq = a;
		a->q_next = NULL;
	}

	/*
	**  Alias the name and handle special mailer types.
	*/

  trylocaluser:
	if (tTd(29, 7))
	{
		dprintf("at trylocaluser: ");
		printaddr(a, FALSE);
	}

	if (!QS_IS_OK(a->q_state))
		goto testselfdestruct;

	if (m == InclMailer)
	{
		a->q_state = QS_INCLUDED;
		if (a->q_alias == NULL)
		{
			a->q_state = QS_BADADDR;
			a->q_status = "5.7.1";
			usrerrenh(a->q_status,
				  "550 Cannot mail directly to :include:s");
		}
		else
		{
			int ret;

			message("including file %s", a->q_user);
			ret = include(a->q_user, FALSE, a, sendq, aliaslevel, e);
			if (transienterror(ret))
			{
				if (LogLevel > 2)
					sm_syslog(LOG_ERR, e->e_id,
						  "include %s: transient error: %s",
						  shortenstring(a->q_user, MAXSHORTSTR),
						  errstring(ret));
				a->q_state = QS_QUEUEUP;
				usrerr("451 4.2.4 Cannot open %s: %s",
					shortenstring(a->q_user, MAXSHORTSTR),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -