14796Seric # include <ctype.h>
24684Seric # include <sysexits.h>
34865Seric # include "sendmail.h"
44684Seric 
55182Seric # ifndef SMTP
6*7229Seric SCCSID(@(#)usersmtp.c	3.12		06/19/82	(no SMTP));
75182Seric # else SMTP
84684Seric 
9*7229Seric SCCSID(@(#)usersmtp.c	3.12		06/19/82);
105182Seric 
114684Seric /*
124865Seric **  SMTPINIT -- initialize SMTP.
134684Seric **
144865Seric **	Opens the connection and sends the initial protocol.
154684Seric **
164684Seric **	Parameters:
174865Seric **		m -- mailer to create connection to.
184865Seric **		pvp -- pointer to parameter vector to pass to
194865Seric **			the mailer.
204865Seric **		ctladdr -- controlling address for this mailer.
214684Seric **
224684Seric **	Returns:
234865Seric **		appropriate exit status -- EX_OK on success.
244684Seric **
254684Seric **	Side Effects:
264865Seric **		creates connection and sends initial protocol.
274684Seric */
284684Seric 
294865Seric # define REPLYTYPE(r)	((r) / 100)
304865Seric 
314865Seric static FILE	*SmtpOut;	/* output file */
324865Seric static FILE	*SmtpIn;	/* input file */
334865Seric static int	SmtpPid;	/* pid of mailer */
346051Seric static int	SmtpErrstat;	/* error status if open fails */
354865Seric 
364865Seric smtpinit(m, pvp, ctladdr)
374865Seric 	struct mailer *m;
384865Seric 	char **pvp;
394865Seric 	ADDRESS *ctladdr;
404684Seric {
414865Seric 	register int r;
424865Seric 	char buf[MAXNAME];
434684Seric 
444865Seric 	/*
454865Seric 	**  Open the connection to the mailer.
464865Seric 	*/
474684Seric 
486051Seric 	SmtpIn = SmtpOut = NULL;
494865Seric 	SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn);
506051Seric 	if (SmtpPid < 0)
516051Seric 	{
526051Seric 		SmtpErrstat = ExitStat;
536051Seric # ifdef DEBUG
546051Seric 		if (Debug > 0)
556051Seric 			printf("smtpinit: cannot open: Errstat %d errno %d\n",
566051Seric 			   SmtpErrstat, errno);
576051Seric # endif DEBUG
586051Seric 		return (ExitStat);
596051Seric 	}
604796Seric 
614865Seric 	/*
624865Seric 	**  Get the greeting message.
634865Seric 	**	This should appear spontaneously.
644865Seric 	*/
654797Seric 
664865Seric 	r = reply();
674865Seric 	if (REPLYTYPE(r) != 2)
684865Seric 		return (EX_TEMPFAIL);
694684Seric 
704865Seric 	/*
714976Seric 	**  Send the HELO command.
724976Seric 	**	My mother taught me to always introduce myself, even
734976Seric 	**	if it is useless.
744976Seric 	*/
754976Seric 
764976Seric 	smtpmessage("HELO %s", HostName);
774976Seric 	r = reply();
784976Seric 	if (REPLYTYPE(r) == 5)
794976Seric 		return (EX_UNAVAILABLE);
804976Seric 	if (REPLYTYPE(r) != 2)
814976Seric 		return (EX_TEMPFAIL);
824976Seric 
834976Seric 	/*
844865Seric 	**  Send the MAIL command.
854865Seric 	**	Designates the sender.
864865Seric 	*/
874796Seric 
886980Seric 	expand("$g", buf, &buf[sizeof buf - 1], CurEnv);
894865Seric 	smtpmessage("MAIL From:<%s>", buf);
904865Seric 	r = reply();
914865Seric 	if (REPLYTYPE(r) == 4)
924865Seric 		return (EX_TEMPFAIL);
934865Seric 	if (r != 250)
944865Seric 		return (EX_SOFTWARE);
954865Seric 	return (EX_OK);
964684Seric }
974684Seric /*
984976Seric **  SMTPRCPT -- designate recipient.
994797Seric **
1004797Seric **	Parameters:
1014865Seric **		to -- address of recipient.
1024797Seric **
1034797Seric **	Returns:
1044865Seric **		exit status corresponding to recipient status.
1054797Seric **
1064797Seric **	Side Effects:
1074865Seric **		Sends the mail via SMTP.
1084797Seric */
1094797Seric 
1104976Seric smtprcpt(to)
1114865Seric 	ADDRESS *to;
1124797Seric {
1134797Seric 	register int r;
1144797Seric 
1156051Seric 	if (SmtpPid < 0)
1166051Seric 		return (SmtpErrstat);
1176051Seric 
1184976Seric 	smtpmessage("RCPT To:<%s>", to->q_user);
1194865Seric 
1204797Seric 	r = reply();
1214865Seric 	if (REPLYTYPE(r) == 4)
1224865Seric 		return (EX_TEMPFAIL);
1234865Seric 	if (r != 250)
1244865Seric 		return (EX_NOUSER);
1254797Seric 
1264865Seric 	return (EX_OK);
1274797Seric }
1284797Seric /*
1294865Seric **  SMTPFINISH -- finish up sending all the SMTP protocol.
1304684Seric **
1314684Seric **	Parameters:
1324865Seric **		m -- mailer being sent to.
1336980Seric **		e -- the envelope for this message.
1344684Seric **
1354684Seric **	Returns:
1364976Seric **		exit status corresponding to DATA command.
1374684Seric **
1384684Seric **	Side Effects:
1394865Seric **		none.
1404684Seric */
1414684Seric 
1426980Seric smtpfinish(m, e)
1434865Seric 	struct mailer *m;
1446980Seric 	register ENVELOPE *e;
1454684Seric {
1464684Seric 	register int r;
1474684Seric 
1486051Seric 	if (SmtpPid < 0)
1496051Seric 		return (SmtpErrstat);
1506051Seric 
1514797Seric 	/*
1524797Seric 	**  Send the data.
1534797Seric 	**	Dot hiding is done here.
1544797Seric 	*/
1554797Seric 
1564865Seric 	smtpmessage("DATA");
1574796Seric 	r = reply();
1584797Seric 	if (REPLYTYPE(r) == 4)
1594797Seric 		return (EX_TEMPFAIL);
1604684Seric 	if (r != 354)
1614684Seric 		return (EX_SOFTWARE);
1626980Seric 	(*e->e_puthdr)(SmtpOut, m, CurEnv);
1636980Seric 	fprintf(SmtpOut, "\n");
1646980Seric 	(*e->e_putbody)(SmtpOut, m, TRUE);
1654865Seric 	smtpmessage(".");
1664796Seric 	r = reply();
1674797Seric 	if (REPLYTYPE(r) == 4)
1684797Seric 		return (EX_TEMPFAIL);
1694684Seric 	if (r != 250)
1704684Seric 		return (EX_SOFTWARE);
1714684Seric 	return (EX_OK);
1724684Seric }
1734684Seric /*
1744865Seric **  SMTPQUIT -- close the SMTP connection.
1754865Seric **
1764865Seric **	Parameters:
1774865Seric **		name -- name of mailer we are quitting.
178*7229Seric **		showresp -- if set, give a response message.
1794865Seric **
1804865Seric **	Returns:
1814865Seric **		none.
1824865Seric **
1834865Seric **	Side Effects:
1844865Seric **		sends the final protocol and closes the connection.
1854865Seric */
1864865Seric 
187*7229Seric smtpquit(name, showresp)
1884865Seric 	char *name;
189*7229Seric 	bool showresp;
1904865Seric {
1914865Seric 	register int i;
1924865Seric 
1936051Seric 	if (SmtpPid < 0)
194*7229Seric 		return;
195*7229Seric 	smtpmessage("QUIT");
196*7229Seric 	(void) reply();
197*7229Seric 	(void) fclose(SmtpIn);
198*7229Seric 	(void) fclose(SmtpOut);
199*7229Seric 	i = endmailer(SmtpPid, name);
200*7229Seric 	if (showresp)
201*7229Seric 		giveresponse(i, TRUE, LocalMailer);
2024865Seric }
2034865Seric /*
2044684Seric **  REPLY -- read arpanet reply
2054684Seric **
2064684Seric **	Parameters:
2074796Seric **		none.
2084684Seric **
2094684Seric **	Returns:
2104684Seric **		reply code it reads.
2114684Seric **
2124684Seric **	Side Effects:
2134684Seric **		flushes the mail file.
2144684Seric */
2154684Seric 
2164796Seric reply()
2174684Seric {
2184865Seric 	(void) fflush(SmtpOut);
2194684Seric 
2204796Seric 	if (Debug)
2214796Seric 		printf("reply\n");
2224796Seric 
2234684Seric 	/* read the input line */
2244684Seric 	for (;;)
2254684Seric 	{
2264684Seric 		char buf[MAXLINE];
2274684Seric 		register int r;
2284684Seric 
2294865Seric 		if (fgets(buf, sizeof buf, SmtpIn) == NULL)
2304684Seric 			return (-1);
231*7229Seric 		if (Verbose && !HoldErrs)
2324684Seric 			fputs(buf, stdout);
233*7229Seric 		fputs(buf, Xscript);
2344796Seric 		if (buf[3] == '-' || !isdigit(buf[0]))
2354684Seric 			continue;
2364684Seric 		r = atoi(buf);
2374684Seric 		if (r < 100)
2384684Seric 			continue;
2394684Seric 		return (r);
2404684Seric 	}
2414684Seric }
2424796Seric /*
2434865Seric **  SMTPMESSAGE -- send message to server
2444796Seric **
2454796Seric **	Parameters:
2464796Seric **		f -- format
2474796Seric **		a, b, c -- parameters
2484796Seric **
2494796Seric **	Returns:
2504796Seric **		none.
2514796Seric **
2524796Seric **	Side Effects:
2534865Seric **		writes message to SmtpOut.
2544796Seric */
2554796Seric 
2564865Seric /*VARARGS1*/
2574865Seric smtpmessage(f, a, b, c)
2584796Seric 	char *f;
2594796Seric {
2604796Seric 	char buf[100];
2614796Seric 
2624865Seric 	(void) sprintf(buf, f, a, b, c);
263*7229Seric 	if (Debug || (Verbose && !HoldErrs))
264*7229Seric 		printf(">>> %s\n", buf);
265*7229Seric 	fprintf(Xscript, ">>> %s\n", buf);
266*7229Seric 	fprintf(SmtpOut, "%s\r\n", buf);
2674796Seric }
2685182Seric 
2695182Seric # endif SMTP
270