14796Seric # include <ctype.h>
24684Seric # include <sysexits.h>
34865Seric # include "sendmail.h"
44684Seric 
55182Seric # ifndef SMTP
6*8237Seric SCCSID(@(#)usersmtp.c	3.23		09/21/82	(no SMTP));
75182Seric # else SMTP
84684Seric 
9*8237Seric SCCSID(@(#)usersmtp.c	3.23		09/21/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)
307963Seric # define REPLYCLASS(r)	(((r) / 10) % 10)
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();
457685Seric 	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 	}
634796Seric 
644865Seric 	/*
654865Seric 	**  Get the greeting message.
664865Seric 	**	This should appear spontaneously.
674865Seric 	*/
684797Seric 
694865Seric 	r = reply();
708005Seric 	if (r < 0 || REPLYTYPE(r) != 2)
714865Seric 		return (EX_TEMPFAIL);
724684Seric 
734865Seric 	/*
744976Seric 	**  Send the HELO command.
757963Seric 	**	My mother taught me to always introduce myself.
764976Seric 	*/
774976Seric 
784976Seric 	smtpmessage("HELO %s", HostName);
794976Seric 	r = reply();
808005Seric 	if (r < 0)
818005Seric 		return (EX_TEMPFAIL);
828005Seric 	else if (REPLYTYPE(r) == 5)
834976Seric 		return (EX_UNAVAILABLE);
847963Seric 	else 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);
938084Seric 	smtpmessage("MAIL From:<%s>", canonname(buf));
944865Seric 	r = reply();
958005Seric 	if (r < 0 || REPLYTYPE(r) == 4)
964865Seric 		return (EX_TEMPFAIL);
977963Seric 	else if (r == 250)
987963Seric 		return (EX_OK);
997963Seric 	else if (r == 552)
1007963Seric 		return (EX_UNAVAILABLE);
1017964Seric 	return (EX_PROTOCOL);
1024684Seric }
1034684Seric /*
1044976Seric **  SMTPRCPT -- designate recipient.
1054797Seric **
1064797Seric **	Parameters:
1074865Seric **		to -- address of recipient.
1084797Seric **
1094797Seric **	Returns:
1104865Seric **		exit status corresponding to recipient status.
1114797Seric **
1124797Seric **	Side Effects:
1134865Seric **		Sends the mail via SMTP.
1144797Seric */
1154797Seric 
1164976Seric smtprcpt(to)
1174865Seric 	ADDRESS *to;
1184797Seric {
1194797Seric 	register int r;
1207685Seric 	extern char *canonname();
1214797Seric 
1226051Seric 	if (SmtpPid < 0)
1236051Seric 		return (SmtpErrstat);
1246051Seric 
1258084Seric 	smtpmessage("RCPT To:<%s>", canonname(to->q_user));
1264865Seric 
1274797Seric 	r = reply();
1288005Seric 	if (r < 0 || REPLYTYPE(r) == 4)
1294865Seric 		return (EX_TEMPFAIL);
1307963Seric 	else if (REPLYTYPE(r) == 2)
1317963Seric 		return (EX_OK);
1327964Seric 	else if (r == 550 || r == 551 || r == 553)
1337964Seric 		return (EX_NOUSER);
1347964Seric 	else if (r == 552 || r == 554)
1357964Seric 		return (EX_UNAVAILABLE);
1367964Seric 	return (EX_PROTOCOL);
1374797Seric }
1384797Seric /*
1394865Seric **  SMTPFINISH -- finish up sending all the SMTP protocol.
1404684Seric **
1414684Seric **	Parameters:
1424865Seric **		m -- mailer being sent to.
1436980Seric **		e -- the envelope for this message.
1444684Seric **
1454684Seric **	Returns:
1464976Seric **		exit status corresponding to DATA command.
1474684Seric **
1484684Seric **	Side Effects:
1494865Seric **		none.
1504684Seric */
1514684Seric 
1526980Seric smtpfinish(m, e)
1534865Seric 	struct mailer *m;
1546980Seric 	register ENVELOPE *e;
1554684Seric {
1564684Seric 	register int r;
1574684Seric 
1586051Seric 	if (SmtpPid < 0)
1596051Seric 		return (SmtpErrstat);
1606051Seric 
1614797Seric 	/*
1624797Seric 	**  Send the data.
1634797Seric 	**	Dot hiding is done here.
1644797Seric 	*/
1654797Seric 
1664865Seric 	smtpmessage("DATA");
1674796Seric 	r = reply();
1688005Seric 	if (r < 0 || REPLYTYPE(r) == 4)
1694797Seric 		return (EX_TEMPFAIL);
1707963Seric 	else if (r == 554)
1717963Seric 		return (EX_UNAVAILABLE);
1727963Seric 	else if (r != 354)
1737964Seric 		return (EX_PROTOCOL);
1746980Seric 	(*e->e_puthdr)(SmtpOut, m, CurEnv);
1756980Seric 	fprintf(SmtpOut, "\n");
1766980Seric 	(*e->e_putbody)(SmtpOut, m, TRUE);
1774865Seric 	smtpmessage(".");
1784796Seric 	r = reply();
1798005Seric 	if (r < 0 || REPLYTYPE(r) == 4)
1804797Seric 		return (EX_TEMPFAIL);
1817963Seric 	else if (r == 250)
1827963Seric 		return (EX_OK);
1837963Seric 	else if (r == 552 || r == 554)
1847963Seric 		return (EX_UNAVAILABLE);
1857964Seric 	return (EX_PROTOCOL);
1864684Seric }
1874684Seric /*
1884865Seric **  SMTPQUIT -- close the SMTP connection.
1894865Seric **
1904865Seric **	Parameters:
1914865Seric **		name -- name of mailer we are quitting.
1927229Seric **		showresp -- if set, give a response message.
1934865Seric **
1944865Seric **	Returns:
1954865Seric **		none.
1964865Seric **
1974865Seric **	Side Effects:
1984865Seric **		sends the final protocol and closes the connection.
1994865Seric */
2004865Seric 
2017229Seric smtpquit(name, showresp)
2024865Seric 	char *name;
2037229Seric 	bool showresp;
2044865Seric {
2054865Seric 	register int i;
2064865Seric 
2076051Seric 	if (SmtpPid < 0)
2087229Seric 		return;
2097229Seric 	smtpmessage("QUIT");
2107229Seric 	(void) reply();
2117229Seric 	(void) fclose(SmtpIn);
2127229Seric 	(void) fclose(SmtpOut);
2137229Seric 	i = endmailer(SmtpPid, name);
2147229Seric 	if (showresp)
2157229Seric 		giveresponse(i, TRUE, LocalMailer);
2164865Seric }
2174865Seric /*
2184684Seric **  REPLY -- read arpanet reply
2194684Seric **
2204684Seric **	Parameters:
2214796Seric **		none.
2224684Seric **
2234684Seric **	Returns:
2244684Seric **		reply code it reads.
2254684Seric **
2264684Seric **	Side Effects:
2274684Seric **		flushes the mail file.
2284684Seric */
2294684Seric 
2304796Seric reply()
2314684Seric {
2324865Seric 	(void) fflush(SmtpOut);
2334684Seric 
2347677Seric 	if (tTd(18, 1))
2354796Seric 		printf("reply\n");
2364796Seric 
2377356Seric 	/*
2387356Seric 	**  Read the input line, being careful not to hang.
2397356Seric 	*/
2407356Seric 
2414684Seric 	for (;;)
2424684Seric 	{
2434684Seric 		char buf[MAXLINE];
2444684Seric 		register int r;
2457356Seric 		register char *p;
2464684Seric 
2477685Seric 		/* actually do the read */
2487677Seric 		(void) fflush(Xscript);			/* for debugging */
2497685Seric 		p = sfgets(buf, sizeof buf, SmtpIn);
2507356Seric 		if (p == NULL)
2517356Seric 			return (-1);
252*8237Seric 		fixcrlf(buf, TRUE);
2537356Seric 
2547356Seric 		/* log the input in the transcript for future error returns */
2557229Seric 		if (Verbose && !HoldErrs)
256*8237Seric 			nmessage(Arpa_Info, "%s", buf);
257*8237Seric 		fprintf(Xscript, "%s\n", buf);
2587356Seric 
2597356Seric 		/* if continuation is required, we can go on */
2604796Seric 		if (buf[3] == '-' || !isdigit(buf[0]))
2614684Seric 			continue;
2627356Seric 
2637356Seric 		/* decode the reply code */
2644684Seric 		r = atoi(buf);
2657356Seric 
2667356Seric 		/* extra semantics: 0xx codes are "informational" */
2674684Seric 		if (r < 100)
2684684Seric 			continue;
2697356Seric 
2704684Seric 		return (r);
2714684Seric 	}
2724684Seric }
2734796Seric /*
2744865Seric **  SMTPMESSAGE -- send message to server
2754796Seric **
2764796Seric **	Parameters:
2774796Seric **		f -- format
2784796Seric **		a, b, c -- parameters
2794796Seric **
2804796Seric **	Returns:
2814796Seric **		none.
2824796Seric **
2834796Seric **	Side Effects:
2844865Seric **		writes message to SmtpOut.
2854796Seric */
2864796Seric 
2874865Seric /*VARARGS1*/
2884865Seric smtpmessage(f, a, b, c)
2894796Seric 	char *f;
2904796Seric {
2914796Seric 	char buf[100];
2924796Seric 
2934865Seric 	(void) sprintf(buf, f, a, b, c);
2947677Seric 	if (tTd(18, 1) || (Verbose && !HoldErrs))
295*8237Seric 		nmessage(Arpa_Info, ">>> %s", buf);
296*8237Seric 	fprintf(Xscript, " >>> %s\n", buf);
2977229Seric 	fprintf(SmtpOut, "%s\r\n", buf);
2984796Seric }
2995182Seric 
3005182Seric # endif SMTP
301