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

📄 smtpcli.c

📁 uCLinux下的一个TCP/IP协议栈源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Say HELO */
	sendcmd(cb,"HELO %s\n",Hostname);
	if(!Smtpbatch){
		rcode = getresp(cb,200);
		if(rcode == -1 || rcode >= 400)
			goto quit;
	}
	do {	/* For each message... */

		/* if this file open fails, skip it */
		if ((cb->tfile = fopen(cb->tname,READ_TEXT)) == NULL)
			continue;

		/* Send MAIL and RCPT commands */
		sendcmd(cb,"MAIL FROM:<%s>\n",cb->jobq->from);
		if(!Smtpbatch){
			rcode = getresp(cb,200);
			if(rcode == -1 || rcode >= 400)
				goto quit;
		}
		rcpts = 0;
		goodrcpt = 0;
		for (tp = cb->jobq->to; tp != NULL; tp = tp->next){
			sendcmd(cb,"RCPT TO:<%s>\n",tp->val);
			if(!Smtpbatch){
				rcode = getresp(cb,200);
				if(rcode == -1)
					goto quit;
				if(rcode < 400)
					goodrcpt = 1; /* At least one good */
			}
			rcpts++;
		}
		/* Send DATA command */
		sendcmd(cb,"DATA\n");
		if(!Smtpbatch){
			rcode = getresp(cb,200);
			if(rcode == -1 || rcode >= 400)
				goto quit;
		}
		if(Smtpbatch){
			/* Now wait for the responses to come back. The first time
			 * we do this, we wait first for the start banner and
			 * HELO response. In any case, we wait for the response to
			 * the MAIL command here.
			 */
			for(i= init ? 3 : 1;i > 0;i--){
				rcode = getresp(cb,200);
				if(rcode == -1 || rcode >= 400)
					goto quit;
			}
			init = 0;

			/* Now process the responses to the RCPT commands */
			for(i=rcpts;i!=0;i--){
				rcode = getresp(cb,200);
				if(rcode == -1)
					goto quit;
				if(rcode < 400)
					goodrcpt = 1; /* At least one good */
			}
			/* And finally get the response to the DATA command.
			 * Some servers will return failure here if no recipients
			 * are valid, some won't.
			 */
			rcode = getresp(cb,200);
			if(rcode == -1 || rcode >= 400)
				goto quit;

			/* check for no good rcpt on the list */
			if (goodrcpt == 0){
				sendcmd(cb,".\n");  /* Get out of data mode */
				goto quit;
			}
		}
		/* Send the file. This also closes it */
		smtpsendfile(cb);

		/* Wait for the OK response */
		rcode = getresp(cb,200);
		if(rcode == -1)
			goto quit;
		if((rcode >= 200 && rcode < 300) || rcode >= 500){
			/* if a good transfer or permanent failure remove job */

			if (cb->errlog != NULL)
				retmail(cb);
			/* Unlink the textfile */
			(void) unlink(cb->tname);
			(void) unlink(cb->wname);	/* unlink workfile */
			logmsg(s,"SMTP sent job %s To: %s From: %s",
			 cb->jobq->jobname,cb->jobq->to->val,cb->jobq->from);
		}
	} while(next_job(cb));
quit:
	sendcmd(cb,"QUIT\n");
	if (cb->errlog != NULL){
		retmail(cb);
		(void) unlink(cb->wname);	/* unlink workfile */
		(void) unlink(cb->tname);	/* unlink text */
	}
	(void) fclose(cb->network);
	if(cb->tfile != NULL)
		fclose(cb->tfile);
	cb->lock = 0;
	del_session(cb);
}


/* create mail lockfile */
int
mlock(dir,id)
char *dir,*id;
{
	char lockname[LINELEN];
	int fd;
	struct stat statbuf;

#ifdef	MSDOS
	if(strlen(id) > 8) {		/* truncate long filenames */
		id[8] = '\0';
		if(id[7] == '/')
			id[7] = '\0';
	}
#endif
	/* Try to create the lock file in an atomic operation */
	sprintf(lockname,"%s/%s.lck",dir,id);
#ifdef        AMIGA
	/* don't ask, really, just don't ask... I'd do file locking on
	 * an Amiga much more differently than this.
	 */
	if(access(lockname, 0) == 0)
		return -1;
#endif
	fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT,0600);
	if(fd != -1){
		/* Lock succeeded */
		close(fd);
		return 0;
	}
	/* See if the dir doesn't exist */
	if(stat(dir,&statbuf) == -1 || (statbuf.st_mode & S_IFMT) != S_IFDIR){
		printf("Lock directory %s missing\n",dir);
		fflush(stdout);
		return 0;
	}
	return -1;	/* lock failed */
}

