usersmtp.c revision 42575
1/*
2 * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4 * Copyright (c) 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13# include "sendmail.h"
14
15#ifndef lint
16#if SMTP
17static char sccsid[] = "@(#)usersmtp.c	8.108 (Berkeley) 10/6/1998 (with SMTP)";
18#else
19static char sccsid[] = "@(#)usersmtp.c	8.108 (Berkeley) 10/6/1998 (without SMTP)";
20#endif
21#endif /* not lint */
22
23# include <sysexits.h>
24# include <errno.h>
25
26# if SMTP
27
28/*
29**  USERSMTP -- run SMTP protocol from the user end.
30**
31**	This protocol is described in RFC821.
32*/
33
34#define REPLYTYPE(r)	((r) / 100)		/* first digit of reply code */
35#define REPLYCLASS(r)	(((r) / 10) % 10)	/* second digit of reply code */
36#define SMTPCLOSING	421			/* "Service Shutting Down" */
37
38char	SmtpMsgBuffer[MAXLINE];		/* buffer for commands */
39char	SmtpReplyBuffer[MAXLINE];	/* buffer for replies */
40char	SmtpError[MAXLINE] = "";	/* save failure error messages */
41bool	SmtpNeedIntro;			/* need "while talking" in transcript */
42
43extern void	smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
44extern int	reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)()));
45/*
46**  SMTPINIT -- initialize SMTP.
47**
48**	Opens the connection and sends the initial protocol.
49**
50**	Parameters:
51**		m -- mailer to create connection to.
52**		pvp -- pointer to parameter vector to pass to
53**			the mailer.
54**
55**	Returns:
56**		none.
57**
58**	Side Effects:
59**		creates connection and sends initial protocol.
60*/
61
62void
63smtpinit(m, mci, e)
64	MAILER *m;
65	register MCI *mci;
66	ENVELOPE *e;
67{
68	register int r;
69	register char *p;
70	extern void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
71	extern void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
72
73	if (tTd(18, 1))
74	{
75		printf("smtpinit ");
76		mci_dump(mci, FALSE);
77	}
78
79	/*
80	**  Open the connection to the mailer.
81	*/
82
83	SmtpError[0] = '\0';
84	CurHostName = mci->mci_host;		/* XXX UGLY XXX */
85	if (CurHostName == NULL)
86		CurHostName = MyHostName;
87	SmtpNeedIntro = TRUE;
88	switch (mci->mci_state)
89	{
90	  case MCIS_ACTIVE:
91		/* need to clear old information */
92		smtprset(m, mci, e);
93		/* fall through */
94
95	  case MCIS_OPEN:
96		return;
97
98	  case MCIS_ERROR:
99	  case MCIS_SSD:
100		/* shouldn't happen */
101		smtpquit(m, mci, e);
102		/* fall through */
103
104	  case MCIS_CLOSED:
105		syserr("451 smtpinit: state CLOSED");
106		return;
107
108	  case MCIS_OPENING:
109		break;
110	}
111
112	mci->mci_state = MCIS_OPENING;
113
114	/*
115	**  Get the greeting message.
116	**	This should appear spontaneously.  Give it five minutes to
117	**	happen.
118	*/
119
120	SmtpPhase = mci->mci_phase = "client greeting";
121	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
122	r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
123	if (r < 0)
124		goto tempfail1;
125	if (REPLYTYPE(r) == 4)
126		goto tempfail2;
127	if (REPLYTYPE(r) != 2)
128		goto unavailable;
129
130	/*
131	**  Send the HELO command.
132	**	My mother taught me to always introduce myself.
133	*/
134
135	if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
136		mci->mci_flags |= MCIF_ESMTP;
137
138tryhelo:
139	if (bitnset(M_LMTP, m->m_flags))
140	{
141		smtpmessage("LHLO %s", m, mci, MyHostName);
142		SmtpPhase = mci->mci_phase = "client LHLO";
143	}
144	else if (bitset(MCIF_ESMTP, mci->mci_flags))
145	{
146		smtpmessage("EHLO %s", m, mci, MyHostName);
147		SmtpPhase = mci->mci_phase = "client EHLO";
148	}
149	else
150	{
151		smtpmessage("HELO %s", m, mci, MyHostName);
152		SmtpPhase = mci->mci_phase = "client HELO";
153	}
154	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
155	r = reply(m, mci, e, TimeOuts.to_helo, helo_options);
156	if (r < 0)
157		goto tempfail1;
158	else if (REPLYTYPE(r) == 5)
159	{
160		if (bitset(MCIF_ESMTP, mci->mci_flags) &&
161		    !bitnset(M_LMTP, m->m_flags))
162		{
163			/* try old SMTP instead */
164			mci->mci_flags &= ~MCIF_ESMTP;
165			goto tryhelo;
166		}
167		goto unavailable;
168	}
169	else if (REPLYTYPE(r) != 2)
170		goto tempfail2;
171
172	/*
173	**  Check to see if we actually ended up talking to ourself.
174	**  This means we didn't know about an alias or MX, or we managed
175	**  to connect to an echo server.
176	*/
177
178	p = strchr(&SmtpReplyBuffer[4], ' ');
179	if (p != NULL)
180		*p = '\0';
181	if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
182	    !bitnset(M_LMTP, m->m_flags) &&
183	    strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
184	{
185		syserr("553 %s config error: mail loops back to me (MX problem?)",
186			CurHostName);
187		mci_setstat(mci, EX_CONFIG, NULL, NULL);
188		mci->mci_errno = 0;
189		smtpquit(m, mci, e);
190		return;
191	}
192
193	/*
194	**  If this is expected to be another sendmail, send some internal
195	**  commands.
196	*/
197
198	if (bitnset(M_INTERNAL, m->m_flags))
199	{
200		/* tell it to be verbose */
201		smtpmessage("VERB", m, mci);
202		r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
203		if (r < 0)
204			goto tempfail1;
205	}
206
207	if (mci->mci_state != MCIS_CLOSED)
208	{
209		mci->mci_state = MCIS_OPEN;
210		return;
211	}
212
213	/* got a 421 error code during startup */
214
215  tempfail1:
216	if (mci->mci_errno == 0)
217		mci->mci_errno = errno;
218	mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
219	if (mci->mci_state != MCIS_CLOSED)
220		smtpquit(m, mci, e);
221	return;
222
223  tempfail2:
224	if (mci->mci_errno == 0)
225		mci->mci_errno = errno;
226	/* XXX should use code from other end iff ENHANCEDSTATUSCODES */
227	mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
228	if (mci->mci_state != MCIS_CLOSED)
229		smtpquit(m, mci, e);
230	return;
231
232  unavailable:
233	mci->mci_errno = errno;
234	mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);
235	smtpquit(m, mci, e);
236	return;
237}
238/*
239**  ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
240**
241**	Parameters:
242**		line -- the response line.
243**		firstline -- set if this is the first line of the reply.
244**		m -- the mailer.
245**		mci -- the mailer connection info.
246**		e -- the envelope.
247**
248**	Returns:
249**		none.
250*/
251
252void
253esmtp_check(line, firstline, m, mci, e)
254	char *line;
255	bool firstline;
256	MAILER *m;
257	register MCI *mci;
258	ENVELOPE *e;
259{
260	if (strstr(line, "ESMTP") != NULL)
261		mci->mci_flags |= MCIF_ESMTP;
262	if (strstr(line, "8BIT-OK") != NULL)
263		mci->mci_flags |= MCIF_8BITOK;
264}
265/*
266**  HELO_OPTIONS -- process the options on a HELO line.
267**
268**	Parameters:
269**		line -- the response line.
270**		firstline -- set if this is the first line of the reply.
271**		m -- the mailer.
272**		mci -- the mailer connection info.
273**		e -- the envelope.
274**
275**	Returns:
276**		none.
277*/
278
279void
280helo_options(line, firstline, m, mci, e)
281	char *line;
282	bool firstline;
283	MAILER *m;
284	register MCI *mci;
285	ENVELOPE *e;
286{
287	register char *p;
288
289	if (firstline)
290		return;
291
292	if (strlen(line) < (SIZE_T) 5)
293		return;
294	line += 4;
295	p = strchr(line, ' ');
296	if (p != NULL)
297		*p++ = '\0';
298	if (strcasecmp(line, "size") == 0)
299	{
300		mci->mci_flags |= MCIF_SIZE;
301		if (p != NULL)
302			mci->mci_maxsize = atol(p);
303	}
304	else if (strcasecmp(line, "8bitmime") == 0)
305	{
306		mci->mci_flags |= MCIF_8BITMIME;
307		mci->mci_flags &= ~MCIF_7BIT;
308	}
309	else if (strcasecmp(line, "expn") == 0)
310		mci->mci_flags |= MCIF_EXPN;
311	else if (strcasecmp(line, "dsn") == 0)
312		mci->mci_flags |= MCIF_DSN;
313}
314/*
315**  SMTPMAILFROM -- send MAIL command
316**
317**	Parameters:
318**		m -- the mailer.
319**		mci -- the mailer connection structure.
320**		e -- the envelope (including the sender to specify).
321*/
322
323int
324smtpmailfrom(m, mci, e)
325	MAILER *m;
326	MCI *mci;
327	ENVELOPE *e;
328{
329	int r;
330	int l;
331	char *bufp;
332	char *bodytype;
333	char buf[MAXNAME + 1];
334	char optbuf[MAXLINE];
335
336	if (tTd(18, 2))
337		printf("smtpmailfrom: CurHost=%s\n", CurHostName);
338
339	/* set up appropriate options to include */
340	if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
341		snprintf(optbuf, sizeof optbuf, " SIZE=%ld", e->e_msgsize);
342	else
343		strcpy(optbuf, "");
344	l = sizeof optbuf - strlen(optbuf) - 1;
345
346	bodytype = e->e_bodytype;
347	if (bitset(MCIF_8BITMIME, mci->mci_flags))
348	{
349		if (bodytype == NULL &&
350		    bitset(MM_MIME8BIT, MimeMode) &&
351		    bitset(EF_HAS8BIT, e->e_flags) &&
352		    !bitset(EF_DONT_MIME, e->e_flags) &&
353		    !bitnset(M_8BITS, m->m_flags))
354			bodytype = "8BITMIME";
355		if (bodytype != NULL && strlen(bodytype) + 7 < l)
356		{
357			strcat(optbuf, " BODY=");
358			strcat(optbuf, bodytype);
359			l -= strlen(optbuf);
360		}
361	}
362	else if (bitnset(M_8BITS, m->m_flags) ||
363		 !bitset(EF_HAS8BIT, e->e_flags) ||
364		 bitset(MCIF_8BITOK, mci->mci_flags))
365	{
366		/* just pass it through */
367	}
368#if MIME8TO7
369	else if (bitset(MM_CVTMIME, MimeMode) &&
370		 !bitset(EF_DONT_MIME, e->e_flags) &&
371		 (!bitset(MM_PASS8BIT, MimeMode) ||
372		  bitset(EF_IS_MIME, e->e_flags)))
373	{
374		/* must convert from 8bit MIME format to 7bit encoded */
375		mci->mci_flags |= MCIF_CVT8TO7;
376	}
377#endif
378	else if (!bitset(MM_PASS8BIT, MimeMode))
379	{
380		/* cannot just send a 8-bit version */
381		extern char MsgBuf[];
382
383		usrerr("%s does not support 8BITMIME", CurHostName);
384		mci_setstat(mci, EX_NOTSTICKY, "5.6.3", MsgBuf);
385		return EX_DATAERR;
386	}
387
388	if (bitset(MCIF_DSN, mci->mci_flags))
389	{
390		if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) (l - 7))
391		{
392			strcat(optbuf, " ENVID=");
393			strcat(optbuf, e->e_envid);
394			l -= strlen(optbuf);
395		}
396
397		/* RET= parameter */
398		if (bitset(EF_RET_PARAM, e->e_flags) && l >= 9)
399		{
400			strcat(optbuf, " RET=");
401			if (bitset(EF_NO_BODY_RETN, e->e_flags))
402				strcat(optbuf, "HDRS");
403			else
404				strcat(optbuf, "FULL");
405			l -= 9;
406		}
407	}
408
409	/*
410	**  Send the MAIL command.
411	**	Designates the sender.
412	*/
413
414	mci->mci_state = MCIS_ACTIVE;
415
416	if (bitset(EF_RESPONSE, e->e_flags) &&
417	    !bitnset(M_NO_NULL_FROM, m->m_flags))
418		(void) strcpy(buf, "");
419	else
420		expand("\201g", buf, sizeof buf, e);
421	if (buf[0] == '<')
422	{
423		/* strip off <angle brackets> (put back on below) */
424		bufp = &buf[strlen(buf) - 1];
425		if (*bufp == '>')
426			*bufp = '\0';
427		bufp = &buf[1];
428	}
429	else
430		bufp = buf;
431	if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) ||
432	    !bitnset(M_FROMPATH, m->m_flags))
433	{
434		smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf);
435	}
436	else
437	{
438		smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
439			*bufp == '@' ? ',' : ':', bufp, optbuf);
440	}
441	SmtpPhase = mci->mci_phase = "client MAIL";
442	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
443	r = reply(m, mci, e, TimeOuts.to_mail, NULL);
444	if (r < 0)
445	{
446		/* communications failure */
447		mci->mci_errno = errno;
448		mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
449		smtpquit(m, mci, e);
450		return EX_TEMPFAIL;
451	}
452	else if (r == 421)
453	{
454		/* service shutting down */
455		mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
456		smtpquit(m, mci, e);
457		return EX_TEMPFAIL;
458	}
459	else if (REPLYTYPE(r) == 4)
460	{
461		mci_setstat(mci, EX_NOTSTICKY, smtptodsn(r), SmtpReplyBuffer);
462		return EX_TEMPFAIL;
463	}
464	else if (REPLYTYPE(r) == 2)
465	{
466		return EX_OK;
467	}
468	else if (r == 501)
469	{
470		/* syntax error in arguments */
471		mci_setstat(mci, EX_NOTSTICKY, "5.5.2", SmtpReplyBuffer);
472		return EX_DATAERR;
473	}
474	else if (r == 553)
475	{
476		/* mailbox name not allowed */
477		mci_setstat(mci, EX_NOTSTICKY, "5.1.3", SmtpReplyBuffer);
478		return EX_DATAERR;
479	}
480	else if (r == 552)
481	{
482		/* exceeded storage allocation */
483		mci_setstat(mci, EX_NOTSTICKY, "5.3.4", SmtpReplyBuffer);
484		if (bitset(MCIF_SIZE, mci->mci_flags))
485			e->e_flags |= EF_NO_BODY_RETN;
486		return EX_UNAVAILABLE;
487	}
488	else if (REPLYTYPE(r) == 5)
489	{
490		/* unknown error */
491		mci_setstat(mci, EX_NOTSTICKY, "5.0.0", SmtpReplyBuffer);
492		return EX_UNAVAILABLE;
493	}
494
495	if (LogLevel > 1)
496	{
497		sm_syslog(LOG_CRIT, e->e_id,
498			"%.100s: SMTP MAIL protocol error: %s",
499			CurHostName,
500			shortenstring(SmtpReplyBuffer, 403));
501	}
502
503	/* protocol error -- close up */
504	mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
505	smtpquit(m, mci, e);
506	return EX_PROTOCOL;
507}
508/*
509**  SMTPRCPT -- designate recipient.
510**
511**	Parameters:
512**		to -- address of recipient.
513**		m -- the mailer we are sending to.
514**		mci -- the connection info for this transaction.
515**		e -- the envelope for this transaction.
516**
517**	Returns:
518**		exit status corresponding to recipient status.
519**
520**	Side Effects:
521**		Sends the mail via SMTP.
522*/
523
524int
525smtprcpt(to, m, mci, e)
526	ADDRESS *to;
527	register MAILER *m;
528	MCI *mci;
529	ENVELOPE *e;
530{
531	register int r;
532	int l;
533	char optbuf[MAXLINE];
534
535	strcpy(optbuf, "");
536	l = sizeof optbuf - 1;
537	if (bitset(MCIF_DSN, mci->mci_flags))
538	{
539		/* NOTIFY= parameter */
540		if (bitset(QHASNOTIFY, to->q_flags) &&
541		    bitset(QPRIMARY, to->q_flags) &&
542		    !bitnset(M_LOCALMAILER, m->m_flags))
543		{
544			bool firstone = TRUE;
545
546			strcat(optbuf, " NOTIFY=");
547			if (bitset(QPINGONSUCCESS, to->q_flags))
548			{
549				strcat(optbuf, "SUCCESS");
550				firstone = FALSE;
551			}
552			if (bitset(QPINGONFAILURE, to->q_flags))
553			{
554				if (!firstone)
555					strcat(optbuf, ",");
556				strcat(optbuf, "FAILURE");
557				firstone = FALSE;
558			}
559			if (bitset(QPINGONDELAY, to->q_flags))
560			{
561				if (!firstone)
562					strcat(optbuf, ",");
563				strcat(optbuf, "DELAY");
564				firstone = FALSE;
565			}
566			if (firstone)
567				strcat(optbuf, "NEVER");
568			l -= strlen(optbuf);
569		}
570
571		/* ORCPT= parameter */
572		if (to->q_orcpt != NULL && strlen(to->q_orcpt) + 7 < l)
573		{
574			strcat(optbuf, " ORCPT=");
575			strcat(optbuf, to->q_orcpt);
576			l -= strlen(optbuf);
577		}
578	}
579
580	smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf);
581
582	SmtpPhase = mci->mci_phase = "client RCPT";
583	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
584	r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
585	to->q_rstatus = newstr(SmtpReplyBuffer);
586	to->q_status = smtptodsn(r);
587	to->q_statmta = mci->mci_host;
588	if (r < 0 || REPLYTYPE(r) == 4)
589		return EX_TEMPFAIL;
590	else if (REPLYTYPE(r) == 2)
591		return EX_OK;
592	else if (r == 550)
593	{
594		to->q_status = "5.1.1";
595		return EX_NOUSER;
596	}
597	else if (r == 551)
598	{
599		to->q_status = "5.1.6";
600		return EX_NOUSER;
601	}
602	else if (r == 553)
603	{
604		to->q_status = "5.1.3";
605		return EX_NOUSER;
606	}
607	else if (REPLYTYPE(r) == 5)
608	{
609		return EX_UNAVAILABLE;
610	}
611
612	if (LogLevel > 1)
613	{
614		sm_syslog(LOG_CRIT, e->e_id,
615			"%.100s: SMTP RCPT protocol error: %s",
616			CurHostName,
617			shortenstring(SmtpReplyBuffer, 403));
618	}
619
620	mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
621	return EX_PROTOCOL;
622}
623/*
624**  SMTPDATA -- send the data and clean up the transaction.
625**
626**	Parameters:
627**		m -- mailer being sent to.
628**		mci -- the mailer connection information.
629**		e -- the envelope for this message.
630**
631**	Returns:
632**		exit status corresponding to DATA command.
633**
634**	Side Effects:
635**		none.
636*/
637
638static jmp_buf	CtxDataTimeout;
639static void	datatimeout __P((void));
640
641int
642smtpdata(m, mci, e)
643	MAILER *m;
644	register MCI *mci;
645	register ENVELOPE *e;
646{
647	register int r;
648	register EVENT *ev;
649	int rstat;
650	int xstat;
651	time_t timeout;
652
653	/*
654	**  Send the data.
655	**	First send the command and check that it is ok.
656	**	Then send the data.
657	**	Follow it up with a dot to terminate.
658	**	Finally get the results of the transaction.
659	*/
660
661	/* send the command and check ok to proceed */
662	smtpmessage("DATA", m, mci);
663	SmtpPhase = mci->mci_phase = "client DATA 354";
664	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
665	r = reply(m, mci, e, TimeOuts.to_datainit, NULL);
666	if (r < 0 || REPLYTYPE(r) == 4)
667	{
668		smtpquit(m, mci, e);
669		return EX_TEMPFAIL;
670	}
671	else if (REPLYTYPE(r) == 5)
672	{
673		smtprset(m, mci, e);
674		return EX_UNAVAILABLE;
675	}
676	else if (r != 354)
677	{
678		if (LogLevel > 1)
679		{
680			sm_syslog(LOG_CRIT, e->e_id,
681				"%.100s: SMTP DATA-1 protocol error: %s",
682				CurHostName,
683				shortenstring(SmtpReplyBuffer, 403));
684		}
685		smtprset(m, mci, e);
686		mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
687		return (EX_PROTOCOL);
688	}
689
690	/*
691	**  Set timeout around data writes.  Make it at least large
692	**  enough for DNS timeouts on all recipients plus some fudge
693	**  factor.  The main thing is that it should not be infinite.
694	*/
695
696	if (setjmp(CtxDataTimeout) != 0)
697	{
698		mci->mci_errno = errno;
699		mci->mci_state = MCIS_ERROR;
700		mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
701		syserr("451 timeout writing message to %s", CurHostName);
702		smtpquit(m, mci, e);
703		return EX_TEMPFAIL;
704	}
705
706	timeout = e->e_msgsize / 16;
707	if (timeout < (time_t) 600)
708		timeout = (time_t) 600;
709	timeout += e->e_nrcpts * 300;
710	ev = setevent(timeout, datatimeout, 0);
711
712	/*
713	**  Output the actual message.
714	*/
715
716	(*e->e_puthdr)(mci, e->e_header, e);
717	(*e->e_putbody)(mci, e, NULL);
718
719	/*
720	**  Cleanup after sending message.
721	*/
722
723	clrevent(ev);
724
725	if (ferror(mci->mci_out))
726	{
727		/* error during processing -- don't send the dot */
728		mci->mci_errno = EIO;
729		mci->mci_state = MCIS_ERROR;
730		mci_setstat(mci, EX_IOERR, "4.4.2", NULL);
731		smtpquit(m, mci, e);
732		return EX_IOERR;
733	}
734
735	/* terminate the message */
736	fprintf(mci->mci_out, ".%s", m->m_eol);
737	if (TrafficLogFile != NULL)
738		fprintf(TrafficLogFile, "%05d >>> .\n", (int) getpid());
739	if (Verbose)
740		nmessage(">>> .");
741
742	/* check for the results of the transaction */
743	SmtpPhase = mci->mci_phase = "client DATA status";
744	sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
745	if (bitnset(M_LMTP, m->m_flags))
746		return EX_OK;
747	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
748	if (r < 0)
749	{
750		smtpquit(m, mci, e);
751		return EX_TEMPFAIL;
752	}
753	mci->mci_state = MCIS_OPEN;
754	xstat = EX_NOTSTICKY;
755	if (r == 452)
756		rstat = EX_TEMPFAIL;
757	else if (REPLYTYPE(r) == 4)
758		rstat = xstat = EX_TEMPFAIL;
759	else if (REPLYCLASS(r) != 5)
760		rstat = xstat = EX_PROTOCOL;
761	else if (REPLYTYPE(r) == 2)
762		rstat = xstat = EX_OK;
763	else if (REPLYTYPE(r) == 5)
764		rstat = EX_UNAVAILABLE;
765	else
766		rstat = EX_PROTOCOL;
767	mci_setstat(mci, xstat, smtptodsn(r), SmtpReplyBuffer);
768	if (e->e_statmsg != NULL)
769		free(e->e_statmsg);
770	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
771	if (rstat != EX_PROTOCOL)
772		return rstat;
773	if (LogLevel > 1)
774	{
775		sm_syslog(LOG_CRIT, e->e_id,
776			"%.100s: SMTP DATA-2 protocol error: %s",
777			CurHostName,
778			shortenstring(SmtpReplyBuffer, 403));
779	}
780	return rstat;
781}
782
783
784static void
785datatimeout()
786{
787	longjmp(CtxDataTimeout, 1);
788}
789/*
790**  SMTPGETSTAT -- get status code from DATA in LMTP
791**
792**	Parameters:
793**		m -- the mailer to which we are sending the message.
794**		mci -- the mailer connection structure.
795**		e -- the current envelope.
796**
797**	Returns:
798**		The exit status corresponding to the reply code.
799*/
800
801int
802smtpgetstat(m, mci, e)
803	MAILER *m;
804	MCI *mci;
805	ENVELOPE *e;
806{
807	int r;
808	int stat;
809
810	/* check for the results of the transaction */
811	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
812	if (r < 0)
813	{
814		smtpquit(m, mci, e);
815		return EX_TEMPFAIL;
816	}
817	if (e->e_statmsg != NULL)
818		free(e->e_statmsg);
819	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
820	if (REPLYTYPE(r) == 4)
821		stat = EX_TEMPFAIL;
822	else if (REPLYCLASS(r) != 5)
823		stat = EX_PROTOCOL;
824	else if (REPLYTYPE(r) == 2)
825		stat = EX_OK;
826	else if (REPLYTYPE(r) == 5)
827		stat = EX_UNAVAILABLE;
828	else
829		stat = EX_PROTOCOL;
830	mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
831	if (LogLevel > 1 && stat == EX_PROTOCOL)
832	{
833		sm_syslog(LOG_CRIT, e->e_id,
834			"%.100s: SMTP DATA-3 protocol error: %s",
835			CurHostName,
836			shortenstring(SmtpReplyBuffer, 403));
837	}
838	return stat;
839}
840/*
841**  SMTPQUIT -- close the SMTP connection.
842**
843**	Parameters:
844**		m -- a pointer to the mailer.
845**		mci -- the mailer connection information.
846**		e -- the current envelope.
847**
848**	Returns:
849**		none.
850**
851**	Side Effects:
852**		sends the final protocol and closes the connection.
853*/
854
855void
856smtpquit(m, mci, e)
857	register MAILER *m;
858	register MCI *mci;
859	ENVELOPE *e;
860{
861	bool oldSuprErrs = SuprErrs;
862
863	/*
864	**	Suppress errors here -- we may be processing a different
865	**	job when we do the quit connection, and we don't want the
866	**	new job to be penalized for something that isn't it's
867	**	problem.
868	*/
869
870	SuprErrs = TRUE;
871
872	/* send the quit message if we haven't gotten I/O error */
873	if (mci->mci_state != MCIS_ERROR)
874	{
875		SmtpPhase = "client QUIT";
876		smtpmessage("QUIT", m, mci);
877		(void) reply(m, mci, e, TimeOuts.to_quit, NULL);
878		SuprErrs = oldSuprErrs;
879		if (mci->mci_state == MCIS_CLOSED)
880			return;
881	}
882
883	/* now actually close the connection and pick up the zombie */
884	(void) endmailer(mci, e, NULL);
885
886	SuprErrs = oldSuprErrs;
887}
888/*
889**  SMTPRSET -- send a RSET (reset) command
890*/
891
892void
893smtprset(m, mci, e)
894	register MAILER *m;
895	register MCI *mci;
896	ENVELOPE *e;
897{
898	int r;
899
900	SmtpPhase = "client RSET";
901	smtpmessage("RSET", m, mci);
902	r = reply(m, mci, e, TimeOuts.to_rset, NULL);
903	if (r < 0)
904		mci->mci_state = MCIS_ERROR;
905	else if (REPLYTYPE(r) == 2)
906	{
907		mci->mci_state = MCIS_OPEN;
908		return;
909	}
910	smtpquit(m, mci, e);
911}
912/*
913**  SMTPPROBE -- check the connection state
914*/
915
916int
917smtpprobe(mci)
918	register MCI *mci;
919{
920	int r;
921	MAILER *m = mci->mci_mailer;
922	extern ENVELOPE BlankEnvelope;
923	ENVELOPE *e = &BlankEnvelope;
924
925	SmtpPhase = "client probe";
926	smtpmessage("RSET", m, mci);
927	r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
928	if (r < 0 || REPLYTYPE(r) != 2)
929		smtpquit(m, mci, e);
930	return r;
931}
932/*
933**  REPLY -- read arpanet reply
934**
935**	Parameters:
936**		m -- the mailer we are reading the reply from.
937**		mci -- the mailer connection info structure.
938**		e -- the current envelope.
939**		timeout -- the timeout for reads.
940**		pfunc -- processing function called on each line of response.
941**			If null, no special processing is done.
942**
943**	Returns:
944**		reply code it reads.
945**
946**	Side Effects:
947**		flushes the mail file.
948*/
949
950int
951reply(m, mci, e, timeout, pfunc)
952	MAILER *m;
953	MCI *mci;
954	ENVELOPE *e;
955	time_t timeout;
956	void (*pfunc)();
957{
958	register char *bufp;
959	register int r;
960	bool firstline = TRUE;
961	char junkbuf[MAXLINE];
962
963	if (mci->mci_out != NULL)
964		(void) fflush(mci->mci_out);
965
966	if (tTd(18, 1))
967		printf("reply\n");
968
969	/*
970	**  Read the input line, being careful not to hang.
971	*/
972
973	bufp = SmtpReplyBuffer;
974	for (;;)
975	{
976		register char *p;
977
978		/* actually do the read */
979		if (e->e_xfp != NULL)
980			(void) fflush(e->e_xfp);	/* for debugging */
981
982		/* if we are in the process of closing just give the code */
983		if (mci->mci_state == MCIS_CLOSED)
984			return (SMTPCLOSING);
985
986		if (mci->mci_out != NULL)
987			fflush(mci->mci_out);
988
989		/* get the line from the other side */
990		p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase);
991		mci->mci_lastuse = curtime();
992
993		if (p == NULL)
994		{
995			bool oldholderrs;
996			extern char MsgBuf[];
997
998			/* if the remote end closed early, fake an error */
999			if (errno == 0)
1000# ifdef ECONNRESET
1001				errno = ECONNRESET;
1002# else /* ECONNRESET */
1003				errno = EPIPE;
1004# endif /* ECONNRESET */
1005
1006			mci->mci_errno = errno;
1007			oldholderrs = HoldErrs;
1008			HoldErrs = TRUE;
1009			usrerr("451 reply: read error from %s", CurHostName);
1010
1011			/* errors on QUIT should not be persistent */
1012			if (strncmp(SmtpMsgBuffer, "QUIT", 4) != 0)
1013				mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf);
1014
1015			/* if debugging, pause so we can see state */
1016			if (tTd(18, 100))
1017				pause();
1018			mci->mci_state = MCIS_ERROR;
1019			smtpquit(m, mci, e);
1020#if XDEBUG
1021			{
1022				char wbuf[MAXLINE];
1023				char *p = wbuf;
1024				int wbufleft = sizeof wbuf;
1025
1026				if (e->e_to != NULL)
1027				{
1028					int plen;
1029
1030					snprintf(p, wbufleft, "%s... ",
1031						shortenstring(e->e_to, MAXSHORTSTR));
1032					plen = strlen(p);
1033					p += plen;
1034					wbufleft -= plen;
1035				}
1036				snprintf(p, wbufleft, "reply(%.100s) during %s",
1037					 CurHostName == NULL ? "NO_HOST" : CurHostName,
1038					 SmtpPhase);
1039				checkfd012(wbuf);
1040			}
1041#endif
1042			HoldErrs = oldholderrs;
1043			return (-1);
1044		}
1045		fixcrlf(bufp, TRUE);
1046
1047		/* EHLO failure is not a real error */
1048		if (e->e_xfp != NULL && (bufp[0] == '4' ||
1049		    (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
1050		{
1051			/* serious error -- log the previous command */
1052			if (SmtpNeedIntro)
1053			{
1054				/* inform user who we are chatting with */
1055				fprintf(CurEnv->e_xfp,
1056					"... while talking to %s:\n",
1057					CurHostName);
1058				SmtpNeedIntro = FALSE;
1059			}
1060			if (SmtpMsgBuffer[0] != '\0')
1061				fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
1062			SmtpMsgBuffer[0] = '\0';
1063
1064			/* now log the message as from the other side */
1065			fprintf(e->e_xfp, "<<< %s\n", bufp);
1066		}
1067
1068		/* display the input for verbose mode */
1069		if (Verbose)
1070			nmessage("050 %s", bufp);
1071
1072		/* ignore improperly formated input */
1073		if (!(isascii(bufp[0]) && isdigit(bufp[0])) ||
1074		    !(isascii(bufp[1]) && isdigit(bufp[1])) ||
1075		    !(isascii(bufp[2]) && isdigit(bufp[2])) ||
1076		    !(bufp[3] == ' ' || bufp[3] == '-' || bufp[3] == '\0'))
1077			continue;
1078
1079		/* process the line */
1080		if (pfunc != NULL)
1081			(*pfunc)(bufp, firstline, m, mci, e);
1082
1083		firstline = FALSE;
1084
1085		/* decode the reply code */
1086		r = atoi(bufp);
1087
1088		/* extra semantics: 0xx codes are "informational" */
1089		if (r < 100)
1090			continue;
1091
1092		/* if no continuation lines, return this line */
1093		if (bufp[3] != '-')
1094			break;
1095
1096		/* first line of real reply -- ignore rest */
1097		bufp = junkbuf;
1098	}
1099
1100	/*
1101	**  Now look at SmtpReplyBuffer -- only care about the first
1102	**  line of the response from here on out.
1103	*/
1104
1105	/* save temporary failure messages for posterity */
1106	if (SmtpReplyBuffer[0] == '4' &&
1107	    (bitnset(M_LMTP, m->m_flags) || SmtpError[0] == '\0'))
1108		snprintf(SmtpError, sizeof SmtpError, "%s", SmtpReplyBuffer);
1109
1110	/* reply code 421 is "Service Shutting Down" */
1111	if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
1112	{
1113		/* send the quit protocol */
1114		mci->mci_state = MCIS_SSD;
1115		smtpquit(m, mci, e);
1116	}
1117
1118	return (r);
1119}
1120/*
1121**  SMTPMESSAGE -- send message to server
1122**
1123**	Parameters:
1124**		f -- format
1125**		m -- the mailer to control formatting.
1126**		a, b, c -- parameters
1127**
1128**	Returns:
1129**		none.
1130**
1131**	Side Effects:
1132**		writes message to mci->mci_out.
1133*/
1134
1135/*VARARGS1*/
1136void
1137#ifdef __STDC__
1138smtpmessage(char *f, MAILER *m, MCI *mci, ...)
1139#else
1140smtpmessage(f, m, mci, va_alist)
1141	char *f;
1142	MAILER *m;
1143	MCI *mci;
1144	va_dcl
1145#endif
1146{
1147	VA_LOCAL_DECL
1148
1149	VA_START(mci);
1150	(void) vsnprintf(SmtpMsgBuffer, sizeof SmtpMsgBuffer, f, ap);
1151	VA_END;
1152
1153	if (tTd(18, 1) || Verbose)
1154		nmessage(">>> %s", SmtpMsgBuffer);
1155	if (TrafficLogFile != NULL)
1156		fprintf(TrafficLogFile, "%05d >>> %s\n",
1157			(int) getpid(), SmtpMsgBuffer);
1158	if (mci->mci_out != NULL)
1159	{
1160		fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
1161			m == NULL ? "\r\n" : m->m_eol);
1162	}
1163	else if (tTd(18, 1))
1164	{
1165		printf("smtpmessage: NULL mci_out\n");
1166	}
1167}
1168
1169# endif /* SMTP */
1170