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