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

📄 savemail.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			}

			/* Final-Recipient: -- the name from the RCPT command */
			p = e->e_parent->e_from.q_mailer->m_addrtype;
			if (p == NULL)
				p = "rfc822";
			for (r = q; r->q_alias != NULL; r = r->q_alias)
				continue;
			if (strcasecmp(p, "rfc822") != 0)
			{
				(void) snprintf(buf, sizeof buf,
						"Final-Recipient: %s; %.800s",
						r->q_mailer->m_addrtype,
						r->q_user);
			}
			else if (strchr(r->q_user, '@') != NULL)
			{
				(void) snprintf(buf, sizeof buf,
						"Final-Recipient: %s; %.800s",
						p, r->q_user);
			}
			else if (strchr(r->q_paddr, '@') != NULL)
			{
				char *qp;
				bool b;

				qp = r->q_paddr;
				/* strip brackets from address */
				b = FALSE;
				if (*qp == '<')
				{
					b = qp[strlen(qp) - 1]  == '>';
					if (b)
						qp[strlen(qp) - 1] = '\0';
					qp++;
				}
				(void) snprintf(buf, sizeof buf,
						"Final-Recipient: %s; %.800s",
						p, qp);
				/* undo damage */
				if (b)
					qp[strlen(qp)] = '>';
			}
			else
			{
				(void) snprintf(buf, sizeof buf,
						"Final-Recipient: %s; %.700s@%.100s",
						p, r->q_user, MyHostName);
			}
			putline(buf, mci);

			/* X-Actual-Recipient: -- the real problem address */
			if (r != q && q->q_user[0] != '\0')
			{
				if (q->q_mailer != NULL &&
				    q->q_mailer->m_addrtype != NULL)
					p = q->q_mailer->m_addrtype;
				else
					p = "rfc822";

				if (strcasecmp(p, "rfc822") == 0 &&
				    strchr(q->q_user, '@') == NULL)
				{
					(void) snprintf(buf, sizeof buf,
							"X-Actual-Recipient: %s; %.700s@%.100s",
							p, q->q_user,
							MyHostName);
				}
				else
				{
					(void) snprintf(buf, sizeof buf,
							"X-Actual-Recipient: %s; %.800s",
							p, q->q_user);
				}
				putline(buf, mci);
			}

			/* Action: -- what happened? */
			snprintf(buf, sizeof buf, "Action: %s", action);
			putline(buf, mci);

			/* Status: -- what _really_ happened? */
			if (q->q_status != NULL)
				p = q->q_status;
			else if (QS_IS_BADADDR(q->q_state))
				p = "5.0.0";
			else if (QS_IS_QUEUEUP(q->q_state))
				p = "4.0.0";
			else
				p = "2.0.0";
			snprintf(buf, sizeof buf, "Status: %s", p);
			putline(buf, mci);

			/* Remote-MTA: -- who was I talking to? */
			if (q->q_statmta != NULL)
			{
				if (q->q_mailer == NULL ||
				    (p = q->q_mailer->m_mtatype) == NULL)
					p = "dns";
				(void) snprintf(buf, sizeof buf,
						"Remote-MTA: %s; %.800s",
						p, q->q_statmta);
				p = &buf[strlen(buf) - 1];
				if (*p == '.')
					*p = '\0';
				putline(buf, mci);
			}

			/* Diagnostic-Code: -- actual result from other end */
			if (q->q_rstatus != NULL)
			{
				p = q->q_mailer->m_diagtype;
				if (p == NULL)
					p = "smtp";
				(void) snprintf(buf, sizeof buf,
						"Diagnostic-Code: %s; %.800s",
						p, q->q_rstatus);
				putline(buf, mci);
			}

			/* Last-Attempt-Date: -- fine granularity */
			if (q->q_statdate == (time_t) 0L)
				q->q_statdate = curtime();
			(void) snprintf(buf, sizeof buf,
					"Last-Attempt-Date: %s",
					arpadate(ctime(&q->q_statdate)));
			putline(buf, mci);

			/* Will-Retry-Until: -- for delayed messages only */
			if (QS_IS_QUEUEUP(q->q_state))
			{
				time_t xdate;

				xdate = e->e_parent->e_ctime +
					TimeOuts.to_q_return[e->e_parent->e_timeoutclass];
				snprintf(buf, sizeof buf,
					 "Will-Retry-Until: %s",
					 arpadate(ctime(&xdate)));
				putline(buf, mci);
			}
		}
	}
