1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 # include "sendmail.h"
10 
11 #ifndef lint
12 #ifdef SMTP
13 static char sccsid[] = "@(#)usersmtp.c	8.20 (Berkeley) 07/03/94 (with SMTP)";
14 #else
15 static char sccsid[] = "@(#)usersmtp.c	8.20 (Berkeley) 07/03/94 (without SMTP)";
16 #endif
17 #endif /* not lint */
18 
19 # include <sysexits.h>
20 # include <errno.h>
21 
22 # ifdef SMTP
23 
24 /*
25 **  USERSMTP -- run SMTP protocol from the user end.
26 **
27 **	This protocol is described in RFC821.
28 */
29 
30 #define REPLYTYPE(r)	((r) / 100)		/* first digit of reply code */
31 #define REPLYCLASS(r)	(((r) / 10) % 10)	/* second digit of reply code */
32 #define SMTPCLOSING	421			/* "Service Shutting Down" */
33 
34 char	SmtpMsgBuffer[MAXLINE];		/* buffer for commands */
35 char	SmtpReplyBuffer[MAXLINE];	/* buffer for replies */
36 char	SmtpError[MAXLINE] = "";	/* save failure error messages */
37 int	SmtpPid;			/* pid of mailer */
38 bool	SmtpNeedIntro;			/* need "while talking" in transcript */
39 
40 #ifdef __STDC__
41 extern	smtpmessage(char *f, MAILER *m, MCI *mci, ...);
42 #endif
43 /*
44 **  SMTPINIT -- initialize SMTP.
45 **
46 **	Opens the connection and sends the initial protocol.
47 **
48 **	Parameters:
49 **		m -- mailer to create connection to.
50 **		pvp -- pointer to parameter vector to pass to
51 **			the mailer.
52 **
53 **	Returns:
54 **		none.
55 **
56 **	Side Effects:
57 **		creates connection and sends initial protocol.
58 */
59 
60 smtpinit(m, mci, e)
61 	struct mailer *m;
62 	register MCI *mci;
63 	ENVELOPE *e;
64 {
65 	register int r;
66 	register char *p;
67 	extern void esmtp_check();
68 	extern void helo_options();
69 
70 	if (tTd(18, 1))
71 	{
72 		printf("smtpinit ");
73 		mci_dump(mci, FALSE);
74 	}
75 
76 	/*
77 	**  Open the connection to the mailer.
78 	*/
79 
80 	SmtpError[0] = '\0';
81 	CurHostName = mci->mci_host;		/* XXX UGLY XXX */
82 	SmtpNeedIntro = TRUE;
83 	switch (mci->mci_state)
84 	{
85 	  case MCIS_ACTIVE:
86 		/* need to clear old information */
87 		smtprset(m, mci, e);
88 		/* fall through */
89 
90 	  case MCIS_OPEN:
91 		return;
92 
93 	  case MCIS_ERROR:
94 	  case MCIS_SSD:
95 		/* shouldn't happen */
96 		smtpquit(m, mci, e);
97 		/* fall through */
98 
99 	  case MCIS_CLOSED:
100 		syserr("451 smtpinit: state CLOSED");
101 		return;
102 
103 	  case MCIS_OPENING:
104 		break;
105 	}
106 
107 	mci->mci_state = MCIS_OPENING;
108 
109 	/*
110 	**  Get the greeting message.
111 	**	This should appear spontaneously.  Give it five minutes to
112 	**	happen.
113 	*/
114 
115 	SmtpPhase = mci->mci_phase = "client greeting";
116 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
117 	r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
118 	if (r < 0 || REPLYTYPE(r) == 4)
119 		goto tempfail1;
120 	if (REPLYTYPE(r) != 2)
121 		goto unavailable;
122 
123 	/*
124 	**  Send the HELO command.
125 	**	My mother taught me to always introduce myself.
126 	*/
127 
128 	if (bitnset(M_ESMTP, m->m_flags))
129 		mci->mci_flags |= MCIF_ESMTP;
130 
131 tryhelo:
132 	if (bitset(MCIF_ESMTP, mci->mci_flags))
133 	{
134 		smtpmessage("EHLO %s", m, mci, MyHostName);
135 		SmtpPhase = mci->mci_phase = "client EHLO";
136 	}
137 	else
138 	{
139 		smtpmessage("HELO %s", m, mci, MyHostName);
140 		SmtpPhase = mci->mci_phase = "client HELO";
141 	}
142 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
143 	r = reply(m, mci, e, TimeOuts.to_helo, helo_options);
144 	if (r < 0)
145 		goto tempfail1;
146 	else if (REPLYTYPE(r) == 5)
147 	{
148 		if (bitset(MCIF_ESMTP, mci->mci_flags))
149 		{
150 			/* try old SMTP instead */
151 			mci->mci_flags &= ~MCIF_ESMTP;
152 			goto tryhelo;
153 		}
154 		goto unavailable;
155 	}
156 	else if (REPLYTYPE(r) != 2)
157 		goto tempfail1;
158 
159 	/*
160 	**  Check to see if we actually ended up talking to ourself.
161 	**  This means we didn't know about an alias or MX, or we managed
162 	**  to connect to an echo server.
163 	*/
164 
165 	p = strchr(&SmtpReplyBuffer[4], ' ');
166 	if (p != NULL)
167 		*p = '\0';
168 	if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
169 	    strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
170 	{
171 		syserr("553 %s config error: mail loops back to myself",
172 			MyHostName);
173 		mci->mci_exitstat = EX_CONFIG;
174 		mci->mci_errno = 0;
175 		smtpquit(m, mci, e);
176 		return;
177 	}
178 
179 	/*
180 	**  If this is expected to be another sendmail, send some internal
181 	**  commands.
182 	*/
183 
184 	if (bitnset(M_INTERNAL, m->m_flags))
185 	{
186 		/* tell it to be verbose */
187 		smtpmessage("VERB", m, mci);
188 		r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
189 		if (r < 0)
190 			goto tempfail2;
191 	}
192 
193 	if (mci->mci_state != MCIS_CLOSED)
194 	{
195 		mci->mci_state = MCIS_OPEN;
196 		return;
197 	}
198 
199 	/* got a 421 error code during startup */
200 
201   tempfail1:
202   tempfail2:
203 	mci->mci_exitstat = EX_TEMPFAIL;
204 	if (mci->mci_errno == 0)
205 		mci->mci_errno = errno;
206 	if (mci->mci_state != MCIS_CLOSED)
207 		smtpquit(m, mci, e);
208 	return;
209 
210   unavailable:
211 	mci->mci_exitstat = EX_UNAVAILABLE;
212 	mci->mci_errno = errno;
213 	smtpquit(m, mci, e);
214 	return;
215 }
216 /*
217 **  ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
218 **
219 **
220 **	Parameters:
221 **		line -- the response line.
222 **		m -- the mailer.
223 **		mci -- the mailer connection info.
224 **		e -- the envelope.
225 **
226 **	Returns:
227 **		none.
228 */
229 
230 void
231 esmtp_check(line, m, mci, e)
232 	char *line;
233 	MAILER *m;
234 	register MCI *mci;
235 	ENVELOPE *e;
236 {
237 	if (strlen(line) < 5)
238 		return;
239 	line += 4;
240 	if (strncmp(line, "ESMTP ", 6) == 0)
241 		mci->mci_flags |= MCIF_ESMTP;
242 }
243 /*
244 **  HELO_OPTIONS -- process the options on a HELO line.
245 **
246 **	Parameters:
247 **		line -- the response line.
248 **		m -- the mailer.
249 **		mci -- the mailer connection info.
250 **		e -- the envelope.
251 **
252 **	Returns:
253 **		none.
254 */
255 
256 void
257 helo_options(line, m, mci, e)
258 	char *line;
259 	MAILER *m;
260 	register MCI *mci;
261 	ENVELOPE *e;
262 {
263 	register char *p;
264 
265 	if (strlen(line) < 5)
266 		return;
267 	line += 4;
268 	p = strchr(line, ' ');
269 	if (p != NULL)
270 		*p++ = '\0';
271 	if (strcasecmp(line, "size") == 0)
272 	{
273 		mci->mci_flags |= MCIF_SIZE;
274 		if (p != NULL)
275 			mci->mci_maxsize = atol(p);
276 	}
277 	else if (strcasecmp(line, "8bitmime") == 0)
278 	{
279 		mci->mci_flags |= MCIF_8BITMIME;
280 		mci->mci_flags &= ~MCIF_7BIT;
281 	}
282 	else if (strcasecmp(line, "expn") == 0)
283 		mci->mci_flags |= MCIF_EXPN;
284 }
285 /*
286 **  SMTPMAILFROM -- send MAIL command
287 **
288 **	Parameters:
289 **		m -- the mailer.
290 **		mci -- the mailer connection structure.
291 **		e -- the envelope (including the sender to specify).
292 */
293 
294 smtpmailfrom(m, mci, e)
295 	struct mailer *m;
296 	MCI *mci;
297 	ENVELOPE *e;
298 {
299 	int r;
300 	char *bufp;
301 	char buf[MAXNAME];
302 	char optbuf[MAXLINE];
303 
304 	if (tTd(18, 2))
305 		printf("smtpmailfrom: CurHost=%s\n", CurHostName);
306 
307 	/* set up appropriate options to include */
308 	if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
309 		sprintf(optbuf, " SIZE=%ld", e->e_msgsize);
310 	else
311 		strcpy(optbuf, "");
312 
313 	if (e->e_bodytype != NULL)
314 	{
315 		if (bitset(MCIF_8BITMIME, mci->mci_flags))
316 		{
317 			strcat(optbuf, " BODY=");
318 			strcat(optbuf, e->e_bodytype);
319 		}
320 		else if (strcasecmp(e->e_bodytype, "7bit") != 0)
321 		{
322 			/* cannot just send a 7-bit version */
323 			usrerr("%s does not support 8BITMIME", mci->mci_host);
324 			return EX_DATAERR;
325 		}
326 	}
327 
328 	/*
329 	**  Send the MAIL command.
330 	**	Designates the sender.
331 	*/
332 
333 	mci->mci_state = MCIS_ACTIVE;
334 
335 	if (bitset(EF_RESPONSE, e->e_flags) &&
336 	    !bitnset(M_NO_NULL_FROM, m->m_flags))
337 		(void) strcpy(buf, "");
338 	else
339 		expand("\201g", buf, &buf[sizeof buf - 1], e);
340 	if (buf[0] == '<')
341 	{
342 		/* strip off <angle brackets> (put back on below) */
343 		bufp = &buf[strlen(buf) - 1];
344 		if (*bufp == '>')
345 			*bufp = '\0';
346 		bufp = &buf[1];
347 	}
348 	else
349 		bufp = buf;
350 	if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) ||
351 	    !bitnset(M_FROMPATH, m->m_flags))
352 	{
353 		smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf);
354 	}
355 	else
356 	{
357 		smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
358 			*bufp == '@' ? ',' : ':', bufp, optbuf);
359 	}
360 	SmtpPhase = mci->mci_phase = "client MAIL";
361 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
362 	r = reply(m, mci, e, TimeOuts.to_mail, NULL);
363 	if (r < 0 || REPLYTYPE(r) == 4)
364 	{
365 		mci->mci_exitstat = EX_TEMPFAIL;
366 		mci->mci_errno = errno;
367 		smtpquit(m, mci, e);
368 		return EX_TEMPFAIL;
369 	}
370 	else if (r == 250)
371 	{
372 		mci->mci_exitstat = EX_OK;
373 		return EX_OK;
374 	}
375 	else if (r == 552)
376 	{
377 		/* signal service unavailable */
378 		mci->mci_exitstat = EX_UNAVAILABLE;
379 		smtpquit(m, mci, e);
380 		return EX_UNAVAILABLE;
381 	}
382 
383 #ifdef LOG
384 	if (LogLevel > 1)
385 	{
386 		syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s",
387 			e->e_id, SmtpReplyBuffer);
388 	}
389 #endif
390 
391 	/* protocol error -- close up */
392 	smtpquit(m, mci, e);
393 	mci->mci_exitstat = EX_PROTOCOL;
394 	return EX_PROTOCOL;
395 }
396 /*
397 **  SMTPRCPT -- designate recipient.
398 **
399 **	Parameters:
400 **		to -- address of recipient.
401 **		m -- the mailer we are sending to.
402 **		mci -- the connection info for this transaction.
403 **		e -- the envelope for this transaction.
404 **
405 **	Returns:
406 **		exit status corresponding to recipient status.
407 **
408 **	Side Effects:
409 **		Sends the mail via SMTP.
410 */
411 
412 smtprcpt(to, m, mci, e)
413 	ADDRESS *to;
414 	register MAILER *m;
415 	MCI *mci;
416 	ENVELOPE *e;
417 {
418 	register int r;
419 
420 	smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
421 
422 	SmtpPhase = mci->mci_phase = "client RCPT";
423 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
424 	r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
425 	if (r < 0 || REPLYTYPE(r) == 4)
426 		return (EX_TEMPFAIL);
427 	else if (REPLYTYPE(r) == 2)
428 		return (EX_OK);
429 	else if (r == 550 || r == 551 || r == 553)
430 		return (EX_NOUSER);
431 	else if (r == 552 || r == 554)
432 		return (EX_UNAVAILABLE);
433 
434 #ifdef LOG
435 	if (LogLevel > 1)
436 	{
437 		syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s",
438 			e->e_id, SmtpReplyBuffer);
439 	}
440 #endif
441 
442 	return (EX_PROTOCOL);
443 }
444 /*
445 **  SMTPDATA -- send the data and clean up the transaction.
446 **
447 **	Parameters:
448 **		m -- mailer being sent to.
449 **		e -- the envelope for this message.
450 **
451 **	Returns:
452 **		exit status corresponding to DATA command.
453 **
454 **	Side Effects:
455 **		none.
456 */
457 
458 static jmp_buf	CtxDataTimeout;
459 static int	datatimeout();
460 
461 smtpdata(m, mci, e)
462 	struct mailer *m;
463 	register MCI *mci;
464 	register ENVELOPE *e;
465 {
466 	register int r;
467 	register EVENT *ev;
468 	time_t timeout;
469 
470 	/*
471 	**  Send the data.
472 	**	First send the command and check that it is ok.
473 	**	Then send the data.
474 	**	Follow it up with a dot to terminate.
475 	**	Finally get the results of the transaction.
476 	*/
477 
478 	/* send the command and check ok to proceed */
479 	smtpmessage("DATA", m, mci);
480 	SmtpPhase = mci->mci_phase = "client DATA 354";
481 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
482 	r = reply(m, mci, e, TimeOuts.to_datainit, NULL);
483 	if (r < 0 || REPLYTYPE(r) == 4)
484 	{
485 		smtpquit(m, mci, e);
486 		return (EX_TEMPFAIL);
487 	}
488 	else if (r == 554)
489 	{
490 		smtprset(m, mci, e);
491 		return (EX_UNAVAILABLE);
492 	}
493 	else if (r != 354)
494 	{
495 #ifdef LOG
496 		if (LogLevel > 1)
497 		{
498 			syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s",
499 				e->e_id, SmtpReplyBuffer);
500 		}
501 #endif
502 		smtprset(m, mci, e);
503 		return (EX_PROTOCOL);
504 	}
505 
506 	/*
507 	**  Set timeout around data writes.  Make it at least large
508 	**  enough for DNS timeouts on all recipients plus some fudge
509 	**  factor.  The main thing is that it should not be infinite.
510 	*/
511 
512 	if (setjmp(CtxDataTimeout) != 0)
513 	{
514 		mci->mci_errno = errno;
515 		mci->mci_exitstat = EX_TEMPFAIL;
516 		mci->mci_state = MCIS_ERROR;
517 		syserr("451 timeout writing message to %s", mci->mci_host);
518 		smtpquit(m, mci, e);
519 		return EX_TEMPFAIL;
520 	}
521 
522 	timeout = e->e_msgsize / 16;
523 	if (timeout < (time_t) 60)
524 		timeout = (time_t) 60;
525 	timeout += e->e_nrcpts * 90;
526 	ev = setevent(timeout, datatimeout, 0);
527 
528 	/* now output the actual message */
529 	(*e->e_puthdr)(mci, e);
530 	putline("\n", mci);
531 	(*e->e_putbody)(mci, e, NULL);
532 
533 	clrevent(ev);
534 
535 	if (ferror(mci->mci_out))
536 	{
537 		/* error during processing -- don't send the dot */
538 		mci->mci_errno = EIO;
539 		mci->mci_exitstat = EX_IOERR;
540 		mci->mci_state = MCIS_ERROR;
541 		smtpquit(m, mci, e);
542 		return EX_IOERR;
543 	}
544 
545 	/* terminate the message */
546 	fprintf(mci->mci_out, ".%s", m->m_eol);
547 	if (TrafficLogFile != NULL)
548 		fprintf(TrafficLogFile, "%05d >>> .\n", getpid());
549 	if (Verbose)
550 		nmessage(">>> .");
551 
552 	/* check for the results of the transaction */
553 	SmtpPhase = mci->mci_phase = "client DATA 250";
554 	setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
555 	r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
556 	if (r < 0)
557 	{
558 		smtpquit(m, mci, e);
559 		return (EX_TEMPFAIL);
560 	}
561 	mci->mci_state = MCIS_OPEN;
562 	e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
563 	if (REPLYTYPE(r) == 4)
564 		return (EX_TEMPFAIL);
565 	else if (r == 250)
566 		return (EX_OK);
567 	else if (r == 552 || r == 554)
568 		return (EX_UNAVAILABLE);
569 #ifdef LOG
570 	if (LogLevel > 1)
571 	{
572 		syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s",
573 			e->e_id, SmtpReplyBuffer);
574 	}
575 #endif
576 	return (EX_PROTOCOL);
577 }
578 
579 
580 static int
581 datatimeout()
582 {
583 	longjmp(CtxDataTimeout, 1);
584 }
585 /*
586 **  SMTPQUIT -- close the SMTP connection.
587 **
588 **	Parameters:
589 **		m -- a pointer to the mailer.
590 **
591 **	Returns:
592 **		none.
593 **
594 **	Side Effects:
595 **		sends the final protocol and closes the connection.
596 */
597 
598 smtpquit(m, mci, e)
599 	register MAILER *m;
600 	register MCI *mci;
601 	ENVELOPE *e;
602 {
603 	bool oldSuprErrs = SuprErrs;
604 
605 	/*
606 	**	Suppress errors here -- we may be processing a different
607 	**	job when we do the quit connection, and we don't want the
608 	**	new job to be penalized for something that isn't it's
609 	**	problem.
610 	*/
611 
612 	SuprErrs = TRUE;
613 
614 	/* send the quit message if we haven't gotten I/O error */
615 	if (mci->mci_state != MCIS_ERROR)
616 	{
617 		SmtpPhase = "client QUIT";
618 		smtpmessage("QUIT", m, mci);
619 		(void) reply(m, mci, e, TimeOuts.to_quit, NULL);
620 		SuprErrs = oldSuprErrs;
621 		if (mci->mci_state == MCIS_CLOSED)
622 		{
623 			SuprErrs = oldSuprErrs;
624 			return;
625 		}
626 	}
627 
628 	/* now actually close the connection and pick up the zombie */
629 	(void) endmailer(mci, e, NULL);
630 
631 	SuprErrs = oldSuprErrs;
632 }
633 /*
634 **  SMTPRSET -- send a RSET (reset) command
635 */
636 
637 smtprset(m, mci, e)
638 	register MAILER *m;
639 	register MCI *mci;
640 	ENVELOPE *e;
641 {
642 	int r;
643 
644 	SmtpPhase = "client RSET";
645 	smtpmessage("RSET", m, mci);
646 	r = reply(m, mci, e, TimeOuts.to_rset, NULL);
647 	if (r < 0)
648 		mci->mci_state = MCIS_ERROR;
649 	else if (REPLYTYPE(r) == 2)
650 	{
651 		mci->mci_state = MCIS_OPEN;
652 		return;
653 	}
654 	smtpquit(m, mci, e);
655 }
656 /*
657 **  SMTPPROBE -- check the connection state
658 */
659 
660 smtpprobe(mci)
661 	register MCI *mci;
662 {
663 	int r;
664 	MAILER *m = mci->mci_mailer;
665 	extern ENVELOPE BlankEnvelope;
666 	ENVELOPE *e = &BlankEnvelope;
667 
668 	SmtpPhase = "client probe";
669 	smtpmessage("RSET", m, mci);
670 	r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
671 	if (r < 0 || REPLYTYPE(r) != 2)
672 		smtpquit(m, mci, e);
673 	return r;
674 }
675 /*
676 **  REPLY -- read arpanet reply
677 **
678 **	Parameters:
679 **		m -- the mailer we are reading the reply from.
680 **		mci -- the mailer connection info structure.
681 **		e -- the current envelope.
682 **		timeout -- the timeout for reads.
683 **		pfunc -- processing function for second and subsequent
684 **			lines of response -- if null, no special
685 **			processing is done.
686 **
687 **	Returns:
688 **		reply code it reads.
689 **
690 **	Side Effects:
691 **		flushes the mail file.
692 */
693 
694 reply(m, mci, e, timeout, pfunc)
695 	MAILER *m;
696 	MCI *mci;
697 	ENVELOPE *e;
698 	time_t timeout;
699 	void (*pfunc)();
700 {
701 	register char *bufp;
702 	register int r;
703 	bool firstline = TRUE;
704 	char junkbuf[MAXLINE];
705 
706 	if (mci->mci_out != NULL)
707 		(void) fflush(mci->mci_out);
708 
709 	if (tTd(18, 1))
710 		printf("reply\n");
711 
712 	/*
713 	**  Read the input line, being careful not to hang.
714 	*/
715 
716 	for (bufp = SmtpReplyBuffer;; bufp = junkbuf)
717 	{
718 		register char *p;
719 		extern time_t curtime();
720 
721 		/* actually do the read */
722 		if (e->e_xfp != NULL)
723 			(void) fflush(e->e_xfp);	/* for debugging */
724 
725 		/* if we are in the process of closing just give the code */
726 		if (mci->mci_state == MCIS_CLOSED)
727 			return (SMTPCLOSING);
728 
729 		if (mci->mci_out != NULL)
730 			fflush(mci->mci_out);
731 
732 		/* get the line from the other side */
733 		p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase);
734 		mci->mci_lastuse = curtime();
735 
736 		if (p == NULL)
737 		{
738 			bool oldholderrs;
739 			extern char MsgBuf[];		/* err.c */
740 
741 			/* if the remote end closed early, fake an error */
742 			if (errno == 0)
743 # ifdef ECONNRESET
744 				errno = ECONNRESET;
745 # else /* ECONNRESET */
746 				errno = EPIPE;
747 # endif /* ECONNRESET */
748 
749 			mci->mci_errno = errno;
750 			mci->mci_exitstat = EX_TEMPFAIL;
751 			oldholderrs = HoldErrs;
752 			HoldErrs = TRUE;
753 			usrerr("451 reply: read error from %s", mci->mci_host);
754 
755 			/* if debugging, pause so we can see state */
756 			if (tTd(18, 100))
757 				pause();
758 			mci->mci_state = MCIS_ERROR;
759 			smtpquit(m, mci, e);
760 #ifdef XDEBUG
761 			{
762 				char wbuf[MAXLINE];
763 				char *p = wbuf;
764 				if (e->e_to != NULL)
765 				{
766 					sprintf(p, "%s... ", e->e_to);
767 					p += strlen(p);
768 				}
769 				sprintf(p, "reply(%s) during %s",
770 					mci->mci_host, SmtpPhase);
771 				checkfd012(wbuf);
772 			}
773 #endif
774 			HoldErrs = oldholderrs;
775 			return (-1);
776 		}
777 		fixcrlf(bufp, TRUE);
778 
779 		/* EHLO failure is not a real error */
780 		if (e->e_xfp != NULL && (bufp[0] == '4' ||
781 		    (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
782 		{
783 			/* serious error -- log the previous command */
784 			if (SmtpNeedIntro)
785 			{
786 				/* inform user who we are chatting with */
787 				fprintf(CurEnv->e_xfp,
788 					"... while talking to %s:\n",
789 					CurHostName);
790 				SmtpNeedIntro = FALSE;
791 			}
792 			if (SmtpMsgBuffer[0] != '\0')
793 				fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
794 			SmtpMsgBuffer[0] = '\0';
795 
796 			/* now log the message as from the other side */
797 			fprintf(e->e_xfp, "<<< %s\n", bufp);
798 		}
799 
800 		/* display the input for verbose mode */
801 		if (Verbose)
802 			nmessage("050 %s", bufp);
803 
804 		/* process the line */
805 		if (pfunc != NULL && !firstline)
806 			(*pfunc)(bufp, m, mci, e);
807 
808 		firstline = FALSE;
809 
810 		/* if continuation is required, we can go on */
811 		if (bufp[3] == '-')
812 			continue;
813 
814 		/* ignore improperly formated input */
815 		if (!(isascii(bufp[0]) && isdigit(bufp[0])))
816 			continue;
817 
818 		/* decode the reply code */
819 		r = atoi(bufp);
820 
821 		/* extra semantics: 0xx codes are "informational" */
822 		if (r >= 100)
823 			break;
824 	}
825 
826 	/*
827 	**  Now look at SmtpReplyBuffer -- only care about the first
828 	**  line of the response from here on out.
829 	*/
830 
831 	/* save temporary failure messages for posterity */
832 	if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
833 		(void) strcpy(SmtpError, SmtpReplyBuffer);
834 
835 	/* reply code 421 is "Service Shutting Down" */
836 	if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
837 	{
838 		/* send the quit protocol */
839 		mci->mci_state = MCIS_SSD;
840 		smtpquit(m, mci, e);
841 	}
842 
843 	return (r);
844 }
845 /*
846 **  SMTPMESSAGE -- send message to server
847 **
848 **	Parameters:
849 **		f -- format
850 **		m -- the mailer to control formatting.
851 **		a, b, c -- parameters
852 **
853 **	Returns:
854 **		none.
855 **
856 **	Side Effects:
857 **		writes message to mci->mci_out.
858 */
859 
860 /*VARARGS1*/
861 #ifdef __STDC__
862 smtpmessage(char *f, MAILER *m, MCI *mci, ...)
863 #else
864 smtpmessage(f, m, mci, va_alist)
865 	char *f;
866 	MAILER *m;
867 	MCI *mci;
868 	va_dcl
869 #endif
870 {
871 	VA_LOCAL_DECL
872 
873 	VA_START(mci);
874 	(void) vsprintf(SmtpMsgBuffer, f, ap);
875 	VA_END;
876 
877 	if (tTd(18, 1) || Verbose)
878 		nmessage(">>> %s", SmtpMsgBuffer);
879 	if (TrafficLogFile != NULL)
880 		fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(), SmtpMsgBuffer);
881 	if (mci->mci_out != NULL)
882 	{
883 		fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
884 			m == NULL ? "\r\n" : m->m_eol);
885 	}
886 	else if (tTd(18, 1))
887 	{
888 		printf("smtpmessage: NULL mci_out\n");
889 	}
890 }
891 
892 # endif /* SMTP */
893