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

📄 srvrsmtp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (p == NULL)				break;			a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', NULL, e);			if (a == NULL)				break;			a->q_flags |= QPRIMARY;			a = recipient(a, &e->e_sendqueue, e);			if (Errors != 0)				break;			/* no errors during parsing, but might be a duplicate */			e->e_to = p;			if (!bitset(QBADADDR, a->q_flags))			{				message("250 Recipient ok%s",					bitset(QQUEUEUP, a->q_flags) ?						" (will queue)" : "");				nrcpts++;			}			else			{				/* punt -- should keep message in ADDRESS.... */				message("550 Addressee unknown");			}			e->e_to = NULL;			break;		  case CMDDATA:		/* data -- text of mail */			SmtpPhase = "server DATA";			if (!gotmail)			{				message("503 Need MAIL command");				break;			}			else if (nrcpts <= 0)			{				message("503 Need RCPT (recipient)");				break;			}			/* check to see if we need to re-expand aliases */			/* also reset QBADADDR on already-diagnosted addrs */			doublequeue = FALSE;			for (a = e->e_sendqueue; a != NULL; a = a->q_next)			{				if (bitset(QVERIFIED, a->q_flags))				{					/* need to re-expand aliases */					doublequeue = TRUE;				}				if (bitset(QBADADDR, a->q_flags))				{					/* make this "go away" */					a->q_flags |= QDONTSEND;					a->q_flags &= ~QBADADDR;				}			}			/* collect the text of the message */			SmtpPhase = "collect";			collect(TRUE, doublequeue, e);			if (Errors != 0)				goto abortmessage;			HoldErrs = TRUE;			/*			**  Arrange to send to everyone.			**	If sending to multiple people, mail back			**		errors rather than reporting directly.			**	In any case, don't mail back errors for			**		anything that has happened up to			**		now (the other end will do this).			**	Truncate our transcript -- the mail has gotten			**		to us successfully, and if we have			**		to mail this back, it will be easier			**		on the reader.			**	Then send to everyone.			**	Finally give a reply code.  If an error has			**		already been given, don't mail a			**		message back.			**	We goose error returns by clearing error bit.			*/			SmtpPhase = "delivery";			if (nrcpts != 1 && !doublequeue)			{				HoldErrs = TRUE;				e->e_errormode = EM_MAIL;			}			e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp);			id = e->e_id;			/* send to all recipients */			sendall(e, doublequeue ? SM_QUEUE : SM_DEFAULT);			e->e_to = NULL;			/* issue success if appropriate and reset */			if (Errors == 0 || HoldErrs)				message("250 %s Message accepted for delivery", id);			if (bitset(EF_FATALERRS, e->e_flags) && !HoldErrs)			{				/* avoid sending back an extra message */				e->e_flags &= ~EF_FATALERRS;				e->e_flags |= EF_CLRQUEUE;			}			else			{				/* from now on, we have to operate silently */				HoldErrs = TRUE;				e->e_errormode = EM_MAIL;				/* if we just queued, poke it */				if (doublequeue && e->e_sendmode != SM_QUEUE)				{					extern pid_t dowork();					unlockqueue(e);					(void) dowork(id, TRUE, TRUE, e);				}			}  abortmessage:			/* if in a child, pop back to our parent */			if (InChild)				finis();			/* clean up a bit */			gotmail = FALSE;			dropenvelope(e);			CurEnv = e = newenvelope(e, CurEnv);			e->e_flags = BlankEnvelope.e_flags;			break;		  case CMDRSET:		/* rset -- reset state */			message("250 Reset state");			e->e_flags |= EF_CLRQUEUE;			if (InChild)				finis();			/* clean up a bit */			gotmail = FALSE;			dropenvelope(e);			CurEnv = e = newenvelope(e, CurEnv);			break;		  case CMDVRFY:		/* vrfy -- verify address */		  case CMDEXPN:		/* expn -- expand address */			vrfy = c->cmdcode == CMDVRFY;			if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,						PrivacyFlags))			{				if (vrfy)					message("252 Who's to say?");				else					message("502 Sorry, we do not allow this operation");#ifdef LOG				if (LogLevel > 5)					syslog(LOG_INFO, "%s: %s [rejected]",						CurSmtpClient, inp);#endif				break;			}			else if (!gothello &&				 bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,						PrivacyFlags))			{				message("503 I demand that you introduce yourself first");				break;			}			if (runinchild(vrfy ? "SMTP-VRFY" : "SMTP-EXPN", e) > 0)				break;#ifdef LOG			if (LogLevel > 5)				syslog(LOG_INFO, "%s: %s", CurSmtpClient, inp);#endif			vrfyqueue = NULL;			QuickAbort = TRUE;			if (vrfy)				e->e_flags |= EF_VRFYONLY;			while (*p != '\0' && isascii(*p) && isspace(*p))				*p++;			if (*p == '\0')			{				message("501 Argument required");				Errors++;			}			else			{				(void) sendtolist(p, NULLADDR, &vrfyqueue, e);			}			if (Errors != 0)			{				if (InChild)					finis();				break;			}			if (vrfyqueue == NULL)			{				message("554 Nothing to %s", vrfy ? "VRFY" : "EXPN");			}			while (vrfyqueue != NULL)			{				a = vrfyqueue;				while ((a = a->q_next) != NULL &&				       bitset(QDONTSEND|QBADADDR, a->q_flags))					continue;				if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))					printvrfyaddr(vrfyqueue, a == NULL);				vrfyqueue = vrfyqueue->q_next;			}			if (InChild)				finis();			break;		  case CMDHELP:		/* help -- give user info */			help(p);			break;		  case CMDNOOP:		/* noop -- do nothing */			message("250 OK");			break;		  case CMDQUIT:		/* quit -- leave mail */			message("221 %s closing connection", MyHostName);doquit:			/* avoid future 050 messages */			disconnect(1, e);			if (InChild)				ExitStat = EX_QUIT;			finis();		  case CMDVERB:		/* set verbose mode */			if (bitset(PRIV_NOEXPN, PrivacyFlags))			{				/* this would give out the same info */				message("502 Verbose unavailable");				break;			}			Verbose = TRUE;			e->e_sendmode = SM_DELIVER;			message("250 Verbose mode");			break;		  case CMDONEX:		/* doing one transaction only */			OneXact = TRUE;			message("250 Only one transaction");			break;# ifdef SMTPDEBUG		  case CMDDBGQSHOW:	/* show queues */			printf("Send Queue=");			printaddr(e->e_sendqueue, TRUE);			break;		  case CMDDBGDEBUG:	/* set debug mode */			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");			tTflag(p);			message("200 Debug set");			break;# else /* not SMTPDEBUG */		  case CMDDBGQSHOW:	/* show queues */		  case CMDDBGDEBUG:	/* set debug mode */# endif /* SMTPDEBUG */		  case CMDLOGBOGUS:	/* bogus command */# ifdef LOG			if (LogLevel > 0)				syslog(LOG_CRIT,				    "\"%s\" command from %s (%s)",				    c->cmdname, peerhostname,				    anynet_ntoa(&RealHostAddr));# endif			/* FALL THROUGH */		  case CMDERROR:	/* unknown command */			if (++badcommands > MAXBADCOMMANDS)			{				message("421 %s Too many bad commands; closing connection",					MyHostName);				goto doquit;			}			message("500 Command unrecognized");			break;		  default:			errno = 0;			syserr("500 smtp: unknown code %d", c->cmdcode);			break;		}	}}/***  SKIPWORD -- skip a fixed word.****	Parameters:**		p -- place to start looking.**		w -- word to skip.****	Returns:**		p following w.**		NULL on error.****	Side Effects:**		clobbers the p data area.*/static char *skipword(p, w)	register char *p;	char *w;{	register char *q;	char *firstp = p;	/* find beginning of word */	while (isascii(*p) && isspace(*p))		p++;	q = p;	/* find end of word */	while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))		p++;	while (isascii(*p) && isspace(*p))		*p++ = '\0';	if (*p != ':')	{	  syntax:		message("501 Syntax error in parameters scanning \"%s\"",			firstp);		Errors++;		return (NULL);	}	*p++ = '\0';	while (isascii(*p) && isspace(*p))		p++;	if (*p == '\0')		goto syntax;	/* see if the input word matches desired word */	if (strcasecmp(q, w))		goto syntax;	return (p);}/***  PRINTVRFYADDR -- print an entry in the verify queue****	Parameters:**		a -- the address to print**		last -- set if this is the last one.****	Returns:**		none.****	Side Effects:**		Prints the appropriate 250 codes.*/printvrfyaddr(a, last)	register ADDRESS *a;	bool last;{	char fmtbuf[20];	strcpy(fmtbuf, "250");	fmtbuf[3] = last ? ' ' : '-';	if (a->q_fullname == NULL)	{		if (strchr(a->q_user, '@') == NULL)			strcpy(&fmtbuf[4], "<%s@%s>");		else			strcpy(&fmtbuf[4], "<%s>");		message(fmtbuf, a->q_user, MyHostName);	}	else	{		if (strchr(a->q_user, '@') == NULL)			strcpy(&fmtbuf[4], "%s <%s@%s>");		else			strcpy(&fmtbuf[4], "%s <%s>");		message(fmtbuf, a->q_fullname, a->q_user, MyHostName);	}}/***  HELP -- implement the HELP command.****	Parameters:**		topic -- the topic we want help for.****	Returns:**		none.****	Side Effects:**		outputs the help file to message output.*/help(topic)	char *topic;{	register FILE *hf;	int len;	char buf[MAXLINE];	bool noinfo;	if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)	{		/* no help */		errno = 0;		message("502 HELP not implemented");		return;	}	if (topic == NULL || *topic == '\0')		topic = "smtp";	else		makelower(topic);	len = strlen(topic);	noinfo = TRUE;	while (fgets(buf, sizeof buf, hf) != NULL)	{		if (strncmp(buf, topic, len) == 0)		{			register char *p;			p = strchr(buf, '\t');			if (p == NULL)				p = buf;			else				p++;			fixcrlf(p, TRUE);			message("214-%s", p);			noinfo = FALSE;		}	}	if (noinfo)		message("504 HELP topic unknown");	else		message("214 End of HELP info");	(void) fclose(hf);}/***  RUNINCHILD -- return twice -- once in the child, then in the parent again****	Parameters:**		label -- a string used in error messages****	Returns:**		zero in the child**		one in the parent****	Side Effects:**		none.*/runinchild(label, e)	char *label;	register ENVELOPE *e;{	int childpid;	if (!OneXact)	{		childpid = dofork();		if (childpid < 0)		{			syserr("%s: cannot fork", label);			return (1);		}		if (childpid > 0)		{			auto int st;			/* parent -- wait for child to complete */			setproctitle("server %s child wait", CurHostName);			st = waitfor(childpid);			if (st == -1)				syserr("%s: lost child", label);			else if (!WIFEXITED(st))				syserr("%s: died on signal %d",					label, st & 0177);			/* if we exited on a QUIT command, complete the process */			if (WEXITSTATUS(st) == EX_QUIT)			{				disconnect(1, e);				finis();			}			return (1);		}		else		{			/* child */			InChild = TRUE;			QuickAbort = FALSE;			clearenvelope(e, FALSE);		}	}	/* open alias database */	initmaps(FALSE, e);	return (0);}# endif /* SMTP */

⌨️ 快捷键说明

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