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