#endif /* DSN */

	/*
	**  Output text of original message
	*/

	putline("", mci);
	if (bitset(EF_HAS_DF, e->e_parent->e_flags))
	{
		sendbody = !bitset(EF_NO_BODY_RETN, e->e_parent->e_flags) &&
			   !bitset(EF_NO_BODY_RETN, e->e_flags);

		if (e->e_msgboundary == NULL)
		{
			if (sendbody)
				putline("   ----- Original message follows -----\n", mci);
			else
				putline("   ----- Message header follows -----\n", mci);
		}
		else
		{
			(void) snprintf(buf, sizeof buf, "--%s",
					e->e_msgboundary);

			putline(buf, mci);
			(void) snprintf(buf, sizeof buf, "Content-Type: %s",
					sendbody ? "message/rfc822"
						 : "text/rfc822-headers");
			putline(buf, mci);

			p = hvalue("Content-Transfer-Encoding",
				   e->e_parent->e_header);
			if (p != NULL && strcasecmp(p, "binary") != 0)
				p = NULL;
			if (p == NULL &&
			    bitset(EF_HAS8BIT, e->e_parent->e_flags))
				p = "8bit";
			if (p != NULL)
			{
				(void) snprintf(buf, sizeof buf,
						"Content-Transfer-Encoding: %s",
						p);
				putline(buf, mci);
			}
		}
		putline("", mci);
		save_errno = errno;
		putheader(mci, e->e_parent->e_header, e->e_parent, M87F_OUTER);
		errno = save_errno;
		if (sendbody)
			putbody(mci, e->e_parent, e->e_msgboundary);
		else if (e->e_msgboundary == NULL)
		{
			putline("", mci);
			putline("   ----- Message body suppressed -----", mci);
		}
	}
	else if (e->e_msgboundary == NULL)
	{
		putline("  ----- No message was collected -----\n", mci);
	}

	if (e->e_msgboundary != NULL)
	{
		putline("", mci);
		(void) snprintf(buf, sizeof buf, "--%s--", e->e_msgboundary);
		putline(buf, mci);
	}
	putline("", mci);
	(void) fflush(mci->mci_out);

	/*
	**  Cleanup and exit
	*/

	if (errno != 0)
		syserr("errbody: I/O error");
}
/*
**  SMTPTODSN -- convert SMTP to DSN status code
**
**	Parameters:
**		smtpstat -- the smtp status code (e.g., 550).
**
**	Returns:
**		The DSN version of the status code.
*/

char *
smtptodsn(smtpstat)
	int smtpstat;
{
	if (smtpstat < 0)
		return "4.4.2";

	switch (smtpstat)
	{
	  case 450:	/* Req mail action not taken: mailbox unavailable */
		return "4.2.0";

	  case 451:	/* Req action aborted: local error in processing */
		return "4.3.0";

	  case 452:	/* Req action not taken: insufficient sys storage */
		return "4.3.1";

	  case 500:	/* Syntax error, command unrecognized */
		return "5.5.2";

	  case 501:	/* Syntax error in parameters or arguments */
		return "5.5.4";

	  case 502:	/* Command not implemented */
		return "5.5.1";

	  case 503:	/* Bad sequence of commands */
		return "5.5.1";

	  case 504:	/* Command parameter not implemented */
		return "5.5.4";

	  case 550:	/* Req mail action not taken: mailbox unavailable */
		return "5.2.0";

	  case 551:	/* User not local; please try <...> */
		return "5.1.6";

	  case 552:	/* Req mail action aborted: exceeded storage alloc */
		return "5.2.2";

	  case 553:	/* Req action not taken: mailbox name not allowed */
		return "5.1.0";

	  case 554:	/* Transaction failed */
		return "5.0.0";
	}

	if ((smtpstat / 100) == 2)
		return "2.0.0";
	if ((smtpstat / 100) == 4)
		return "4.0.0";
	return "5.0.0";
}
/*
**  XTEXTIFY -- take regular text and turn it into DSN-style xtext
**
**	Parameters:
**		t -- the text to convert.
**		taboo -- additional characters that must be encoded.
**
**	Returns:
**		The xtext-ified version of the same string.
*/

char *
xtextify(t, taboo)
	register char *t;
	char *taboo;
{
	register char *p;
	int l;
	int nbogus;
	static char *bp = NULL;
	static int bplen = 0;

	if (taboo == NULL)
		taboo = "";

	/* figure out how long this xtext will have to be */
	nbogus = l = 0;
	for (p = t; *p != '\0'; p++)
	{
		register int c = (*p & 0xff);

		/* ASCII dependence here -- this is the way the spec words it */
		if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' ||
		    strchr(taboo, c) != NULL)
			nbogus++;
		l++;
	}
	if (nbogus == 0)
		return t;
	l += nbogus * 2 + 1;

	/* now allocate space if necessary for the new string */
	if (l > bplen)
	{
		if (bp != NULL)
			free(bp);
		bp = xalloc(l);
		bplen = l;
	}

	/* ok, copy the text with byte expansion */
	for (p = bp; *t != '\0'; )
	{
		register int c = (*t++ & 0xff);

		/* ASCII dependence here -- this is the way the spec words it */
		if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' ||
		    strchr(taboo, c) != NULL)
		{
			*p++ = '+';
			*p++ = "0123456789ABCDEF"[c >> 4];
			*p++ = "0123456789ABCDEF"[c & 0xf];
		}
		else
			*p++ = c;
	}
	*p = '\0';
	return bp;
}
/*
**  XUNTEXTIFY -- take xtext and turn it into plain text
**
**	Parameters:
**		t -- the xtextified text.
**
**	Returns:
**		The decoded text.  No attempt is made to deal with
**		null strings in the resulting text.
*/

