14796Seric # include <ctype.h>
27356Seric # include <signal.h>
34684Seric # include <sysexits.h>
44865Seric # include "sendmail.h"
54684Seric 
65182Seric # ifndef SMTP
7*7685Seric SCCSID(@(#)usersmtp.c	3.16		08/08/82	(no SMTP));
85182Seric # else SMTP
94684Seric 
10*7685Seric SCCSID(@(#)usersmtp.c	3.16		08/08/82);
115182Seric 
124684Seric /*
134865Seric **  SMTPINIT -- initialize SMTP.
144684Seric **
154865Seric **	Opens the connection and sends the initial protocol.
164684Seric **
174684Seric **	Parameters:
184865Seric **		m -- mailer to create connection to.
194865Seric **		pvp -- pointer to parameter vector to pass to
204865Seric **			the mailer.
214865Seric **		ctladdr -- controlling address for this mailer.
224684Seric **
234684Seric **	Returns:
244865Seric **		appropriate exit status -- EX_OK on success.
254684Seric **
264684Seric **	Side Effects:
274865Seric **		creates connection and sends initial protocol.
284684Seric */
294684Seric 
304865Seric # define REPLYTYPE(r)	((r) / 100)
314865Seric 
324865Seric static FILE	*SmtpOut;	/* output file */
334865Seric static FILE	*SmtpIn;	/* input file */
344865Seric static int	SmtpPid;	/* pid of mailer */
356051Seric static int	SmtpErrstat;	/* error status if open fails */
364865Seric 
374865Seric smtpinit(m, pvp, ctladdr)
384865Seric 	struct mailer *m;
394865Seric 	char **pvp;
404865Seric 	ADDRESS *ctladdr;
414684Seric {
424865Seric 	register int r;
434865Seric 	char buf[MAXNAME];
447356Seric 	extern tick();
45*7685Seric 	extern char *canonname();
464684Seric 
474865Seric 	/*
484865Seric 	**  Open the connection to the mailer.
494865Seric 	*/
504684Seric 
516051Seric 	SmtpIn = SmtpOut = NULL;
524865Seric 	SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn);
536051Seric 	if (SmtpPid < 0)
546051Seric 	{
556051Seric 		SmtpErrstat = ExitStat;
566051Seric # ifdef DEBUG
577677Seric 		if (tTd(18, 1))
586051Seric 			printf("smtpinit: cannot open: Errstat %d errno %d\n",
596051Seric 			   SmtpErrstat, errno);
606051Seric # endif DEBUG
616051Seric 		return (ExitStat);
626051Seric 	}
637356Seric 	(void) signal(SIGALRM, tick);
644796Seric 
654865Seric 	/*
664865Seric 	**  Get the greeting message.
674865Seric 	**	This should appear spontaneously.
684865Seric 	*/
694797Seric 
704865Seric 	r = reply();
714865Seric 	if (REPLYTYPE(r) != 2)
724865Seric 		return (EX_TEMPFAIL);
734684Seric 
744865Seric 	/*
754976Seric 	**  Send the HELO command.
764976Seric 	**	My mother taught me to always introduce myself, even
774976Seric 	**	if it is useless.
784976Seric 	*/
794976Seric 
804976Seric 	smtpmessage("HELO %s", HostName);
814976Seric 	r = reply();
824976Seric 	if (REPLYTYPE(r) == 5)
834976Seric 		return (EX_UNAVAILABLE);
844976Seric 	if (REPLYTYPE(r) != 2)
854976Seric 		return (EX_TEMPFAIL);
864976Seric 
874976Seric 	/*
884865Seric 	**  Send the MAIL command.
894865Seric 	**	Designates the sender.
904865Seric 	*/
914796Seric 
926980Seric 	expand("$g", buf, &buf[sizeof buf - 1], CurEnv);
93*7685Seric 	smtpmessage("MAIL From: %s", canonname(buf));
944865Seric 	r = reply();
954865Seric 	if (REPLYTYPE(r) == 4)
964865Seric 		return (EX_TEMPFAIL);
974865Seric 	if (r != 250)
984865Seric 		return (EX_SOFTWARE);
994865Seric 	return (EX_OK);
1004684Seric }
1014684Seric /*
1024976Seric **  SMTPRCPT -- designate recipient.
1034797Seric **
1044797Seric **	Parameters:
1054865Seric **		to -- address of recipient.
1064797Seric **
1074797Seric **	Returns:
1084865Seric **		exit status corresponding to recipient status.
1094797Seric **
1104797Seric **	Side Effects:
1114865Seric **		Sends the mail via SMTP.
1124797Seric */
1134797Seric 
1144976Seric smtprcpt(to)
1154865Seric 	ADDRESS *to;
1164797Seric {
1174797Seric 	register int r;
118*7685Seric 	extern char *canonname();
1194797Seric 
1206051Seric 	if (SmtpPid < 0)
1216051Seric 		return (SmtpErrstat);
1226051Seric 
123*7685Seric 	smtpmessage("RCPT To: %s", canonname(to->q_user));
1244865Seric 
1254797Seric 	r = reply();
1264865Seric 	if (REPLYTYPE(r) == 4)
1274865Seric 		return (EX_TEMPFAIL);
1284865Seric 	if (r != 250)
1294865Seric 		return (EX_NOUSER);
1304797Seric 
1314865Seric 	return (EX_OK);
1324797Seric }
1334797Seric /*
1344865Seric **  SMTPFINISH -- finish up sending all the SMTP protocol.
1354684Seric **
1364684Seric **	Parameters:
1374865Seric **		m -- mailer being sent to.
1386980Seric **		e -- the envelope for this message.
1394684Seric **
1404684Seric **	Returns:
1414976Seric **		exit status corresponding to DATA command.
1424684Seric **
1434684Seric **	Side Effects:
1444865Seric **		none.
1454684Seric */
1464684Seric 
1476980Seric smtpfinish(m, e)
1484865Seric 	struct mailer *m;
1496980Seric 	register ENVELOPE *e;
1504684Seric {
1514684Seric 	register int r;
1524684Seric 
1536051Seric 	if (SmtpPid < 0)
1546051Seric 		return (SmtpErrstat);
1556051Seric 
1564797Seric 	/*
1574797Seric 	**  Send the data.
1584797Seric 	**	Dot hiding is done here.
1594797Seric 	*/
1604797Seric 
1614865Seric 	smtpmessage("DATA");
1624796Seric 	r = reply();
1634797Seric 	if (REPLYTYPE(r) == 4)
1644797Seric 		return (EX_TEMPFAIL);
1654684Seric 	if (r != 354)
1664684Seric 		return (EX_SOFTWARE);
1676980Seric 	(*e->e_puthdr)(SmtpOut, m, CurEnv);
1686980Seric 	fprintf(SmtpOut, "\n");
1696980Seric 	(*e->e_putbody)(SmtpOut, m, TRUE);
1704865Seric 	smtpmessage(".");
1714796Seric 	r = reply();
1724797Seric 	if (REPLYTYPE(r) == 4)
1734797Seric 		return (EX_TEMPFAIL);
1744684Seric 	if (r != 250)
1754684Seric 		return (EX_SOFTWARE);
1764684Seric 	return (EX_OK);
1774684Seric }
1784684Seric /*
1794865Seric **  SMTPQUIT -- close the SMTP connection.
1804865Seric **
1814865Seric **	Parameters:
1824865Seric **		name -- name of mailer we are quitting.
1837229Seric **		showresp -- if set, give a response message.
1844865Seric **
1854865Seric **	Returns:
1864865Seric **		none.
1874865Seric **
1884865Seric **	Side Effects:
1894865Seric **		sends the final protocol and closes the connection.
1904865Seric */
1914865Seric 
1927229Seric smtpquit(name, showresp)
1934865Seric 	char *name;
1947229Seric 	bool showresp;
1954865Seric {
1964865Seric 	register int i;
1974865Seric 
1986051Seric 	if (SmtpPid < 0)
1997229Seric 		return;
2007229Seric 	smtpmessage("QUIT");
2017229Seric 	(void) reply();
2027229Seric 	(void) fclose(SmtpIn);
2037229Seric 	(void) fclose(SmtpOut);
2047229Seric 	i = endmailer(SmtpPid, name);
2057229Seric 	if (showresp)
2067229Seric 		giveresponse(i, TRUE, LocalMailer);
2074865Seric }
2084865Seric /*
2094684Seric **  REPLY -- read arpanet reply
2104684Seric **
2114684Seric **	Parameters:
2124796Seric **		none.
2134684Seric **
2144684Seric **	Returns:
2154684Seric **		reply code it reads.
2164684Seric **
2174684Seric **	Side Effects:
2184684Seric **		flushes the mail file.
2194684Seric */
2204684Seric 
2214796Seric reply()
2224684Seric {
2234865Seric 	(void) fflush(SmtpOut);
2244684Seric 
2257677Seric 	if (tTd(18, 1))
2264796Seric 		printf("reply\n");
2274796Seric 
2287356Seric 	/*
2297356Seric 	**  Read the input line, being careful not to hang.
2307356Seric 	*/
2317356Seric 
2324684Seric 	for (;;)
2334684Seric 	{
2344684Seric 		char buf[MAXLINE];
2354684Seric 		register int r;
2367356Seric 		register char *p;
2374684Seric 
238*7685Seric 		/* actually do the read */
2397677Seric 		(void) fflush(Xscript);			/* for debugging */
240*7685Seric 		p = sfgets(buf, sizeof buf, SmtpIn);
2417356Seric 
2427356Seric 		if (p == NULL)
2437356Seric 			return (-1);
2447356Seric 
2457356Seric 		/* log the input in the transcript for future error returns */
2467229Seric 		if (Verbose && !HoldErrs)
2474684Seric 			fputs(buf, stdout);
2487229Seric 		fputs(buf, Xscript);
2497356Seric 
2507356Seric 		/* if continuation is required, we can go on */
2514796Seric 		if (buf[3] == '-' || !isdigit(buf[0]))
2524684Seric 			continue;
2537356Seric 
2547356Seric 		/* decode the reply code */
2554684Seric 		r = atoi(buf);
2567356Seric 
2577356Seric 		/* extra semantics: 0xx codes are "informational" */
2584684Seric 		if (r < 100)
2594684Seric 			continue;
2607356Seric 
2614684Seric 		return (r);
2624684Seric 	}
2634684Seric }
2644796Seric /*
2654865Seric **  SMTPMESSAGE -- send message to server
2664796Seric **
2674796Seric **	Parameters:
2684796Seric **		f -- format
2694796Seric **		a, b, c -- parameters
2704796Seric **
2714796Seric **	Returns:
2724796Seric **		none.
2734796Seric **
2744796Seric **	Side Effects:
2754865Seric **		writes message to SmtpOut.
2764796Seric */
2774796Seric 
2784865Seric /*VARARGS1*/
2794865Seric smtpmessage(f, a, b, c)
2804796Seric 	char *f;
2814796Seric {
2824796Seric 	char buf[100];
2834796Seric 
2844865Seric 	(void) sprintf(buf, f, a, b, c);
2857677Seric 	if (tTd(18, 1) || (Verbose && !HoldErrs))
2867229Seric 		printf(">>> %s\n", buf);
2877229Seric 	fprintf(Xscript, ">>> %s\n", buf);
2887229Seric 	fprintf(SmtpOut, "%s\r\n", buf);
2894796Seric }
2905182Seric 
2915182Seric # endif SMTP
292