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

📄 smtpserv.c

📁 uCLinux下的一个TCP/IP协议栈源码
💻 C
📖 第 1 页 / 共 2 页
字号:
							fprintf(fp,"%s%s\n",
								Hdrs[APPARTO],
								ap->val);
						fputc('\n',fp);
						break;
					}
					fputs(buf,fp);
					rip(buf);
					switch(htype(buf)){
					case TO:
					case CC:
						++tocnt;
						break;
					case RRECEIPT:
						if((cp = getaddress(buf,0))
						   != NULL){
							free(host);
							host = strdup(cp);
						}
						break;
					}
				}
				while((c = fread(buf,1,sizeof(buf),data)) > 0)
					if(fwrite(buf,1,c,fp) != c)
						break;
				if(ferror(fp))
					fail = 1;
				else
					fprintf(fp,"\n");
				/* Leave a blank line between msgs */
				fclose(fp);
				printf("New mail arrived for %s\n",ap->val);
				if(host != NULL){
					rewind(data); /* Send return receipt */
					mdaemon(data,host,NULL,0);
					free(host);
				}
			} else 
				fail = 1;
			(void) rmlock(Mailspool,ap->val);
			if (fail)
				break;
			smtplog("deliver: To: %s From: %s",ap->val,from);
		}
	}
	return fail;
}

/* Return Date/Time in Arpanet format in passed string */
char *
ptime(t)
long *t;
{
	/* Print out the time and date field as
	 *		"DAY day MONTH year hh:mm:ss ZONE"
	 */
	register struct tm *ltm;
	static char tz[4];
	static char str[40];
	char *p, *getenv();
	/* Read the system time */
	ltm = localtime(t);

	if (*tz == '\0')
		if ((p = getenv("TZ")) == NULL)
			strcpy(tz,"UTC");
		else
			strncpy(tz,p,3);

	/* rfc 822 format */
	sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
		Days[ltm->tm_wday],
		ltm->tm_mday,
		Months[ltm->tm_mon],
		ltm->tm_year,
		ltm->tm_hour,
		ltm->tm_min,
		ltm->tm_sec,
		tz);
	return(str);
}

long 
get_msgid()
{
	char sfilename[LINELEN];
	char s[20];
	register long sequence = 0;
	FILE *sfile;

	sprintf(sfilename,"%s/sequence.seq",Mailqdir);
	sfile = fopen(sfilename,READ_TEXT);

	/* if sequence file exists, get the value, otherwise set it */
	if (sfile != NULL) {
		(void) fgets(s,sizeof(s),sfile);
		sequence = atol(s);
	/* Keep it in range of and 8 digit number to use for dos name prefix. */
		if (sequence < 0L || sequence > 99999999L )
			sequence = 0;
		fclose(sfile);
	}

	/* increment sequence number, and write to sequence file */
	sfile = fopen(sfilename,WRITE_TEXT);
	fprintf(sfile,"%ld",++sequence);
	fclose(sfile);
	return sequence;
}

#ifdef	MSDOS
/* Illegal characters in a DOS filename */
static char baddoschars[] = "\"[]:|<>+=;,";
#endif

/* test if mail address is valid */
int
validate_address(s)
char *s;
{
	char *cp;
	int32 addr;

	/* if address has @ in it the check dest address */
	if ((cp = strrchr(s,'@')) != NULL) {
		cp++;
		/* 1st check if its our hostname
		* if not then check the hosts file and see
		* if we can resolve ther address to a know site
		* or one of our aliases
		*/
		if (strcmp(cp,Hostname) != 0) {
			if ((addr = mailroute(cp)) == 0
				&& (Smtpmode & QUEUE) == 0)
				return BADADDR;
			if (ismyaddr(addr) == NULL)
				return DOMAIN;
		}
		
		/* on a local address remove the host name part */
		*--cp = '\0';
	}

	/* if using an external router leave address alone */
	if ((Smtpmode & QUEUE) != 0)
		return LOCAL;

	/* check for the user%host hack */
	if ((cp = strrchr(s,'%')) != NULL) {
		*cp = '@';
		cp++;
		/* reroute based on host name following the % seperator */
		if (mailroute(cp) == 0)
			return BADADDR;
		else
			return DOMAIN;
	}

#ifdef MSDOS	/* dos file name checks */
	/* Check for characters illegal in MS-DOS file names */
	for(cp = baddoschars;*cp != '\0';cp++){
		if(strchr(s,*cp) != NULL)
			return BADADDR;	
	}
#endif
	return LOCAL;
}

