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

📄 smtpcli.c

📁 在51单片机上实现TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:

#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <setjmp.h>
#ifdef UNIX
#include <sys/types.h>
#endif
#ifdef	AMIGA
#include <stat.h>
#else
#include <sys/stat.h>
#endif
#ifdef	__TURBOC__
#include <dir.h>
#include <io.h>
#endif
#include "global.h"
#include <stdarg.h>
#include "mbuf.h"
#include "cmdparse.h"
#include "proc.h"
#include "socket.h"
#include "timer.h"
#include "netuser.h"
#include "smtp.h"
#include "dirutil.h"
#include "commands.h"
#include "session.h"

static struct timer Smtpcli_t;
static int32 Gateway;

#ifdef SMTPTRACE
static unsigned short Smtptrace = 0;		/* used for trace level */
static int dosmtptrace(int argc,char *argv[],void *p);
#endif

static unsigned  short Smtpmaxcli  = MAXSESSIONS;	/* the max client connections allowed */
static int Smtpsessions = 0;		/* number of client connections
					* currently open */
static int Smtpbatch;
int	Smtpmode = 0;

static struct smtpcli *cli_session[MAXSESSIONS]; /* queue of client sessions  */

static void del_job(struct smtp_job *jp);
static void del_session(struct smtpcli *cb);
static int dogateway(int argc,char *argv[],void *p);
static int dosmtpmaxcli(int argc,char *argv[],void *p);
static int dotimer(int argc,char *argv[],void *p);
static int dosmtpkill(int argc,char *argv[],void *p);
static int dosmtplist(int argc,char *argv[],void *p);
static int dobatch(int argc,char *argv[],void *p);
static void execjobs(void);
static int getresp(struct smtpcli *ftp,int mincode);
static void logerr(struct smtpcli *cb,char *line);
static struct smtpcli *lookup(int32 destaddr);
static struct smtpcli *newcb(void);
static int next_job(struct smtpcli *cb);
static void retmail(struct smtpcli *cb);
static void sendcmd(struct smtpcli *cb,char *fmt,...);
static int smtpsendfile(struct smtpcli *cb);
static int setsmtpmode(int argc,char *argv[],void *p);
static struct smtp_job *setupjob(struct smtpcli *cb,char *id,char *from);
static void smtp_send(int unused,void *cb1,void *p);
static int smtpkick(int argc,char *argv[],void *p);

static struct cmds Smtpcmds[] = {
	"batch",	dobatch,	0,	0,	NULL,
	"gateway",	dogateway,	0,	0,	NULL,
	"mode",		setsmtpmode,	0,	0,	NULL,
	"kick",		smtpkick,	0,	0,	NULL,
	"kill",		dosmtpkill,	0,	2,	"kill <jobnumber>",
	"list",		dosmtplist,	0,	0,	NULL,
	"maxclients",	dosmtpmaxcli,	0,	0,	NULL,
	"timer",	dotimer,	0,	0,	NULL,
#ifdef SMTPTRACE
	"trace",	dosmtptrace,	0,	0,	NULL,
#endif
	NULL,
};

int
dosmtp(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return subcmd(Smtpcmds,argc,argv,p);
}

static int
dobatch(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&Smtpbatch,"SMTP batching",argc,argv);
}
static int
dosmtpmaxcli(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setshort(&Smtpmaxcli,"Max clients",argc,argv);
}

static int
setsmtpmode(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if (argc < 2) {
		printf("smtp mode: %s\n",
			(Smtpmode & QUEUE) ? "queue" : "route");
	} else {
		switch(*argv[1]) {
		case 'q':
			Smtpmode |= QUEUE;
			break;
		case 'r':
			Smtpmode &= ~QUEUE;
			break;
		default:
			printf("Usage: smtp mode [queue | route]\n");
			break;
		}
	}
	return 0;
}
static int
dogateway(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	int32 n;

	if(argc < 2){
		printf("%s\n",inet_ntoa(Gateway));
	} else if((n = resolve(argv[1])) == 0){
		printf(Badhost,argv[1]);
		return 1;
	} else
		Gateway = n;
	return 0;
}

#ifdef SMTPTRACE
static int
dosmtptrace(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setshort(&Smtptrace,"SMTP tracing",argc,argv);
}
#endif