char *
xuntextify(t)
	register char *t;
{
	register char *p;
	int l;
	static char *bp = NULL;
	static int bplen = 0;

	/* heuristic -- if no plus sign, just return the input */
	if (strchr(t, '+') == NULL)
		return t;

	/* xtext is always longer than decoded text */
	l = strlen(t);
	if (l > bplen)
	{
		if (bp != NULL)
			free(bp);
		bp = xalloc(l);
		bplen = l;
	}

	/* ok, copy the text with byte compression */
	for (p = bp; *t != '\0'; t++)
	{
		register int c = *t & 0xff;

		if (c != '+')
		{
			*p++ = c;
			continue;
		}

		c = *++t & 0xff;
		if (!isascii(c) || !isxdigit(c))
		{
			/* error -- first digit is not hex */
			usrerr("bogus xtext: +%c", c);
			t--;
			continue;
		}
		if (isdigit(c))
			c -= '0';
		else if (isupper(c))
			c -= 'A' - 10;
		else
			c -= 'a' - 10;
		*p = c << 4;

		c = *++t & 0xff;
		if (!isascii(c) || !isxdigit(c))
		{
			/* error -- second digit is not hex */
			usrerr("bogus xtext: +%x%c", *p >> 4, c);
			t--;
			continue;
		}
		if (isdigit(c))
			c -= '0';
		else if (isupper(c))
			c -= 'A' - 10;
		else
			c -= 'a' - 10;
		*p++ |= c;
	}
	*p = '\0';
	return bp;
}
/*
**  XTEXTOK -- check if a string is legal xtext
**
**	Xtext is used in Delivery Status Notifications.  The spec was
**	taken from RFC 1891, ``SMTP Service Extension for Delivery
**	Status Notifications''.
**
**	Parameters:
**		s -- the string to check.
**
**	Returns:
**		TRUE -- if 's' is legal xtext.
**		FALSE -- if it has any illegal characters in it.
*/

bool
xtextok(s)
	char *s;
{
	int c;

	while ((c = *s++) != '\0')
	{
		if (c == '+')
		{
			c = *s++;
			if (!isascii(c) || !isxdigit(c))
				return FALSE;
			c = *s++;
			if (!isascii(c) || !isxdigit(c))
				return FALSE;
		}
		else if (c < '!' || c > '~' || c == '=')
			return FALSE;
	}
	return TRUE;
}
/*
**  PRUNEROUTE -- prune an RFC-822 source route
**
**	Trims down a source route to the last internet-registered hop.
**	This is encouraged by RFC 1123 section 5.3.3.
**
**	Parameters:
**		addr -- the address
**
**	Returns:
**		TRUE -- address was modified
**		FALSE -- address could not be pruned
**
**	Side Effects:
**		modifies addr in-place
*/

static bool
pruneroute(addr)
	char *addr;
{
#if NAMED_BIND
	char *start, *at, *comma;
	char c;
	int rcode;
	int i;
	char hostbuf[BUFSIZ];
	char *mxhosts[MAXMXHOSTS + 1];

	/* check to see if this is really a route-addr */
	if (*addr != '<' || addr[1] != '@' || addr[strlen(addr) - 1] != '>')
		return FALSE;
	start = strchr(addr, ':');
	at = strrchr(addr, '@');
	if (start == NULL || at == NULL || at < start)
		return FALSE;

	/* slice off the angle brackets */
	i = strlen(at + 1);
	if (i >= (SIZE_T) sizeof hostbuf)
		return FALSE;
	(void) strlcpy(hostbuf, at + 1, sizeof hostbuf);
	hostbuf[i - 1] = '\0';

	while (start)
	{
		if (getmxrr(hostbuf, mxhosts, NULL, FALSE, &rcode) > 0)
		{
			(void) strlcpy(addr + 1, start + 1, strlen(addr) - 1);
			return TRUE;
		}
		c = *start;
		*start = '\0';
		comma = strrchr(addr, ',');
		if (comma != NULL && comma[1] == '@' &&
		    strlen(comma + 2) < (SIZE_T) sizeof hostbuf)
			(void) strlcpy(hostbuf, comma + 2, sizeof hostbuf);
		else
			comma = NULL;
		*start = c;
		start = comma;
	}
#endif /* NAMED_BIND */
	return FALSE;
}

⌨️ 快捷键说明

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