/* place a mail job in the outbound queue */
int
queuejob(dfile,host,to,from)
FILE *dfile;
char *host;
struct list *to;
char *from;
{
	FILE *fp;
	struct list *ap;
	char tmpstring[50], prefix[9], buf[LINELEN];
	register int cnt;

	sprintf(prefix,"%ld",get_msgid());
	mlock(Mailqdir,prefix);
	sprintf(tmpstring,"%s/%s.txt",Mailqdir,prefix);
	if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
		(void) rmlock(Mailqdir,prefix);
		return 1;
	}
	while((cnt = fread(buf, 1, LINELEN, dfile)) > 0)
		if(fwrite(buf, 1, cnt, fp) != cnt)
			break;
	if(ferror(fp)){
		fclose(fp);
		(void) rmlock(Mailqdir,prefix);
		return 1;
	}
	fclose(fp);
	sprintf(tmpstring,"%s/%s.wrk",Mailqdir,prefix);
	if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
		(void) rmlock(Mailqdir,prefix);
		return 1;
	}
	fprintf(fp,"%s\n%s\n",host,from);
	for(ap = to; ap != NULL; ap = ap->next) {
		fprintf(fp,"%s\n",ap->val);
		smtplog("queue job %s To: %s From: %s",prefix,ap->val,from);
	}
	fclose(fp);
	(void) rmlock(Mailqdir,prefix);
	return 0;
}

/* Deliver mail to the appropriate mail boxes */
static int
router_queue(data,from,to)
FILE *data;
char *from;
struct list *to;
{
	int c;
	register struct list *ap;
	FILE *fp;
	char tmpstring[50];
	char prefix[9];

	sprintf(prefix,"%ld",get_msgid());
	mlock(Routeqdir,prefix);
	sprintf(tmpstring,"%s/%s.txt",Routeqdir,prefix);
	if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
		(void) rmlock(Routeqdir,prefix);
		return 1;
	}
	rewind(data);
	while((c = getc(data)) != EOF)
		if(putc(c,fp) == EOF)
			break;
	if(ferror(fp)){
		fclose(fp);
		(void) rmlock(Routeqdir,prefix);
		return 1;
	}
	fclose(fp);
	sprintf(tmpstring,"%s/%s.wrk",Routeqdir,prefix);
	if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
		(void) rmlock(Routeqdir,prefix);
		return 1;
	}
	fprintf(fp,"From: %s\n",from);
	for(ap = to;ap != NULL;ap = ap->next) {
		fprintf(fp,"To: %s\n",ap->val);
	}
	fclose(fp);
	(void) rmlock(Routeqdir,prefix);
	smtplog("rqueue job %s From: %s",prefix,from);
	return 0;
}

/* add an element to the front of the list pointed to by head 
** return NULL if out of memory.
*/
struct list *
addlist(head,val,type)
struct list **head;
char *val;
int type;
{
	register struct list *tp;

	tp = (struct list *)callocw(1,sizeof(struct list));

	tp->next = NULL;

	/* allocate storage for the char string */
	tp->val = strdup(val);
	tp->type = type;

	/* add entry to front of existing list */
	if (*head == NULL)
		*head = tp;
	else {
		tp->next = *head;
		*head = tp;
	}
	return tp;

}

#define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
#define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;

/* check for and alias and expand alias into a address list */
static struct list *
expandalias(head, user)
struct list **head;
char *user;
{
	FILE *fp;
	register char *s,*p;
	struct rr *rrp, *rrlp;
	int inalias = 0;
	struct list *tp;
	char buf[LINELEN];
	
	/* no alias file found */
	if ((fp = fopen(Alias, READ_TEXT)) == NULL) {
		/* Try MB, MG or MR domain name records */
		rrlp = rrp = resolve_mailb(user);
		while(rrp != NULL){
			if(rrp->rdlength > 0){
				/* remove the trailing dot */
				rrp->rdata.name[rrp->rdlength-1] = '\0';
				/* replace first dot with @ if there is no @ */
				if(strchr(rrp->rdata.name,'@') == NULL
				   && (p = strchr(rrp->rdata.name,'.')) !=
				   NULL)
					*p = '@';
				if(strchr(rrp->rdata.name,'@') != NULL)
					tp = addlist(head,rrp->rdata.name,
						     DOMAIN);
				else
					tp = addlist(head,rrp->rdata.name,
						     LOCAL);
				++inalias;
			}
			rrp = rrp->next;
		}
		free_rr(rrlp);
		if(inalias)
			return tp;
		else
			return addlist(head, user, LOCAL);
	}

	while (fgets(buf,LINELEN,fp) != NULL) {
		p = buf;
		if ( *p == '#' || *p == '\0')
			continue;
		rip(p);

		/* if not in an matching entry skip continuation lines */
		if (!inalias && isspace(*p))
			continue;

		/* when processing an active alias check for a continuation */
		if (inalias) {
			if (!isspace(*p)) 
				break;	/* done */
		} else {
			s = p;
			SKIPWORD(p);
			*p++ = '\0';	/* end the alias name */
			if (strcmp(s,user) != 0)
				continue;	/* no match go on */
			inalias = 1;
		}

		/* process the recipients on the alias line */
		SKIPSPACE(p);
		while(*p != '\0' && *p != '#') {
			s = p;
			SKIPWORD(p);
			if (*p != '\0')
				*p++ = '\0';

			/* find hostname */
			if (strchr(s,'@') != NULL)
				tp = addlist(head,s,DOMAIN);
			else
				tp = addlist(head,s,LOCAL);
			SKIPSPACE(p);
		}
	}
	(void) fclose(fp);

	if (inalias)	/* found and processed and alias. */
		return tp;

	/* no alias found treat as a local address */
	return addlist(head, user, LOCAL);
}

