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