/* list jobs wating to be sent in the mqueue */
static int
dosmtplist(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	char tstring[80];
	char line[20];
	char host[LINELEN];
	char to[LINELEN];
	char from[LINELEN];
	char *cp;
	char	status;
	struct stat stbuf;
	struct tm *tminfo, *localtime();
	FILE *fp;

	printf("S     Job    Size Date  Time  Host                 From\n");
	filedir(Mailqueue,0,line);
	while(line[0] != '\0') {
		sprintf(tstring,"%s/%s",Mailqdir,line);
		if ((fp = fopen(tstring,READ_TEXT)) == NULL) {
			printf("Can't open %s: %s\n",tstring,sys_errlist[errno]);
			continue;
		}
		if ((cp = strrchr(line,'.')) != NULL)
			*cp = '\0';
		sprintf(tstring,"%s/%s.lck",Mailqdir,line);
		if (access(tstring,0))
			status = ' ';
		else
			status = 'L';
		sprintf(tstring,"%s/%s.txt",Mailqdir,line);
		stat(tstring,&stbuf);
		tminfo = localtime(&stbuf.st_ctime);
		fgets(host,sizeof(host),fp);
		rip(host);
		fgets(from,sizeof(from),fp);
		rip(from);
		printf("%c %7s %7ld %02d/%02d %02d:%02d %-20s %s\n      ",
			status, line, stbuf.st_size,
			tminfo->tm_mon+1,
			tminfo->tm_mday,
			tminfo->tm_hour,
			tminfo->tm_min,
			host,from);
		while (fgets(to,sizeof(to),fp) != NULL) {
			rip(to);
			printf("%s ",to);
		}
		printf("\n");
		(void) fclose(fp);
		kwait(NULL);
		filedir(Mailqueue,1,line);
	}
	return 0;
}

/* kill a job in the mqueue */
static int
dosmtpkill(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	char s[SLINELEN];
	char *cp,c;
	sprintf(s,"%s/%s.lck",Mailqdir,argv[1]);
	cp = strrchr(s,'.');
	if (!access(s,0)) {
		Current->ttystate.echo = Current->ttystate.edit = 0;
		c = keywait("Warning, the job is locked by SMTP. Remove (y/n)? ",0);
		Current->ttystate.echo = Current->ttystate.edit = 1;
		if (c != 'y')
			return 0;
		(void) unlink(s);
	}
	strcpy(cp,".wrk");
	if (unlink(s))
		printf("Job id %s not found\n",argv[1]);
	strcpy(cp,".txt");
	(void) unlink(s);
	return 0;
}

/* Set outbound spool scan interval */
static int
dotimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if(argc < 2){
		printf("%lu/%lu\n",
		read_timer(&Smtpcli_t) /1000L,
		dur_timer(&Smtpcli_t)/ 1000L);
		return 0;
	}
	Smtpcli_t.func = (void (*)())smtptick;/* what to call on timeout */
	Smtpcli_t.arg = NULL;		/* dummy value */
	set_timer(&Smtpcli_t,atol(argv[1])*1000L);	/* set timer duration */
	start_timer(&Smtpcli_t);		/* and fire it up */
	return 0;
}

static int
smtpkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	int32 addr = 0;
	if(argc > 1 && (addr = resolve(argv[1])) == 0){
		printf(Badhost,argv[1]);
		return 1;
	}
	smtptick(addr);
	return 0;
}

/* This is the routine that gets called every so often to do outgoing
 * mail processing. When called with a null argument, it runs the entire
 * queue; if called with a specific non-zero IP address from the remote
 * kick server, it only starts up sessions to that address.
 */
