14796Seric # include <ctype.h>
24684Seric # include <wellknown.h>
34684Seric # include <sysexits.h>
44684Seric # include <stdio.h>
54684Seric # include <useful.h>
64684Seric 
7*4797Seric static char	SccsId[] =	"@(#)usersmtp.c	3.3	11/08/81";
84684Seric 
94684Seric /*
104684Seric **  TCP -- TCP/Ethernet/ARPAnet mailer
114684Seric **
124684Seric **	This arranges to send a message over the TCP connection.
134684Seric */
144684Seric 
154684Seric # define MAXLINE	200
164684Seric 
174684Seric char	*MailCommand =	"/usr/lib/sendmail";
184684Seric char	*MailUser =	"network";
194796Seric char	*MailPassword =	"mailhack";
204796Seric FILE	*InConnection;
214796Seric FILE	*OutConnection;
224684Seric bool	Verbose;
234796Seric bool	Debug;
24*4797Seric int	Status;			/* exit status */
254684Seric 
264684Seric main(argc, argv)
274684Seric 	int argc;
284684Seric 	char **argv;
294684Seric {
304796Seric 	while (argc > 1 && argv[1][0] == '-')
314796Seric 	{
324796Seric 		register char *p = *++argv;
334796Seric 
344796Seric 		argc--;
354796Seric 		switch (p[1])
364796Seric 		{
374796Seric 		  case 'v':
384796Seric 			Verbose = TRUE;
394796Seric 			break;
404796Seric 
414796Seric 		  case 'd':
424796Seric 			Debug = TRUE;
434796Seric 			break;
444796Seric 		}
454796Seric 	}
464796Seric 
474684Seric 	if (argc < 4)
484796Seric 	{
494796Seric 		if (Debug)
504796Seric 			printf("Usage\n");
514684Seric 		exit(EX_USAGE);
524796Seric 	}
534684Seric 
544796Seric 	if (openconnection(argv[2]) < 0)
55*4797Seric 		exit(Status);
564684Seric 
57*4797Seric 	Status = runsmtp(argv[1], &argv[3]);
584684Seric 
59*4797Seric 	closeconnection();
60*4797Seric 
614796Seric 	if (Debug)
62*4797Seric 		printf("Finishing with stat %d\n", Status);
634796Seric 
64*4797Seric 	exit(Status);
654684Seric }
664684Seric /*
674684Seric **  OPENCONNECTION -- open connection to SMTP socket
684684Seric **
694684Seric **	Parameters:
70*4797Seric **		host -- the name of the host to connect to.  This
71*4797Seric **			will be replaced by the canonical name of
72*4797Seric **			the host.
734684Seric **
744684Seric **	Returns:
75*4797Seric **		File descriptor of connection.
76*4797Seric **		-1 on error.
774684Seric **
784684Seric **	Side Effects:
79*4797Seric **		sets 'Status' to represent the problem on error.
804684Seric */
814684Seric 
824684Seric openconnection(host)
834684Seric 	char *host;
844684Seric {
854684Seric 	char cmdbuf[100];
864796Seric 	register int fd;
874684Seric 
884684Seric 	/* create the command name */
894796Seric 	sprintf(cmdbuf, "%s -as%s%s", MailCommand,
904796Seric 					Verbose ? " -v" : "",
914796Seric 					Debug ? " -d" : "");
924684Seric 
934796Seric 	if (Debug)
944796Seric 		printf("Creating connection to \"%s\" on %s\n", cmdbuf, host);
954796Seric 
96*4797Seric 	/* verify host name */
97*4797Seric 	if (rhost(&host) < 0)
98*4797Seric 	{
99*4797Seric 		if (Debug)
100*4797Seric 			printf("Unknown host %s\n", host);
101*4797Seric 		Status = EX_NOHOST;
102*4797Seric 		return (-1);
103*4797Seric 	}
104*4797Seric 
1054684Seric 	/* create connection (we hope) */
1064796Seric 	fd = rexec(&host, SHELLSERVER, cmdbuf, MailUser, MailPassword);
1074796Seric 	if (fd < 0)
108*4797Seric 	{
109*4797Seric 		Status = EX_TEMPFAIL;
1104796Seric 		return (-1);
111*4797Seric 	}
1124796Seric 	InConnection = fdopen(fd, "r");
1134796Seric 	OutConnection = fdopen(fd, "w");
1144796Seric 	if (InConnection == NULL || OutConnection == NULL)
115*4797Seric 	{
116*4797Seric 		Status = EX_SOFTWARE;
1174796Seric 		return (-1);
118*4797Seric 	}
1194684Seric 
1204796Seric 	if (Debug)
1214796Seric 		printf("Connection open to %s\n", host);
1224796Seric 
1234796Seric 	return (0);
1244684Seric }
1254684Seric /*
126*4797Seric **	CLOSECONNECTION -- close the connection to the SMTP server.
127*4797Seric **
128*4797Seric **	This routine also sends a handshake.
129*4797Seric **
130*4797Seric **	Parameters:
131*4797Seric **		none.
132*4797Seric **
133*4797Seric **	Returns:
134*4797Seric **		none.
135*4797Seric **
136*4797Seric **	Side Effects:
137*4797Seric **		Closes the connection.
138*4797Seric */
139*4797Seric 
140*4797Seric closeconnection()
141*4797Seric {
142*4797Seric 	register int r;
143*4797Seric 
144*4797Seric 	message("QUIT");
145*4797Seric 	r = reply();
146*4797Seric 
147*4797Seric 	if (Debug)
148*4797Seric 		printf("Closing connection, reply = %d\n", r);
149*4797Seric }
150*4797Seric /*
1514684Seric **  RUNSMTP -- run the SMTP protocol over connection.
1524684Seric **
1534684Seric **	Parameters:
1544684Seric **		fr -- from person.
1554684Seric **		tolist -- list of recipients.
1564684Seric **
1574684Seric **	Returns:
1584684Seric **		none.
1594684Seric **
1604684Seric **	Side Effects:
1614684Seric **		Sends the mail via SMTP.
1624684Seric */
1634684Seric 
164*4797Seric # define REPLYTYPE(r)	((r) / 100)
165*4797Seric 
1664796Seric runsmtp(fr, tolist)
1674684Seric 	char *fr;
1684684Seric 	char **tolist;
1694684Seric {
1704684Seric 	register int r;
1714684Seric 	register char **t;
1724684Seric 	char buf[MAXLINE];
1734684Seric 
174*4797Seric 	/*
175*4797Seric 	**  Get the greeting message.
176*4797Seric 	**	This should appear spontaneously.
177*4797Seric 	*/
178*4797Seric 
1794796Seric 	r = reply();
180*4797Seric 	if (REPLYTYPE(r) != 2)
1814684Seric 		return (EX_TEMPFAIL);
1824684Seric 
183*4797Seric 	/*
184*4797Seric 	**  Send the MAIL command.
185*4797Seric 	**	Designates the sender.
186*4797Seric 	*/
187*4797Seric 
188*4797Seric 	message("MAIL From:<%s>", fr);
1894796Seric 	r = reply();
190*4797Seric 	if (REPLYTYPE(r) == 4)
191*4797Seric 		return (EX_TEMPFAIL);
1924684Seric 	if (r != 250)
1934684Seric 		return (EX_SOFTWARE);
1944684Seric 
195*4797Seric 	/*
196*4797Seric 	**  Send the recipients.
197*4797Seric 	*/
198*4797Seric 
1994684Seric 	for (t = tolist; *t != NULL; t++)
2004684Seric 	{
201*4797Seric 		message("MRCP To:<%s>", *t);
2024796Seric 		r = reply();
203*4797Seric 		if (REPLYTYPE(r) == 4)
204*4797Seric 			return (EX_TEMPFAIL);
2054684Seric 		if (r != 250)
2064684Seric 			return (EX_NOUSER);
2074684Seric 	}
2084684Seric 
209*4797Seric 	/*
210*4797Seric 	**  Send the data.
211*4797Seric 	**	Dot hiding is done here.
212*4797Seric 	*/
213*4797Seric 
214*4797Seric 	message("DATA");
2154796Seric 	r = reply();
216*4797Seric 	if (REPLYTYPE(r) == 4)
217*4797Seric 		return (EX_TEMPFAIL);
2184684Seric 	if (r != 354)
2194684Seric 		return (EX_SOFTWARE);
2204684Seric 	while (fgets(buf, sizeof buf, stdin) != NULL)
2214684Seric 	{
2224684Seric 		/* change trailing newline to crlf */
2234684Seric 		register char *p = index(buf, '\n');
2244684Seric 
2254684Seric 		if (p != NULL)
2264684Seric 			*p = '\0';
227*4797Seric 		message("%s%s", buf[0] == '.' ? "." : "", buf);
2284684Seric 	}
229*4797Seric 	message(".");
2304796Seric 	r = reply();
231*4797Seric 	if (REPLYTYPE(r) == 4)
232*4797Seric 		return (EX_TEMPFAIL);
2334684Seric 	if (r != 250)
2344684Seric 		return (EX_SOFTWARE);
2354684Seric 
236*4797Seric 	/*
237*4797Seric 	**  Make the actual delivery happen.
238*4797Seric 	*/
239*4797Seric 
240*4797Seric 	message("DOIT");
2414796Seric 	r = reply();
2424684Seric 	if (r != 250)
2434684Seric 		return (EX_TEMPFAIL);
2444684Seric 
2454684Seric 	return (EX_OK);
2464684Seric }
2474684Seric /*
2484684Seric **  REPLY -- read arpanet reply
2494684Seric **
2504684Seric **	Parameters:
2514796Seric **		none.
2524684Seric **
2534684Seric **	Returns:
2544684Seric **		reply code it reads.
2554684Seric **
2564684Seric **	Side Effects:
2574684Seric **		flushes the mail file.
2584684Seric */
2594684Seric 
2604796Seric reply()
2614684Seric {
2624796Seric 	fflush(OutConnection);
2634684Seric 
2644796Seric 	if (Debug)
2654796Seric 		printf("reply\n");
2664796Seric 
2674684Seric 	/* read the input line */
2684684Seric 	for (;;)
2694684Seric 	{
2704684Seric 		char buf[MAXLINE];
2714684Seric 		register int r;
2724684Seric 
2734796Seric 		if (fgets(buf, sizeof buf, InConnection) == NULL)
2744684Seric 			return (-1);
2754684Seric 		if (Verbose)
2764684Seric 			fputs(buf, stdout);
2774796Seric 		if (buf[3] == '-' || !isdigit(buf[0]))
2784684Seric 			continue;
2794684Seric 		r = atoi(buf);
2804684Seric 		if (r < 100)
2814684Seric 			continue;
2824684Seric 		return (r);
2834684Seric 	}
2844684Seric }
2854796Seric /*
2864796Seric **  MESSAGE -- send message to server
2874796Seric **
2884796Seric **	Parameters:
2894796Seric **		f -- format
2904796Seric **		a, b, c -- parameters
2914796Seric **
2924796Seric **	Returns:
2934796Seric **		none.
2944796Seric **
2954796Seric **	Side Effects:
2964796Seric **		writes message to OutChannel.
2974796Seric */
2984796Seric 
2994796Seric message(f, a, b, c)
3004796Seric 	char *f;
3014796Seric {
3024796Seric 	char buf[100];
3034796Seric 
3044796Seric 	sprintf(buf, f, a, b, c);
305*4797Seric 	strcat(buf, "\r\n");
3064796Seric 	if (Debug)
3074796Seric 		fputs(buf, stdout);
3084796Seric 	fputs(buf, OutConnection);
3094796Seric }
310