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