int
smtptick(target)
int32 target;
{
	register struct smtpcli *cb;
	struct smtp_job *jp;
	struct list *ap;
	char	tmpstring[LINELEN], wfilename[13], prefix[9];
	char	from[LINELEN], to[LINELEN];
	char *cp, *cp1;
	int32 destaddr;
	FILE *wfile;

#ifdef SMTPTRACE
	if (Smtptrace > 5)
		printf("smtp daemon entered, target = %s\n",inet_ntoa(target));
#endif
	if(availmem() != 0){
		/* Memory is tight, don't do anything */
		/* Restart timer */
		start_timer(&Smtpcli_t);
		return 0;
	}
	for(filedir(Mailqueue,0,wfilename);wfilename[0] != '\0';
		filedir(Mailqueue,1,wfilename)){

		/* save the prefix of the file name which it job id */
		cp = wfilename;
		cp1 = prefix;
		while (*cp && *cp != '.')
			*cp1++ = *cp++;
		*cp1 = '\0';

		/* lock this file from the smtp daemon */
		if (mlock(Mailqdir,prefix))
			continue;

		sprintf(tmpstring,"%s/%s",Mailqdir,wfilename);
		if ((wfile = fopen(tmpstring,READ_TEXT)) == NULL) {
			/* probably too many open files */
			(void) rmlock(Mailqdir,prefix);
			/* continue to next message. The failure
			* may be temporary */
			continue;
		}

		(void) fgets(tmpstring,LINELEN,wfile);	/* read target host */
		rip(tmpstring);

		if ((destaddr = mailroute(tmpstring)) == 0) {
			fclose(wfile);
			printf("** smtp: Unknown address %s\n",tmpstring);
			(void) rmlock(Mailqdir,prefix);
			continue;
		}
		if(target != 0 && destaddr != target){
			fclose(wfile);
			(void) rmlock(Mailqdir,prefix);
			continue;	/* Not the proper target of a kick */
		}
		if ((cb = lookup(destaddr)) == NULL) {
			/* there are enough processes running already */
			if (Smtpsessions >= Smtpmaxcli) {
#ifdef SMTPTRACE
				if (Smtptrace) {
					printf("smtp daemon: too many processes\n");
				}
#endif
				fclose(wfile);
				(void) rmlock(Mailqdir,prefix);
				break;
			}
			if ((cb = newcb()) == NULL) {
				fclose(wfile);
				(void) rmlock(Mailqdir,prefix);
				break;
			} 
			cb->ipdest = destaddr;
			cb->destname = strdup(tmpstring);
		} else {
			if(cb->lock){
				/* This system is already is sending mail lets not
				* interfere with its send queue.
				*/
				fclose(wfile);
				(void) rmlock(Mailqdir,prefix);
				continue;
			}
		}

		(void) fgets(from,LINELEN,wfile);	/* read from */
		rip(from);
		if ((jp = setupjob(cb,prefix,from)) == NULL) {
			fclose(wfile);
			(void) rmlock(Mailqdir,prefix);
			del_session(cb);
			break;
		}
		while (fgets(to,LINELEN,wfile) != NULL) {
			rip(to);
			if (addlist(&jp->to,to,DOMAIN) == NULL) {
				fclose(wfile);
				del_session(cb);
			}
		}
		fclose(wfile);
#ifdef SMTPTRACE
		if (Smtptrace > 1) {
			printf("queue job %s From: %s To:",prefix,from);
			for (ap = jp->to; ap != NULL; ap = ap->next)
				printf(" %s",ap->val);
			printf("\n");
		}
#endif
	}

	/* start sending that mail */
	execjobs();

	/* Restart timer */
	start_timer(&Smtpcli_t);
	return 0;
}

/* This is the master state machine that handles a single SMTP transaction.
 * It is called with a queue of jobs for a particular host.
 * The logic is complicated by the "Smtpbatch" variable, which controls
 * the batching of SMTP commands. If Smtpbatch is true, then many of the
 * SMTP commands are sent in one swell foop before waiting for any of
 * the responses. Unfortunately, this breaks many brain-damaged SMTP servers
 * out there, so provisions have to be made to operate SMTP in lock-step mode.
 */
static void
smtp_send(unused,cb1,p)
int unused;
void *cb1;
void *p;
{
	register struct smtpcli *cb;
	register struct list *tp;
	struct sockaddr_in fsocket;
	char *cp;
	int rcode;
	int rcpts;
	int goodrcpt;
	int i,s;
	int init = 1;

	cb = (struct smtpcli *)cb1;
	cb->lock = 1;
	fsocket.sin_family = AF_INET;
	fsocket.sin_addr.s_addr = cb->ipdest;
	fsocket.sin_port = IPPORT_SMTP;

	s = socket(AF_INET,SOCK_STREAM,0);
#ifdef SMTPTRACE
	if (Smtptrace) 
		printf("SMTP client Trying...\n");
#endif
	if(connect(s,(struct sockaddr *)&fsocket,SOCKSIZE) == 0){
		cb->network = fdopen(s,"r+t");
#ifdef SMTPTRACE
		if (Smtptrace) 
			printf("Connected\n");
#endif
	} else {
		cp = sockerr(s);
#ifdef SMTPTRACE
		if (Smtptrace) 
			printf("Connect failed: %s\n",cp != NULL ? cp : "");
#endif
		logmsg(s,"SMTP %s Connect failed: %s",psocket(&fsocket),
		    cp != NULL ? cp : "");
	}
	if(!Smtpbatch){
		rcode = getresp(cb,200);
		if(rcode == -1 || rcode >= 400)
			goto quit;
	}

⌨️ 快捷键说明

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