static void
smtplog(char *fmt, ...)
{
	va_list ap;
	char *cp;
	long t;
	FILE *fp;

	if ((fp = fopen(Maillog,APPEND_TEXT)) == NULL)
		return;
	time(&t);
	cp = ctime(&t);
	rip(cp);
	fprintf(fp,"%s ",cp);
	va_start(ap,fmt);
	vfprintf(fp,fmt,ap);
	va_end(ap);
	fprintf(fp,"\n");
	fclose(fp);
}
/* send mail to a single user. Can be called from the ax24 mailbox or
** from the return mail function in the smtp client 
*/
static int
mailuser(data,from,to)
FILE *data;
char *from;
char *to;
{

		int address_type, ret;
		struct list *tolist = NULL;

		/* check if address is ok */
		if ((address_type = validate_address(to)) == BADADDR) {
			return 1;
		}
		/* if a local address check for an alias */
		if (address_type == LOCAL)
			expandalias(&tolist, to);
		else
			/* a remote address is added to the list */
			addlist(&tolist, to, address_type);
		ret = mailit(data,from,tolist);
		del_list(tolist);
		return ret;

}

/* Mailer daemon return mail mechanism */
int
mdaemon(data,to,lp,bounce)
FILE *data;		/* pointer to rewound data file */
char *to;		/* Overridden by Errors-To: line if bounce is true */
struct list *lp;	/* error log for failed mail */
int bounce;		/* True for failed mail, otherwise return receipt */
{
	time_t t;
	FILE *tfile;
	char buf[LINELEN], *cp, *newto = NULL;
	int cnt;
	if(to == NULL || (to != NULL && *to == '\0') || bounce){
		while(fgets(buf,sizeof(buf),data) != NULL) {
			if(buf[0] == '\n')
				break;
			/* Look for Errors-To: */
			if(htype(buf) == ERRORSTO &&
			   (cp = getaddress(buf,0)) != NULL){
				free(newto);
				newto = strdup(cp);
				break;
			}
		}
		if(newto == NULL && ((to != NULL && *to == '\0') ||
		   to == NULL))
			return -1;
		rewind(data);
	}
	if((tfile = tmpfile()) == NULL)
		return -1;
	time(&t);
	fprintf(tfile,"%s%s",Hdrs[DATE],ptime(&t));
	fprintf(tfile,"%s<%ld@%s>\n",Hdrs[MSGID],get_msgid(),Hostname);
	fprintf(tfile,"%sMAILER-DAEMON@%s (Mail Delivery Subsystem)\n",
		Hdrs[FROM],Hostname);
	fprintf(tfile,"%s%s\n",Hdrs[TO],newto != NULL ? newto : to);
	fprintf(tfile,"%s%s\n\n",Hdrs[SUBJECT],
		bounce ? "Failed mail" : "Return receipt");
	if(bounce) {
		fprintf(tfile,"  ===== transcript follows =====\n\n");
		for (; lp != NULL; lp = lp->next)
			fprintf(tfile,"%s\n",lp->val);
		fprintf(tfile,"\n");
	}
	fprintf(tfile,"  ===== %s follows ====\n",
		bounce ? "Unsent message" : "Message header");

	while(fgets(buf,sizeof(buf),data) != NULL){
		if(buf[0] == '\n')
			break;
		fputs(buf,tfile);
	}
	if(bounce){
		fputc('\n',tfile);
		while((cnt = fread(buf,1,sizeof(buf),data)) > 0)
			fwrite(buf,1,cnt,tfile);
	}
	fseek(tfile,0L,0);
	/* A null From<> so no looping replys to MAIL-DAEMONS */
	(void) mailuser(tfile,"",newto != NULL ? newto : to);
	fclose(tfile);
	free(newto);
	return 0;
}

⌨️ 快捷键说明

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