1 # include <ctype.h>
2 # include <sysexits.h>
3 # include "sendmail.h"
4 
5 # ifndef SMTP
6 SCCSID(@(#)usersmtp.c	3.18		08/29/82	(no SMTP));
7 # else SMTP
8 
9 SCCSID(@(#)usersmtp.c	3.18		08/29/82);
10 
11 /*
12 **  SMTPINIT -- initialize SMTP.
13 **
14 **	Opens the connection and sends the initial protocol.
15 **
16 **	Parameters:
17 **		m -- mailer to create connection to.
18 **		pvp -- pointer to parameter vector to pass to
19 **			the mailer.
20 **		ctladdr -- controlling address for this mailer.
21 **
22 **	Returns:
23 **		appropriate exit status -- EX_OK on success.
24 **
25 **	Side Effects:
26 **		creates connection and sends initial protocol.
27 */
28 
29 # define REPLYTYPE(r)	((r) / 100)
30 # define REPLYCLASS(r)	(((r) / 10) % 10)
31 
32 static FILE	*SmtpOut;	/* output file */
33 static FILE	*SmtpIn;	/* input file */
34 static int	SmtpPid;	/* pid of mailer */
35 static int	SmtpErrstat;	/* error status if open fails */
36 
37 smtpinit(m, pvp, ctladdr)
38 	struct mailer *m;
39 	char **pvp;
40 	ADDRESS *ctladdr;
41 {
42 	register int r;
43 	char buf[MAXNAME];
44 	extern tick();
45 	extern char *canonname();
46 
47 	/*
48 	**  Open the connection to the mailer.
49 	*/
50 
51 	SmtpIn = SmtpOut = NULL;
52 	SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn);
53 	if (SmtpPid < 0)
54 	{
55 		SmtpErrstat = ExitStat;
56 # ifdef DEBUG
57 		if (tTd(18, 1))
58 			printf("smtpinit: cannot open: Errstat %d errno %d\n",
59 			   SmtpErrstat, errno);
60 # endif DEBUG
61 		return (ExitStat);
62 	}
63 
64 	/*
65 	**  Get the greeting message.
66 	**	This should appear spontaneously.
67 	*/
68 
69 	r = reply();
70 	if (REPLYTYPE(r) != 2)
71 		return (EX_TEMPFAIL);
72 
73 	/*
74 	**  Send the HELO command.
75 	**	My mother taught me to always introduce myself.
76 	*/
77 
78 	smtpmessage("HELO %s", HostName);
79 	r = reply();
80 	if (REPLYTYPE(r) == 5)
81 		return (EX_UNAVAILABLE);
82 	else if (REPLYTYPE(r) != 2)
83 		return (EX_TEMPFAIL);
84 
85 	/*
86 	**  Send the MAIL command.
87 	**	Designates the sender.
88 	*/
89 
90 	expand("$g", buf, &buf[sizeof buf - 1], CurEnv);
91 	smtpmessage("MAIL From: %s", canonname(buf));
92 	r = reply();
93 	if (REPLYTYPE(r) == 4)
94 		return (EX_TEMPFAIL);
95 	else if (r == 250)
96 		return (EX_OK);
97 	else if (r == 552)
98 		return (EX_UNAVAILABLE);
99 	return (EX_SOFTWARE);
100 }
101 /*
102 **  SMTPRCPT -- designate recipient.
103 **
104 **	Parameters:
105 **		to -- address of recipient.
106 **
107 **	Returns:
108 **		exit status corresponding to recipient status.
109 **
110 **	Side Effects:
111 **		Sends the mail via SMTP.
112 */
113 
114 smtprcpt(to)
115 	ADDRESS *to;
116 {
117 	register int r;
118 	extern char *canonname();
119 
120 	if (SmtpPid < 0)
121 		return (SmtpErrstat);
122 
123 	smtpmessage("RCPT To: %s", canonname(to->q_user));
124 
125 	r = reply();
126 	if (REPLYTYPE(r) == 4)
127 		return (EX_TEMPFAIL);
128 	else if (REPLYCLASS(r) == 5)
129 		return (EX_NOUSER);
130 	else if (REPLYTYPE(r) == 2)
131 		return (EX_OK);
132 	return (EX_SOFTWARE);
133 }
134 /*
135 **  SMTPFINISH -- finish up sending all the SMTP protocol.
136 **
137 **	Parameters:
138 **		m -- mailer being sent to.
139 **		e -- the envelope for this message.
140 **
141 **	Returns:
142 **		exit status corresponding to DATA command.
143 **
144 **	Side Effects:
145 **		none.
146 */
147 
148 smtpfinish(m, e)
149 	struct mailer *m;
150 	register ENVELOPE *e;
151 {
152 	register int r;
153 
154 	if (SmtpPid < 0)
155 		return (SmtpErrstat);
156 
157 	/*
158 	**  Send the data.
159 	**	Dot hiding is done here.
160 	*/
161 
162 	smtpmessage("DATA");
163 	r = reply();
164 	if (REPLYTYPE(r) == 4)
165 		return (EX_TEMPFAIL);
166 	else if (r == 554)
167 		return (EX_UNAVAILABLE);
168 	else if (r != 354)
169 		return (EX_SOFTWARE);
170 	(*e->e_puthdr)(SmtpOut, m, CurEnv);
171 	fprintf(SmtpOut, "\n");
172 	(*e->e_putbody)(SmtpOut, m, TRUE);
173 	smtpmessage(".");
174 	r = reply();
175 	if (REPLYTYPE(r) == 4)
176 		return (EX_TEMPFAIL);
177 	else if (r == 250)
178 		return (EX_OK);
179 	else if (r == 552 || r == 554)
180 		return (EX_UNAVAILABLE);
181 	return (EX_SOFTWARE);
182 }
183 /*
184 **  SMTPQUIT -- close the SMTP connection.
185 **
186 **	Parameters:
187 **		name -- name of mailer we are quitting.
188 **		showresp -- if set, give a response message.
189 **
190 **	Returns:
191 **		none.
192 **
193 **	Side Effects:
194 **		sends the final protocol and closes the connection.
195 */
196 
197 smtpquit(name, showresp)
198 	char *name;
199 	bool showresp;
200 {
201 	register int i;
202 
203 	if (SmtpPid < 0)
204 		return;
205 	smtpmessage("QUIT");
206 	(void) reply();
207 	(void) fclose(SmtpIn);
208 	(void) fclose(SmtpOut);
209 	i = endmailer(SmtpPid, name);
210 	if (showresp)
211 		giveresponse(i, TRUE, LocalMailer);
212 }
213 /*
214 **  REPLY -- read arpanet reply
215 **
216 **	Parameters:
217 **		none.
218 **
219 **	Returns:
220 **		reply code it reads.
221 **
222 **	Side Effects:
223 **		flushes the mail file.
224 */
225 
226 reply()
227 {
228 	(void) fflush(SmtpOut);
229 
230 	if (tTd(18, 1))
231 		printf("reply\n");
232 
233 	/*
234 	**  Read the input line, being careful not to hang.
235 	*/
236 
237 	for (;;)
238 	{
239 		char buf[MAXLINE];
240 		register int r;
241 		register char *p;
242 
243 		/* actually do the read */
244 		(void) fflush(Xscript);			/* for debugging */
245 		p = sfgets(buf, sizeof buf, SmtpIn);
246 
247 		if (p == NULL)
248 			return (-1);
249 
250 		/* log the input in the transcript for future error returns */
251 		if (Verbose && !HoldErrs)
252 			fputs(buf, stdout);
253 		fputs(buf, Xscript);
254 
255 		/* if continuation is required, we can go on */
256 		if (buf[3] == '-' || !isdigit(buf[0]))
257 			continue;
258 
259 		/* decode the reply code */
260 		r = atoi(buf);
261 
262 		/* extra semantics: 0xx codes are "informational" */
263 		if (r < 100)
264 			continue;
265 
266 		return (r);
267 	}
268 }
269 /*
270 **  SMTPMESSAGE -- send message to server
271 **
272 **	Parameters:
273 **		f -- format
274 **		a, b, c -- parameters
275 **
276 **	Returns:
277 **		none.
278 **
279 **	Side Effects:
280 **		writes message to SmtpOut.
281 */
282 
283 /*VARARGS1*/
284 smtpmessage(f, a, b, c)
285 	char *f;
286 {
287 	char buf[100];
288 
289 	(void) sprintf(buf, f, a, b, c);
290 	if (tTd(18, 1) || (Verbose && !HoldErrs))
291 		printf(">>> %s\n", buf);
292 	fprintf(Xscript, ">>> %s\n", buf);
293 	fprintf(SmtpOut, "%s\r\n", buf);
294 }
295 
296 # endif SMTP
297