/* remove mail lockfile */
int
rmlock(dir,id)
char *dir,*id;
{
	char lockname[LINELEN];
#ifdef	MSDOS
	if(strlen(id) > 8) {		/* truncate long filenames */
		id[8] = '\0';
		if(id[7] == '/')
			id[7] = '\0';
	}
#endif
	sprintf(lockname,"%s/%s.lck",dir,id);
	return(unlink(lockname));
}

/* free the message struct and data */
static void
del_session(cb)
register struct smtpcli *cb;
{
	register struct smtp_job *jp,*tp;
	register int i;

	if (cb == NULL)
		return;
	for(i=0; i<MAXSESSIONS; i++) 
		if(cli_session[i] == cb) {
			cli_session[i] = NULL;
			break;
		}

	free(cb->wname);
	free(cb->tname);
	free(cb->destname);
	for (jp = cb->jobq; jp != NULL;jp = tp) {
			tp = jp->next;
			del_job(jp);
	}
	del_list(cb->errlog);
	free(cb);
	Smtpsessions--;	/* number of connections active */
}

static void
del_job(jp)
register struct smtp_job *jp;
{
	if ( *jp->jobname != '\0')
		(void) rmlock(Mailqdir,jp->jobname);
	free(jp->from);
	del_list(jp->to);
	free(jp);
}

/* delete a list of list structs */
void
del_list(lp)
struct list *lp;
{
	register struct list *tp, *tp1;
	for (tp = lp; tp != NULL; tp = tp1) {
		tp1 = tp->next;
		free(tp->val);
		free(tp);
	}
}

/* stub for calling mdaemon to return message to sender */
static void
retmail(cb)
struct smtpcli *cb;
{
	FILE *infile;
#ifdef SMTPTRACE
	if (Smtptrace > 5) {
		printf("smtp job %s returned to sender\n",cb->wname);
	}
#endif
	if ((infile = fopen(cb->tname,READ_TEXT)) == NULL)
		return;
	mdaemon(infile,cb->jobq->from,cb->errlog,1);
	fclose(infile);
}

/* look to see if a smtp control block exists for this ipdest */
static struct smtpcli *
lookup(destaddr)
int32 destaddr;
{
	register int i;

	for(i=0; i<MAXSESSIONS; i++) {
		if (cli_session[i] == NULL)
			continue;
		if(cli_session[i]->ipdest == destaddr)
			return cli_session[i];
	}
	return NULL;
}

/* create a new  smtp control block */
static struct smtpcli *
newcb()
{
	register int i;
	register struct smtpcli *cb;

	for(i=0; i<MAXSESSIONS; i++) {
		if(cli_session[i] == NULL) {
			cb = (struct smtpcli *)callocw(1,sizeof(struct smtpcli));
			cb->wname = mallocw((unsigned)strlen(Mailqdir)+JOBNAME);
			cb->tname = mallocw((unsigned)strlen(Mailqdir)+JOBNAME);
			cli_session[i] = cb;
			Smtpsessions++;	/* number of connections active */
			return(cb);
		}
	}
	return NULL;
}

static void
execjobs()
{
	register struct smtpcli *cb;
	register int i;

	for(i=0; i<MAXSESSIONS; i++) {
		cb = cli_session[i];
		if (cb == NULL) 
			continue;
		if(cb->lock)
			continue;

		sprintf(cb->tname,"%s/%s.txt",Mailqdir,cb->jobq->jobname);
		sprintf(cb->wname,"%s/%s.wrk",Mailqdir,cb->jobq->jobname);

		newproc("smtp_send", 1024, smtp_send, 0, cb,NULL,0);

#ifdef SMTPTRACE
		if (Smtptrace) 
			printf("Trying Connection to %s\n",inet_ntoa(cb->ipdest));
#endif


	}
}
	
