2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
13 # include "sendmail.h"
17 static char sccsid[] = "@(#)usersmtp.c 8.111 (Berkeley) 2/3/1999 (with SMTP)";
19 static char sccsid[] = "@(#)usersmtp.c 8.111 (Berkeley) 2/3/1999 (without SMTP)";
23 # include <sysexits.h>
29 ** USERSMTP -- run SMTP protocol from the user end.
31 ** This protocol is described in RFC821.
34 #define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */
35 #define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */
36 #define SMTPCLOSING 421 /* "Service Shutting Down" */
38 char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */
39 char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */
40 char SmtpError[MAXLINE] = ""; /* save failure error messages */
41 bool SmtpNeedIntro; /* need "while talking" in transcript */
43 extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
44 extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)()));
46 ** SMTPINIT -- initialize SMTP.
48 ** Opens the connection and sends the initial protocol.
51 ** m -- mailer to create connection to.
52 ** pvp -- pointer to parameter vector to pass to
59 ** creates connection and sends initial protocol.
70 extern void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
71 extern void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
80 ** Open the connection to the mailer.
84 CurHostName = mci->mci_host; /* XXX UGLY XXX */
85 if (CurHostName == NULL)
86 CurHostName = MyHostName;
88 switch (mci->mci_state)
91 /* need to clear old information */
100 /* shouldn't happen */
105 syserr("451 smtpinit: state CLOSED");
112 mci->mci_state = MCIS_OPENING;
115 ** Get the greeting message.
116 ** This should appear spontaneously. Give it five minutes to
120 SmtpPhase = mci->mci_phase = "client greeting";
121 sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
122 r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
125 if (REPLYTYPE(r) == 4)
127 if (REPLYTYPE(r) != 2)
131 ** Send the HELO command.
132 ** My mother taught me to always introduce myself.
135 if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
136 mci->mci_flags |= MCIF_ESMTP;
139 if (bitnset(M_LMTP, m->m_flags))
141 smtpmessage("LHLO %s", m, mci, MyHostName);
142 SmtpPhase = mci->mci_phase = "client LHLO";
144 else if (bitset(MCIF_ESMTP, mci->mci_flags))
146 smtpmessage("EHLO %s", m, mci, MyHostName);
147 SmtpPhase = mci->mci_phase = "client EHLO";
151 smtpmessage("HELO %s", m, mci, MyHostName);
152 SmtpPhase = mci->mci_phase = "client HELO";
154 sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
155 r = reply(m, mci, e, TimeOuts.to_helo, helo_options);
158 else if (REPLYTYPE(r) == 5)
160 if (bitset(MCIF_ESMTP, mci->mci_flags) &&
161 !bitnset(M_LMTP, m->m_flags))
163 /* try old SMTP instead */
164 mci->mci_flags &= ~MCIF_ESMTP;
169 else if (REPLYTYPE(r) != 2)
173 ** Check to see if we actually ended up talking to ourself.
174 ** This means we didn't know about an alias or MX, or we managed
175 ** to connect to an echo server.
178 p = strchr(&SmtpReplyBuffer[4], ' ');
181 if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
182 !bitnset(M_LMTP, m->m_flags) &&
183 strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
185 syserr("553 %s config error: mail loops back to me (MX problem?)",
187 mci_setstat(mci, EX_CONFIG, NULL, NULL);
194 ** If this is expected to be another sendmail, send some internal
198 if (bitnset(M_INTERNAL, m->m_flags))
200 /* tell it to be verbose */
201 smtpmessage("VERB", m, mci);
202 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
207 if (mci->mci_state != MCIS_CLOSED)
209 mci->mci_state = MCIS_OPEN;
213 /* got a 421 error code during startup */
216 if (mci->mci_errno == 0)
217 mci->mci_errno = errno;
218 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
219 if (mci->mci_state != MCIS_CLOSED)
224 if (mci->mci_errno == 0)
225 mci->mci_errno = errno;
226 /* XXX should use code from other end iff ENHANCEDSTATUSCODES */
227 mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
228 if (mci->mci_state != MCIS_CLOSED)
233 mci->mci_errno = errno;
234 mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);
239 ** ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
242 ** line -- the response line.
243 ** firstline -- set if this is the first line of the reply.
245 ** mci -- the mailer connection info.
246 ** e -- the envelope.
253 esmtp_check(line, firstline, m, mci, e)
260 if (strstr(line, "ESMTP") != NULL)
261 mci->mci_flags |= MCIF_ESMTP;
262 if (strstr(line, "8BIT-OK") != NULL)
263 mci->mci_flags |= MCIF_8BITOK;
266 ** HELO_OPTIONS -- process the options on a HELO line.
269 ** line -- the response line.
270 ** firstline -- set if this is the first line of the reply.
272 ** mci -- the mailer connection info.
273 ** e -- the envelope.
280 helo_options(line, firstline, m, mci, e)
292 if (strlen(line) < (SIZE_T) 5)
295 p = strchr(line, ' ');
298 if (strcasecmp(line, "size") == 0)
300 mci->mci_flags |= MCIF_SIZE;
302 mci->mci_maxsize = atol(p);
304 else if (strcasecmp(line, "8bitmime") == 0)
306 mci->mci_flags |= MCIF_8BITMIME;
307 mci->mci_flags &= ~MCIF_7BIT;
309 else if (strcasecmp(line, "expn") == 0)
310 mci->mci_flags |= MCIF_EXPN;
311 else if (strcasecmp(line, "dsn") == 0)
312 mci->mci_flags |= MCIF_DSN;
315 ** SMTPMAILFROM -- send MAIL command
319 ** mci -- the mailer connection structure.
320 ** e -- the envelope (including the sender to specify).
324 smtpmailfrom(m, mci, e)
332 char buf[MAXNAME + 1];
333 char optbuf[MAXLINE];
336 printf("smtpmailfrom: CurHost=%s\n", CurHostName);
338 /* set up appropriate options to include */
340 if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
341 snprintf(optbuf, sizeof optbuf, " SIZE=%ld", e->e_msgsize);
344 bufp = &optbuf[strlen(optbuf)];
346 bodytype = e->e_bodytype;
347 if (bitset(MCIF_8BITMIME, mci->mci_flags))
349 if (bodytype == NULL &&
350 bitset(MM_MIME8BIT, MimeMode) &&
351 bitset(EF_HAS8BIT, e->e_flags) &&
352 !bitset(EF_DONT_MIME, e->e_flags) &&
353 !bitnset(M_8BITS, m->m_flags))
354 bodytype = "8BITMIME";
355 if (bodytype != NULL &&
356 SPACELEFT(optbuf, bufp) > strlen(bodytype) + 7)
358 snprintf(bufp, SPACELEFT(optbuf, bufp),
359 " BODY=%s", bodytype);
360 bufp += strlen(bufp);
363 else if (bitnset(M_8BITS, m->m_flags) ||
364 !bitset(EF_HAS8BIT, e->e_flags) ||
365 bitset(MCIF_8BITOK, mci->mci_flags))
367 /* just pass it through */
370 else if (bitset(MM_CVTMIME, MimeMode) &&
371 !bitset(EF_DONT_MIME, e->e_flags) &&
372 (!bitset(MM_PASS8BIT, MimeMode) ||
373 bitset(EF_IS_MIME, e->e_flags)))
375 /* must convert from 8bit MIME format to 7bit encoded */
376 mci->mci_flags |= MCIF_CVT8TO7;
379 else if (!bitset(MM_PASS8BIT, MimeMode))
381 /* cannot just send a 8-bit version */
382 extern char MsgBuf[];
384 usrerr("%s does not support 8BITMIME", CurHostName);
385 mci_setstat(mci, EX_NOTSTICKY, "5.6.3", MsgBuf);
389 if (bitset(MCIF_DSN, mci->mci_flags))
391 if (e->e_envid != NULL &&
392 SPACELEFT(optbuf, bufp) > strlen(e->e_envid) + 7)
394 snprintf(bufp, SPACELEFT(optbuf, bufp),
395 " ENVID=%s", e->e_envid);
396 bufp += strlen(bufp);
400 if (bitset(EF_RET_PARAM, e->e_flags) &&
401 SPACELEFT(optbuf, bufp) > 9)
403 snprintf(bufp, SPACELEFT(optbuf, bufp),
405 bitset(EF_NO_BODY_RETN, e->e_flags) ?
407 bufp += strlen(bufp);
412 ** Send the MAIL command.
413 ** Designates the sender.
416 mci->mci_state = MCIS_ACTIVE;
418 if (bitset(EF_RESPONSE, e->e_flags) &&
419 !bitnset(M_NO_NULL_FROM, m->m_flags))
420 (void) strcpy(buf, "");
422 expand("\201g", buf, sizeof buf, e);
425 /* strip off <angle brackets> (put back on below) */
426 bufp = &buf[strlen(buf) - 1];
433 if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) ||
434 !bitnset(M_FROMPATH, m->m_flags))
436 smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf);
440 smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
441 *bufp == '@' ? ',' : ':', bufp, optbuf);
443 SmtpPhase = mci->mci_phase = "client MAIL";
444 sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
445 r = reply(m, mci, e, TimeOuts.to_mail, NULL);
448 /* communications failure */
449 mci->mci_errno = errno;
450 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
456 /* service shutting down */
457 mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
461 else if (REPLYTYPE(r) == 4)
463 mci_setstat(mci, EX_NOTSTICKY, smtptodsn(r), SmtpReplyBuffer);
466 else if (REPLYTYPE(r) == 2)
472 /* syntax error in arguments */
473 mci_setstat(mci, EX_NOTSTICKY, "5.5.2", SmtpReplyBuffer);
478 /* mailbox name not allowed */
479 mci_setstat(mci, EX_NOTSTICKY, "5.1.3", SmtpReplyBuffer);
484 /* exceeded storage allocation */
485 mci_setstat(mci, EX_NOTSTICKY, "5.3.4", SmtpReplyBuffer);
486 if (bitset(MCIF_SIZE, mci->mci_flags))
487 e->e_flags |= EF_NO_BODY_RETN;
488 return EX_UNAVAILABLE;
490 else if (REPLYTYPE(r) == 5)
493 mci_setstat(mci, EX_NOTSTICKY, "5.0.0", SmtpReplyBuffer);
494 return EX_UNAVAILABLE;
499 sm_syslog(LOG_CRIT, e->e_id,
500 "%.100s: SMTP MAIL protocol error: %s",
502 shortenstring(SmtpReplyBuffer, 403));
505 /* protocol error -- close up */
506 mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
511 ** SMTPRCPT -- designate recipient.
514 ** to -- address of recipient.
515 ** m -- the mailer we are sending to.
516 ** mci -- the connection info for this transaction.
517 ** e -- the envelope for this transaction.
520 ** exit status corresponding to recipient status.
523 ** Sends the mail via SMTP.
527 smtprcpt(to, m, mci, e)
535 char optbuf[MAXLINE];
538 bufp = &optbuf[strlen(optbuf)];
539 if (bitset(MCIF_DSN, mci->mci_flags))
541 /* NOTIFY= parameter */
542 if (bitset(QHASNOTIFY, to->q_flags) &&
543 bitset(QPRIMARY, to->q_flags) &&
544 !bitnset(M_LOCALMAILER, m->m_flags))
546 bool firstone = TRUE;
548 strcat(bufp, " NOTIFY=");
549 if (bitset(QPINGONSUCCESS, to->q_flags))
551 strcat(bufp, "SUCCESS");
554 if (bitset(QPINGONFAILURE, to->q_flags))
558 strcat(bufp, "FAILURE");
561 if (bitset(QPINGONDELAY, to->q_flags))
565 strcat(bufp, "DELAY");
569 strcat(bufp, "NEVER");
570 bufp += strlen(bufp);
573 /* ORCPT= parameter */
574 if (to->q_orcpt != NULL &&
575 SPACELEFT(optbuf, bufp) > strlen(to->q_orcpt) + 7)
577 snprintf(bufp, SPACELEFT(optbuf, bufp),
578 " ORCPT=%s", to->q_orcpt);
579 bufp += strlen(bufp);
583 smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf);
585 SmtpPhase = mci->mci_phase = "client RCPT";
586 sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
587 r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
588 to->q_rstatus = newstr(SmtpReplyBuffer);
589 to->q_status = smtptodsn(r);
590 to->q_statmta = mci->mci_host;
591 if (r < 0 || REPLYTYPE(r) == 4)
593 else if (REPLYTYPE(r) == 2)
597 to->q_status = "5.1.1";
602 to->q_status = "5.1.6";
607 to->q_status = "5.1.3";
610 else if (REPLYTYPE(r) == 5)
612 return EX_UNAVAILABLE;
617 sm_syslog(LOG_CRIT, e->e_id,
618 "%.100s: SMTP RCPT protocol error: %s",
620 shortenstring(SmtpReplyBuffer, 403));
623 mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
627 ** SMTPDATA -- send the data and clean up the transaction.
630 ** m -- mailer being sent to.
631 ** mci -- the mailer connection information.
632 ** e -- the envelope for this message.
635 ** exit status corresponding to DATA command.
641 static jmp_buf CtxDataTimeout;
642 static void datatimeout __P((void));
648 register ENVELOPE *e;
658 ** First send the command and check that it is ok.
659 ** Then send the data.
660 ** Follow it up with a dot to terminate.
661 ** Finally get the results of the transaction.
664 /* send the command and check ok to proceed */
665 smtpmessage("DATA", m, mci);
666 SmtpPhase = mci->mci_phase = "client DATA 354";
667 sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
668 r = reply(m, mci, e, TimeOuts.to_datainit, NULL);
669 if (r < 0 || REPLYTYPE(r) == 4)
674 else if (REPLYTYPE(r) == 5)
677 return EX_UNAVAILABLE;
679 else if (REPLYTYPE(r) != 3)
683 sm_syslog(LOG_CRIT, e->e_id,
684 "%.100s: SMTP DATA-1 protocol error: %s",
686 shortenstring(SmtpReplyBuffer, 403));
689 mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
690 return (EX_PROTOCOL);
694 ** Set timeout around data writes. Make it at least large
695 ** enough for DNS timeouts on all recipients plus some fudge
696 ** factor. The main thing is that it should not be infinite.
699 if (setjmp(CtxDataTimeout) != 0)
701 mci->mci_errno = errno;
702 mci->mci_state = MCIS_ERROR;
703 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
704 syserr("451 timeout writing message to %s", CurHostName);
709 timeout = e->e_msgsize / 16;
710 if (timeout < (time_t) 600)
711 timeout = (time_t) 600;
712 timeout += e->e_nrcpts * 300;
713 ev = setevent(timeout, datatimeout, 0);
716 ** Output the actual message.
719 (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
720 (*e->e_putbody)(mci, e, NULL);
723 ** Cleanup after sending message.
728 if (ferror(mci->mci_out))
730 /* error during processing -- don't send the dot */
731 mci->mci_errno = EIO;
732 mci->mci_state = MCIS_ERROR;
733 mci_setstat(mci, EX_IOERR, "4.4.2", NULL);
738 /* terminate the message */
739 fprintf(mci->mci_out, ".%s", m->m_eol);
740 if (TrafficLogFile != NULL)
741 fprintf(TrafficLogFile, "%05d >>> .\n", (int) getpid());
745 /* check for the results of the transaction */
746 SmtpPhase = mci->mci_phase = "client DATA status";
747 sm_setproctitle(TRUE, "%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
748 if (bitnset(M_LMTP, m->m_flags))
750 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
756 mci->mci_state = MCIS_OPEN;
757 xstat = EX_NOTSTICKY;
760 else if (REPLYTYPE(r) == 4)
761 rstat = xstat = EX_TEMPFAIL;
762 else if (REPLYCLASS(r) != 5)
763 rstat = xstat = EX_PROTOCOL;
764 else if (REPLYTYPE(r) == 2)
765 rstat = xstat = EX_OK;
766 else if (REPLYTYPE(r) == 5)
767 rstat = EX_UNAVAILABLE;
770 mci_setstat(mci, xstat, smtptodsn(r), SmtpReplyBuffer);
771 if (e->e_statmsg != NULL)
773 e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
774 if (rstat != EX_PROTOCOL)
778 sm_syslog(LOG_CRIT, e->e_id,
779 "%.100s: SMTP DATA-2 protocol error: %s",
781 shortenstring(SmtpReplyBuffer, 403));
790 longjmp(CtxDataTimeout, 1);
793 ** SMTPGETSTAT -- get status code from DATA in LMTP
796 ** m -- the mailer to which we are sending the message.
797 ** mci -- the mailer connection structure.
798 ** e -- the current envelope.
801 ** The exit status corresponding to the reply code.
805 smtpgetstat(m, mci, e)
813 /* check for the results of the transaction */
814 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
820 if (e->e_statmsg != NULL)
822 e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
823 if (REPLYTYPE(r) == 4)
825 else if (REPLYCLASS(r) != 5)
827 else if (REPLYTYPE(r) == 2)
829 else if (REPLYTYPE(r) == 5)
830 stat = EX_UNAVAILABLE;
833 mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
834 if (LogLevel > 1 && stat == EX_PROTOCOL)
836 sm_syslog(LOG_CRIT, e->e_id,
837 "%.100s: SMTP DATA-3 protocol error: %s",
839 shortenstring(SmtpReplyBuffer, 403));
844 ** SMTPQUIT -- close the SMTP connection.
847 ** m -- a pointer to the mailer.
848 ** mci -- the mailer connection information.
849 ** e -- the current envelope.
855 ** sends the final protocol and closes the connection.
864 bool oldSuprErrs = SuprErrs;
867 ** Suppress errors here -- we may be processing a different
868 ** job when we do the quit connection, and we don't want the
869 ** new job to be penalized for something that isn't it's
875 /* send the quit message if we haven't gotten I/O error */
876 if (mci->mci_state != MCIS_ERROR)
878 SmtpPhase = "client QUIT";
879 smtpmessage("QUIT", m, mci);
880 (void) reply(m, mci, e, TimeOuts.to_quit, NULL);
881 SuprErrs = oldSuprErrs;
882 if (mci->mci_state == MCIS_CLOSED)
886 /* now actually close the connection and pick up the zombie */
887 (void) endmailer(mci, e, NULL);
889 SuprErrs = oldSuprErrs;
892 ** SMTPRSET -- send a RSET (reset) command
903 SmtpPhase = "client RSET";
904 smtpmessage("RSET", m, mci);
905 r = reply(m, mci, e, TimeOuts.to_rset, NULL);
907 mci->mci_state = MCIS_ERROR;
908 else if (REPLYTYPE(r) == 2)
910 mci->mci_state = MCIS_OPEN;
916 ** SMTPPROBE -- check the connection state
924 MAILER *m = mci->mci_mailer;
925 extern ENVELOPE BlankEnvelope;
926 ENVELOPE *e = &BlankEnvelope;
928 SmtpPhase = "client probe";
929 smtpmessage("RSET", m, mci);
930 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
931 if (r < 0 || REPLYTYPE(r) != 2)
936 ** REPLY -- read arpanet reply
939 ** m -- the mailer we are reading the reply from.
940 ** mci -- the mailer connection info structure.
941 ** e -- the current envelope.
942 ** timeout -- the timeout for reads.
943 ** pfunc -- processing function called on each line of response.
944 ** If null, no special processing is done.
947 ** reply code it reads.
950 ** flushes the mail file.
954 reply(m, mci, e, timeout, pfunc)
963 bool firstline = TRUE;
964 char junkbuf[MAXLINE];
966 if (mci->mci_out != NULL)
967 (void) fflush(mci->mci_out);
973 ** Read the input line, being careful not to hang.
976 bufp = SmtpReplyBuffer;
981 /* actually do the read */
982 if (e->e_xfp != NULL)
983 (void) fflush(e->e_xfp); /* for debugging */
985 /* if we are in the process of closing just give the code */
986 if (mci->mci_state == MCIS_CLOSED)
987 return (SMTPCLOSING);
989 if (mci->mci_out != NULL)
990 fflush(mci->mci_out);
992 /* get the line from the other side */
993 p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase);
994 mci->mci_lastuse = curtime();
999 extern char MsgBuf[];
1001 /* if the remote end closed early, fake an error */
1005 # else /* ECONNRESET */
1007 # endif /* ECONNRESET */
1009 mci->mci_errno = errno;
1010 oldholderrs = HoldErrs;
1012 usrerr("451 reply: read error from %s", CurHostName);
1014 /* errors on QUIT should not be persistent */
1015 if (strncmp(SmtpMsgBuffer, "QUIT", 4) != 0)
1016 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf);
1018 /* if debugging, pause so we can see state */
1021 mci->mci_state = MCIS_ERROR;
1022 smtpquit(m, mci, e);
1027 int wbufleft = sizeof wbuf;
1029 if (e->e_to != NULL)
1033 snprintf(p, wbufleft, "%s... ",
1034 shortenstring(e->e_to, MAXSHORTSTR));
1039 snprintf(p, wbufleft, "reply(%.100s) during %s",
1040 CurHostName == NULL ? "NO_HOST" : CurHostName,
1045 HoldErrs = oldholderrs;
1048 fixcrlf(bufp, TRUE);
1050 /* EHLO failure is not a real error */
1051 if (e->e_xfp != NULL && (bufp[0] == '4' ||
1052 (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
1054 /* serious error -- log the previous command */
1057 /* inform user who we are chatting with */
1058 fprintf(CurEnv->e_xfp,
1059 "... while talking to %s:\n",
1061 SmtpNeedIntro = FALSE;
1063 if (SmtpMsgBuffer[0] != '\0')
1064 fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
1065 SmtpMsgBuffer[0] = '\0';
1067 /* now log the message as from the other side */
1068 fprintf(e->e_xfp, "<<< %s\n", bufp);
1071 /* display the input for verbose mode */
1073 nmessage("050 %s", bufp);
1075 /* ignore improperly formated input */
1076 if (!(isascii(bufp[0]) && isdigit(bufp[0])) ||
1077 !(isascii(bufp[1]) && isdigit(bufp[1])) ||
1078 !(isascii(bufp[2]) && isdigit(bufp[2])) ||
1079 !(bufp[3] == ' ' || bufp[3] == '-' || bufp[3] == '\0'))
1082 /* process the line */
1084 (*pfunc)(bufp, firstline, m, mci, e);
1088 /* decode the reply code */
1091 /* extra semantics: 0xx codes are "informational" */
1095 /* if no continuation lines, return this line */
1099 /* first line of real reply -- ignore rest */
1104 ** Now look at SmtpReplyBuffer -- only care about the first
1105 ** line of the response from here on out.
1108 /* save temporary failure messages for posterity */
1109 if (SmtpReplyBuffer[0] == '4' &&
1110 (bitnset(M_LMTP, m->m_flags) || SmtpError[0] == '\0'))
1111 snprintf(SmtpError, sizeof SmtpError, "%s", SmtpReplyBuffer);
1113 /* reply code 421 is "Service Shutting Down" */
1114 if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
1116 /* send the quit protocol */
1117 mci->mci_state = MCIS_SSD;
1118 smtpquit(m, mci, e);
1124 ** SMTPMESSAGE -- send message to server
1128 ** m -- the mailer to control formatting.
1129 ** a, b, c -- parameters
1135 ** writes message to mci->mci_out.
1141 smtpmessage(char *f, MAILER *m, MCI *mci, ...)
1143 smtpmessage(f, m, mci, va_alist)
1153 (void) vsnprintf(SmtpMsgBuffer, sizeof SmtpMsgBuffer, f, ap);
1156 if (tTd(18, 1) || Verbose)
1157 nmessage(">>> %s", SmtpMsgBuffer);
1158 if (TrafficLogFile != NULL)
1159 fprintf(TrafficLogFile, "%05d >>> %s\n",
1160 (int) getpid(), SmtpMsgBuffer);
1161 if (mci->mci_out != NULL)
1163 fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
1164 m == NULL ? "\r\n" : m->m_eol);
1166 else if (tTd(18, 1))
1168 printf("smtpmessage: NULL mci_out\n");