1 # include <ctype.h>
2 # include <sysexits.h>
3 # include "sendmail.h"
4 
5 # ifndef SMTP
6 SCCSID(@(#)usersmtp.c	3.19		08/29/82	(no SMTP));
7 # else SMTP
8 
9 SCCSID(@(#)usersmtp.c	3.19		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_PROTOCOL);
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 (REPLYTYPE(r) == 2)
129 		return (EX_OK);
130 	else if (r == 550 || r == 551 || r == 553)
131 		return (EX_NOUSER);
132 	else if (r == 552 || r == 554)
133 		return (EX_UNAVAILABLE);
134 	return (EX_PROTOCOL);
135 }
136 /*
137 **  SMTPFINISH -- finish up sending all the SMTP protocol.
138 **
139 **	Parameters:
140 **		m -- mailer being sent to.
141 **		e -- the envelope for this message.
142 **
143 **	Returns:
144 **		exit status corresponding to DATA command.
145 **
146 **	Side Effects:
147 **		none.
148 */
149 
150 smtpfinish(m, e)
151 	struct mailer *m;
152 	register ENVELOPE *e;
153 {
154 	register int r;
155 
156 	if (SmtpPid < 0)
157 		return (SmtpErrstat);
158 
159 	/*
160 	**  Send the data.
161 	**	Dot hiding is done here.
162 	*/
163 
164 	smtpmessage("DATA");
165 	r = reply();
166 	if (REPLYTYPE(r) == 4)
167 		return (EX_TEMPFAIL);
168 	else if (r == 554)
169 		return (EX_UNAVAILABLE);
170 	else if (r != 354)
171 		return (EX_PROTOCOL);
172 	(*e->e_puthdr)(SmtpOut, m, CurEnv);
173 	fprintf(SmtpOut, "\n");
174 	(*e->e_putbody)(SmtpOut, m, TRUE);
175 	smtpmessage(".");
176 	r = reply();
177 	if (REPLYTYPE(r) == 4)
178 		return (EX_TEMPFAIL);
179 	else if (r == 250)
180 		return (EX_OK);
181 	else if (r == 552 || r == 554)
182 		return (EX_UNAVAILABLE);
183 	return (EX_PROTOCOL);
184 }
185 /*
186 **  SMTPQUIT -- close the SMTP connection.
187 **
188 **	Parameters:
189 **		name -- name of mailer we are quitting.
190 **		showresp -- if set, give a response message.
191 **
192 **	Returns:
193 **		none.
194 **
195 **	Side Effects:
196 **		sends the final protocol and closes the connection.
197 */
198 
199 smtpquit(name, showresp)
200 	char *name;
201 	bool showresp;
202 {
203 	register int i;
204 
205 	if (SmtpPid < 0)
206 		return;
207 	smtpmessage("QUIT");
208 	(void) reply();
209 	(void) fclose(SmtpIn);
210 	(void) fclose(SmtpOut);
211 	i = endmailer(SmtpPid, name);
212 	if (showresp)
213 		giveresponse(i, TRUE, LocalMailer);
214 }
215 /*
216 **  REPLY -- read arpanet reply
217 **
218 **	Parameters:
219 **		none.
220 **
221 **	Returns:
222 **		reply code it reads.
223 **
224 **	Side Effects:
225 **		flushes the mail file.
226 */
227 
228 reply()
229 {
230 	(void) fflush(SmtpOut);
231 
232 	if (tTd(18, 1))
233 		printf("reply\n");
234 
235 	/*
236 	**  Read the input line, being careful not to hang.
237 	*/
238 
239 	for (;;)
240 	{
241 		char buf[MAXLINE];
242 		register int r;
243 		register char *p;
244 
245 		/* actually do the read */
246 		(void) fflush(Xscript);			/* for debugging */
247 		p = sfgets(buf, sizeof buf, SmtpIn);
248 
249 		if (p == NULL)
250 			return (-1);
251 
252 		/* log the input in the transcript for future error returns */
253 		if (Verbose && !HoldErrs)
254 			fputs(buf, stdout);
255 		fputs(buf, Xscript);
256 
257 		/* if continuation is required, we can go on */
258 		if (buf[3] == '-' || !isdigit(buf[0]))
259 			continue;
260 
261 		/* decode the reply code */
262 		r = atoi(buf);
263 
264 		/* extra semantics: 0xx codes are "informational" */
265 		if (r < 100)
266 			continue;
267 
268 		return (r);
269 	}
270 }
271 /*
272 **  SMTPMESSAGE -- send message to server
273 **
274 **	Parameters:
275 **		f -- format
276 **		a, b, c -- parameters
277 **
278 **	Returns:
279 **		none.
280 **
281 **	Side Effects:
282 **		writes message to SmtpOut.
283 */
284 
285 /*VARARGS1*/
286 smtpmessage(f, a, b, c)
287 	char *f;
288 {
289 	char buf[100];
290 
291 	(void) sprintf(buf, f, a, b, c);
292 	if (tTd(18, 1) || (Verbose && !HoldErrs))
293 		printf(">>> %s\n", buf);
294 	fprintf(Xscript, ">>> %s\n", buf);
295 	fprintf(SmtpOut, "%s\r\n", buf);
296 }
297 
298 # endif SMTP
299