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