/* add this job to control block queue */
static struct smtp_job *
setupjob(cb,id,from)
struct smtpcli *cb;
char *id,*from;
{
	register struct smtp_job *p1,*p2;

	p1 = (struct smtp_job *)callocw(1,sizeof(struct smtp_job));
	p1->from = strdup(from);
	strcpy(p1->jobname,id);
	/* now add to end of jobq */
	if ((p2 = cb->jobq) == NULL)
		cb->jobq = p1;
	else {
		while(p2->next != NULL)
			p2 = p2->next;
		p2->next = p1;
	}
	return p1;
}

/* called to advance to the next job */
static int
next_job(cb)
register struct smtpcli *cb;
{
	register struct smtp_job *jp;

	jp = cb->jobq->next;
	del_job(cb->jobq);
	/* remove the error log of previous message */
	del_list(cb->errlog);
	cb->errlog = NULL;
	cb->jobq = jp;
	if (jp == NULL)
		return 0;
	sprintf(cb->tname,"%s/%s.txt",Mailqdir,jp->jobname);
	sprintf(cb->wname,"%s/%s.wrk",Mailqdir,jp->jobname);
#ifdef SMTPTRACE
	if (Smtptrace > 5) {
		printf("sending job %s\n",jp->jobname);
	}
#endif
		return 1;

}


/* Mail routing function. For now just use the hosts file */
int32
mailroute(dest)
char *dest;
{
	int32 destaddr;

	/* look up address or use the gateway */
	destaddr = resolve_mx(dest);
	if (destaddr == 0 && (destaddr = resolve(dest)) == 0)
		if (Gateway != 0) 
			destaddr = Gateway; /* Use the gateway  */
	return destaddr;
	
}

/* save line in error list */
static void
logerr(cb,line)
struct smtpcli *cb;
char *line;
{
	register struct list *lp,*tp;
	tp = (struct list *)callocw(1,sizeof(struct list));
	tp->val = strdup(line);
	/* find end of list */
	if ((lp = cb->errlog) == NULL)
		cb->errlog = tp;
	else {
		while(lp->next != NULL)
			lp = lp->next;
		lp->next = tp;
	}
}

static int
smtpsendfile(cb)
register struct smtpcli *cb;
{
	int error = 0;

	strcpy(cb->buf,"\n");
	while(fgets(cb->buf,sizeof(cb->buf),cb->tfile) != NULL) {
		/* Escape a single '.' character at the beginning of a line */
		if(strcmp(cb->buf,".\n") == 0)
			putc('.',cb->network);
		fputs(cb->buf,cb->network);
	}
	fclose(cb->tfile);
	cb->tfile = NULL;
	/* Send the end-of-message command */
	if(cb->buf[strlen(cb->buf)-1] == '\n')
		sendcmd(cb,".\n");
	else
		sendcmd(cb,"\n.\n");
	return error;
}
/* do a printf() on the network stream with optional local tracing */
static void
sendcmd(struct smtpcli *cb,char *fmt, ...)
{
	va_list args;

	va_start(args,fmt);
#ifdef	SMTPTRACE
	if(Smtptrace){
		printf("smtp sent: ");
		vprintf(fmt,args);
	}
#endif
	vsprintf(cb->buf,fmt,args);
	fputs(cb->buf,cb->network);
	va_end(args);
}

/* Wait for, read and display response from server. Return the result code. */
static int
getresp(cb,mincode)
struct smtpcli *cb;
int mincode;	/* Keep reading until at least this code comes back */
{
	int rval;
	char line[LINELEN];

	fflush(cb->network);
	for(;;){
		/* Get line */
		if(fgets(line,LINELEN,cb->network) == NULL){
			rval = -1;
			break;
		}
		rip(line);		/* Remove cr/lf */
		rval = atoi(line);
#ifdef	SMTPTRACE
		if(Smtptrace)
			printf("smtp recv: %s\n",line);/* Display to user */
#endif
		if(rval >= 500) {	/* Save permanent error replies */
			char tmp[LINELEN];
			if(cb->errlog == NULL) {
				sprintf(tmp,"While talking to %s:",
					cb->destname);
				logerr(cb,tmp);
			}
			if(cb->buf[0] != '\0') { /* Save offending command */
				rip(cb->buf);
				sprintf(tmp,">>> %s",cb->buf);
				logerr(cb,tmp);
				cb->buf[0] = '\0';
			}
			sprintf(tmp,"<<< %s",line);
			logerr(cb,tmp);		/* save the error reply */
		}
		/* Messages with dashes are continued */
		if(line[3] != '-' && rval >= mincode)
			break;
	}
	return rval;
}

⌨️ 快捷键说明

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