1 # include <ctype.h>
2 # include <sysexits.h>
3 # include "sendmail.h"
4 
5 # ifndef SMTP
6 SCCSID(@(#)usersmtp.c	3.12.1.1		07/04/82	(no SMTP));
7 # else SMTP
8 
9 SCCSID(@(#)usersmtp.c	3.12.1.1		07/04/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 
31 static FILE	*SmtpOut;	/* output file */
32 static FILE	*SmtpIn;	/* input file */
33 static int	SmtpPid;	/* pid of mailer */
34 static int	SmtpErrstat;	/* error status if open fails */
35 
36 smtpinit(m, pvp, ctladdr)
37 	struct mailer *m;
38 	char **pvp;
39 	ADDRESS *ctladdr;
40 {
41 	register int r;
42 	char buf[MAXNAME];
43 
44 	/*
45 	**  Open the connection to the mailer.
46 	*/
47 
48 	SmtpIn = SmtpOut = NULL;
49 	SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn);
50 	if (SmtpPid < 0)
51 	{
52 		SmtpErrstat = ExitStat;
53 # ifdef DEBUG
54 		if (Debug > 0)
55 			printf("smtpinit: cannot open: Errstat %d errno %d\n",
56 			   SmtpErrstat, errno);
57 # endif DEBUG
58 		return (ExitStat);
59 	}
60 
61 	/*
62 	**  Get the greeting message.
63 	**	This should appear spontaneously.
64 	*/
65 
66 	r = reply();
67 	if (REPLYTYPE(r) != 2)
68 		return (EX_TEMPFAIL);
69 
70 	/*
71 	**  Send the HELO command.
72 	**	My mother taught me to always introduce myself, even
73 	**	if it is useless.
74 	*/
75 
76 	smtpmessage("HELO %s", HostName);
77 	r = reply();
78 	if (REPLYTYPE(r) == 5)
79 		return (EX_UNAVAILABLE);
80 	if (REPLYTYPE(r) != 2)
81 		return (EX_TEMPFAIL);
82 
83 	/*
84 	**  Send the HOPS command.
85 	**	This is non-standard and may give an "unknown command".
86 	**		This is not an error.
87 	**	It can give a "bad hop count" error if the hop
88 	**		count is exceeded.
89 	*/
90 
91 	/*
92 	**  Send the MAIL command.
93 	**	Designates the sender.
94 	*/
95 
96 	expand("$g", buf, &buf[sizeof buf - 1], CurEnv);
97 	smtpmessage("MAIL From:<%s>", buf);
98 	r = reply();
99 	if (REPLYTYPE(r) == 4)
100 		return (EX_TEMPFAIL);
101 	if (r != 250)
102 		return (EX_SOFTWARE);
103 	return (EX_OK);
104 }
105 /*
106 **  SMTPRCPT -- designate recipient.
107 **
108 **	Parameters:
109 **		to -- address of recipient.
110 **
111 **	Returns:
112 **		exit status corresponding to recipient status.
113 **
114 **	Side Effects:
115 **		Sends the mail via SMTP.
116 */
117 
118 smtprcpt(to)
119 	ADDRESS *to;
120 {
121 	register int r;
122 
123 	if (SmtpPid < 0)
124 		return (SmtpErrstat);
125 
126 	smtpmessage("RCPT To:<%s>", to->q_user);
127 
128 	r = reply();
129 	if (REPLYTYPE(r) == 4)
130 		return (EX_TEMPFAIL);
131 	if (r != 250)
132 		return (EX_NOUSER);
133 
134 	return (EX_OK);
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 	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 	if (r != 250)
178 		return (EX_SOFTWARE);
179 	return (EX_OK);
180 }
181 /*
182 **  SMTPQUIT -- close the SMTP connection.
183 **
184 **	Parameters:
185 **		name -- name of mailer we are quitting.
186 **		showresp -- if set, give a response message.
187 **
188 **	Returns:
189 **		none.
190 **
191 **	Side Effects:
192 **		sends the final protocol and closes the connection.
193 */
194 
195 smtpquit(name, showresp)
196 	char *name;
197 	bool showresp;
198 {
199 	register int i;
200 
201 	if (SmtpPid < 0)
202 		return;
203 	smtpmessage("QUIT");
204 	(void) reply();
205 	(void) fclose(SmtpIn);
206 	(void) fclose(SmtpOut);
207 	i = endmailer(SmtpPid, name);
208 	if (showresp)
209 		giveresponse(i, TRUE, LocalMailer);
210 }
211 /*
212 **  REPLY -- read arpanet reply
213 **
214 **	Parameters:
215 **		none.
216 **
217 **	Returns:
218 **		reply code it reads.
219 **
220 **	Side Effects:
221 **		flushes the mail file.
222 */
223 
224 reply()
225 {
226 	(void) fflush(SmtpOut);
227 
228 	if (Debug)
229 		printf("reply\n");
230 
231 	/* read the input line */
232 	for (;;)
233 	{
234 		char buf[MAXLINE];
235 		register int r;
236 
237 		if (fgets(buf, sizeof buf, SmtpIn) == NULL)
238 			return (-1);
239 		if (Verbose && !HoldErrs)
240 			fputs(buf, stdout);
241 		fputs(buf, Xscript);
242 		if (buf[3] == '-' || !isdigit(buf[0]))
243 			continue;
244 		r = atoi(buf);
245 		if (r < 100)
246 			continue;
247 		return (r);
248 	}
249 }
250 /*
251 **  SMTPMESSAGE -- send message to server
252 **
253 **	Parameters:
254 **		f -- format
255 **		a, b, c -- parameters
256 **
257 **	Returns:
258 **		none.
259 **
260 **	Side Effects:
261 **		writes message to SmtpOut.
262 */
263 
264 /*VARARGS1*/
265 smtpmessage(f, a, b, c)
266 	char *f;
267 {
268 	char buf[100];
269 
270 	(void) sprintf(buf, f, a, b, c);
271 	if (Debug || (Verbose && !HoldErrs))
272 		printf(">>> %s\n", buf);
273 	fprintf(Xscript, ">>> %s\n", buf);
274 	fprintf(SmtpOut, "%s\r\n", buf);
275 }
276 
277 # endif SMTP
278