122716Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333731Sbostic * Copyright (c) 1988 Regents of the University of California. 433731Sbostic * All rights reserved. 533731Sbostic * 642831Sbostic * %sccs.include.redist.c% 733731Sbostic */ 822716Sdist 933731Sbostic # include "sendmail.h" 1022716Sdist 1133731Sbostic #ifndef lint 1233731Sbostic #ifdef SMTP 13*58008Seric static char sccsid[] = "@(#)usersmtp.c 6.7 (Berkeley) 02/15/93 (with SMTP)"; 1433731Sbostic #else 15*58008Seric static char sccsid[] = "@(#)usersmtp.c 6.7 (Berkeley) 02/15/93 (without SMTP)"; 1633731Sbostic #endif 1733731Sbostic #endif /* not lint */ 1833731Sbostic 194684Seric # include <sysexits.h> 2021065Seric # include <errno.h> 214684Seric 2233731Sbostic # ifdef SMTP 234684Seric 244684Seric /* 259391Seric ** USERSMTP -- run SMTP protocol from the user end. 269391Seric ** 279391Seric ** This protocol is described in RFC821. 289391Seric */ 299391Seric 309391Seric #define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */ 319391Seric #define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */ 329391Seric #define SMTPCLOSING 421 /* "Service Shutting Down" */ 339391Seric 3414900Seric char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */ 3510054Seric char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */ 3621065Seric char SmtpError[MAXLINE] = ""; /* save failure error messages */ 3710054Seric int SmtpPid; /* pid of mailer */ 389391Seric /* 394865Seric ** SMTPINIT -- initialize SMTP. 404684Seric ** 414865Seric ** Opens the connection and sends the initial protocol. 424684Seric ** 434684Seric ** Parameters: 444865Seric ** m -- mailer to create connection to. 454865Seric ** pvp -- pointer to parameter vector to pass to 464865Seric ** the mailer. 474684Seric ** 484684Seric ** Returns: 4954967Seric ** none. 504684Seric ** 514684Seric ** Side Effects: 524865Seric ** creates connection and sends initial protocol. 534684Seric */ 544684Seric 5554967Seric smtpinit(m, mci, e) 564865Seric struct mailer *m; 5754967Seric register MCI *mci; 5853751Seric ENVELOPE *e; 594684Seric { 604865Seric register int r; 6114886Seric EVENT *gte; 6252107Seric extern STAB *stab(); 634684Seric 6457379Seric if (tTd(17, 1)) 6557379Seric { 6657379Seric printf("smtpinit "); 6757379Seric mci_dump(mci); 6857379Seric } 6957379Seric 704865Seric /* 714865Seric ** Open the connection to the mailer. 724865Seric */ 734684Seric 7421065Seric SmtpError[0] = '\0'; 7557379Seric CurHostName = mci->mci_host; /* XXX UGLY XXX */ 7654967Seric switch (mci->mci_state) 776051Seric { 7854967Seric case MCIS_ACTIVE: 7954967Seric /* need to clear old information */ 8054967Seric smtprset(m, mci, e); 8157734Seric /* fall through */ 8215139Seric 8354967Seric case MCIS_OPEN: 8454967Seric return; 8554967Seric 8654967Seric case MCIS_ERROR: 8754967Seric case MCIS_SSD: 8854967Seric /* shouldn't happen */ 8954967Seric smtpquit(m, mci, e); 9057734Seric /* fall through */ 9154967Seric 9254967Seric case MCIS_CLOSED: 9354967Seric syserr("smtpinit: state CLOSED"); 9454967Seric return; 9554967Seric 9654967Seric case MCIS_OPENING: 9754967Seric break; 986051Seric } 994796Seric 10057379Seric SmtpPhase = mci->mci_phase = "user open"; 10154967Seric mci->mci_state = MCIS_OPENING; 10254967Seric 1034865Seric /* 1044865Seric ** Get the greeting message. 10514913Seric ** This should appear spontaneously. Give it five minutes to 10614886Seric ** happen. 1074865Seric */ 1084797Seric 10957379Seric SmtpPhase = mci->mci_phase = "greeting wait"; 11053751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 11157379Seric r = reply(m, mci, e, (time_t) 300); 1128005Seric if (r < 0 || REPLYTYPE(r) != 2) 11352104Seric goto tempfail1; 1144684Seric 1154865Seric /* 1164976Seric ** Send the HELO command. 1177963Seric ** My mother taught me to always introduce myself. 1184976Seric */ 1194976Seric 12053751Seric smtpmessage("HELO %s", m, mci, MyHostName); 12157379Seric SmtpPhase = mci->mci_phase = "HELO wait"; 12253751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 12357379Seric r = reply(m, mci, e, ReadTimeout); 1248005Seric if (r < 0) 12552104Seric goto tempfail1; 1268005Seric else if (REPLYTYPE(r) == 5) 12714913Seric goto unavailable; 1287963Seric else if (REPLYTYPE(r) != 2) 12952104Seric goto tempfail1; 1304976Seric 1314976Seric /* 1329315Seric ** If this is expected to be another sendmail, send some internal 1339315Seric ** commands. 1349315Seric */ 1359315Seric 13610688Seric if (bitnset(M_INTERNAL, m->m_flags)) 1379315Seric { 1389315Seric /* tell it to be verbose */ 13953751Seric smtpmessage("VERB", m, mci); 14057379Seric r = reply(m, mci, e, ReadTimeout); 1419315Seric if (r < 0) 14252104Seric goto tempfail2; 1439315Seric } 1449315Seric 14553751Seric mci->mci_state = MCIS_OPEN; 14654967Seric return; 14753751Seric 14853751Seric tempfail1: 14953751Seric tempfail2: 15053751Seric mci->mci_exitstat = EX_TEMPFAIL; 15157379Seric if (mci->mci_errno == 0) 15257379Seric mci->mci_errno = errno; 15357379Seric if (mci->mci_state != MCIS_CLOSED) 15457379Seric smtpquit(m, mci, e); 15554967Seric return; 15653751Seric 15753751Seric unavailable: 15853751Seric mci->mci_exitstat = EX_UNAVAILABLE; 15953751Seric mci->mci_errno = errno; 16053751Seric smtpquit(m, mci, e); 16154967Seric return; 16253751Seric } 16353751Seric 16453751Seric smtpmailfrom(m, mci, e) 16553751Seric struct mailer *m; 16654967Seric MCI *mci; 16753751Seric ENVELOPE *e; 16853751Seric { 16953751Seric int r; 17053751Seric char buf[MAXNAME]; 17153751Seric 17257943Seric if (tTd(17, 2)) 17357943Seric printf("smtpmailfrom: CurHost=%s\n", CurHostName); 17457943Seric 1759315Seric /* 1764865Seric ** Send the MAIL command. 1774865Seric ** Designates the sender. 1784865Seric */ 1794796Seric 18053751Seric mci->mci_state = MCIS_ACTIVE; 18153751Seric 18253751Seric expand("\001<", buf, &buf[sizeof buf - 1], e); 18353751Seric if (e->e_from.q_mailer == LocalMailer || 18410688Seric !bitnset(M_FROMPATH, m->m_flags)) 1858436Seric { 18653751Seric smtpmessage("MAIL From:<%s>", m, mci, buf); 1878436Seric } 1888436Seric else 1898436Seric { 19053751Seric smtpmessage("MAIL From:<@%s%c%s>", m, mci, MyHostName, 19110308Seric buf[0] == '@' ? ',' : ':', buf); 1928436Seric } 19357379Seric SmtpPhase = mci->mci_phase = "MAIL wait"; 19453751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 19557379Seric r = reply(m, mci, e, ReadTimeout); 1968005Seric if (r < 0 || REPLYTYPE(r) == 4) 19753751Seric { 19853751Seric mci->mci_exitstat = EX_TEMPFAIL; 19953751Seric mci->mci_errno = errno; 20053751Seric smtpquit(m, mci, e); 20153751Seric return EX_TEMPFAIL; 20253751Seric } 2037963Seric else if (r == 250) 20453751Seric { 20553751Seric mci->mci_exitstat = EX_OK; 20653751Seric return EX_OK; 20753751Seric } 2087963Seric else if (r == 552) 20953751Seric { 21053751Seric /* signal service unavailable */ 21153751Seric mci->mci_exitstat = EX_UNAVAILABLE; 21253751Seric smtpquit(m, mci, e); 21353751Seric return EX_UNAVAILABLE; 21453751Seric } 21514913Seric 216*58008Seric #ifdef LOG 217*58008Seric if (LogLevel >= 4) 218*58008Seric { 219*58008Seric syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s", 220*58008Seric e->e_id, SmtpReplyBuffer); 221*58008Seric } 222*58008Seric #endif 223*58008Seric 22414913Seric /* protocol error -- close up */ 22553751Seric smtpquit(m, mci, e); 22653751Seric mci->mci_exitstat = EX_PROTOCOL; 22753751Seric return EX_PROTOCOL; 2284684Seric } 2294684Seric /* 2304976Seric ** SMTPRCPT -- designate recipient. 2314797Seric ** 2324797Seric ** Parameters: 2334865Seric ** to -- address of recipient. 23410175Seric ** m -- the mailer we are sending to. 23557379Seric ** mci -- the connection info for this transaction. 23657379Seric ** e -- the envelope for this transaction. 2374797Seric ** 2384797Seric ** Returns: 2394865Seric ** exit status corresponding to recipient status. 2404797Seric ** 2414797Seric ** Side Effects: 2424865Seric ** Sends the mail via SMTP. 2434797Seric */ 2444797Seric 24553751Seric smtprcpt(to, m, mci, e) 2464865Seric ADDRESS *to; 24710175Seric register MAILER *m; 24854967Seric MCI *mci; 24953751Seric ENVELOPE *e; 2504797Seric { 2514797Seric register int r; 2524797Seric 25353751Seric smtpmessage("RCPT To:<%s>", m, mci, to->q_user); 2544865Seric 25557379Seric SmtpPhase = mci->mci_phase = "RCPT wait"; 25653751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 25757379Seric r = reply(m, mci, e, ReadTimeout); 2588005Seric if (r < 0 || REPLYTYPE(r) == 4) 2594865Seric return (EX_TEMPFAIL); 2607963Seric else if (REPLYTYPE(r) == 2) 2617963Seric return (EX_OK); 2627964Seric else if (r == 550 || r == 551 || r == 553) 2637964Seric return (EX_NOUSER); 2647964Seric else if (r == 552 || r == 554) 2657964Seric return (EX_UNAVAILABLE); 266*58008Seric 267*58008Seric #ifdef LOG 268*58008Seric if (LogLevel >= 4) 269*58008Seric { 270*58008Seric syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s", 271*58008Seric e->e_id, SmtpReplyBuffer); 272*58008Seric } 273*58008Seric #endif 274*58008Seric 2757964Seric return (EX_PROTOCOL); 2764797Seric } 2774797Seric /* 27810175Seric ** SMTPDATA -- send the data and clean up the transaction. 2794684Seric ** 2804684Seric ** Parameters: 2814865Seric ** m -- mailer being sent to. 2826980Seric ** e -- the envelope for this message. 2834684Seric ** 2844684Seric ** Returns: 2854976Seric ** exit status corresponding to DATA command. 2864684Seric ** 2874684Seric ** Side Effects: 2884865Seric ** none. 2894684Seric */ 2904684Seric 29153740Seric smtpdata(m, mci, e) 2924865Seric struct mailer *m; 29354967Seric register MCI *mci; 2946980Seric register ENVELOPE *e; 2954684Seric { 2964684Seric register int r; 2974684Seric 2984797Seric /* 2994797Seric ** Send the data. 30010175Seric ** First send the command and check that it is ok. 30110175Seric ** Then send the data. 30210175Seric ** Follow it up with a dot to terminate. 30310175Seric ** Finally get the results of the transaction. 3044797Seric */ 3054797Seric 30610175Seric /* send the command and check ok to proceed */ 30753751Seric smtpmessage("DATA", m, mci); 30857379Seric SmtpPhase = mci->mci_phase = "DATA wait"; 30953751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 31057379Seric r = reply(m, mci, e, ReadTimeout); 3118005Seric if (r < 0 || REPLYTYPE(r) == 4) 31257990Seric { 31357990Seric smtpquit(m, mci, e); 3144797Seric return (EX_TEMPFAIL); 31557990Seric } 3167963Seric else if (r == 554) 31757990Seric { 31857990Seric smtprset(m, mci, e); 3197963Seric return (EX_UNAVAILABLE); 32057990Seric } 3217963Seric else if (r != 354) 32257990Seric { 323*58008Seric #ifdef LOG 324*58008Seric if (LogLevel >= 4) 325*58008Seric { 326*58008Seric syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s", 327*58008Seric e->e_id, SmtpReplyBuffer); 328*58008Seric } 329*58008Seric #endif 33057990Seric smtprset(m, mci, e); 3317964Seric return (EX_PROTOCOL); 33257990Seric } 33310175Seric 33410175Seric /* now output the actual message */ 33553751Seric (*e->e_puthdr)(mci->mci_out, m, e); 33653740Seric putline("\n", mci->mci_out, m); 33753751Seric (*e->e_putbody)(mci->mci_out, m, e); 33810175Seric 33910175Seric /* terminate the message */ 34053740Seric fprintf(mci->mci_out, ".%s", m->m_eol); 34110215Seric if (Verbose && !HoldErrs) 34210215Seric nmessage(Arpa_Info, ">>> ."); 34310175Seric 34410175Seric /* check for the results of the transaction */ 34557379Seric SmtpPhase = mci->mci_phase = "result wait"; 34653751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 34757379Seric r = reply(m, mci, e, ReadTimeout); 34853751Seric if (r < 0) 34957990Seric { 35057990Seric smtpquit(m, mci, e); 3514797Seric return (EX_TEMPFAIL); 35257990Seric } 35353751Seric mci->mci_state = MCIS_OPEN; 35453751Seric if (REPLYTYPE(r) == 4) 35553751Seric return (EX_TEMPFAIL); 3567963Seric else if (r == 250) 3577963Seric return (EX_OK); 3587963Seric else if (r == 552 || r == 554) 3597963Seric return (EX_UNAVAILABLE); 360*58008Seric #ifdef LOG 361*58008Seric if (LogLevel >= 4) 362*58008Seric { 363*58008Seric syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s", 364*58008Seric e->e_id, SmtpReplyBuffer); 365*58008Seric } 366*58008Seric #endif 3677964Seric return (EX_PROTOCOL); 3684684Seric } 3694684Seric /* 3704865Seric ** SMTPQUIT -- close the SMTP connection. 3714865Seric ** 3724865Seric ** Parameters: 37315535Seric ** m -- a pointer to the mailer. 3744865Seric ** 3754865Seric ** Returns: 3764865Seric ** none. 3774865Seric ** 3784865Seric ** Side Effects: 3794865Seric ** sends the final protocol and closes the connection. 3804865Seric */ 3814865Seric 38253751Seric smtpquit(m, mci, e) 38353751Seric register MAILER *m; 38454967Seric register MCI *mci; 38553751Seric ENVELOPE *e; 3864865Seric { 3879391Seric int i; 3884865Seric 38954967Seric /* send the quit message if we haven't gotten I/O error */ 39053751Seric if (mci->mci_state != MCIS_ERROR) 3919391Seric { 39253751Seric smtpmessage("QUIT", m, mci); 39357379Seric (void) reply(m, mci, e, ReadTimeout); 39453740Seric if (mci->mci_state == MCIS_CLOSED) 39510159Seric return; 3969391Seric } 3979391Seric 39852676Seric /* now actually close the connection and pick up the zombie */ 39952676Seric i = endmailer(mci, m->m_argv[0]); 4009391Seric if (i != EX_OK) 40115535Seric syserr("smtpquit %s: stat %d", m->m_argv[0], i); 4024865Seric } 4034865Seric /* 40454967Seric ** SMTPRSET -- send a RSET (reset) command 40554967Seric */ 40654967Seric 40754967Seric smtprset(m, mci, e) 40854967Seric register MAILER *m; 40954967Seric register MCI *mci; 41054967Seric ENVELOPE *e; 41154967Seric { 41254967Seric int r; 41354967Seric 41454967Seric smtpmessage("RSET", m, mci); 41557734Seric r = reply(m, mci, e, (time_t) 300); 41657734Seric if (r < 0) 41757734Seric mci->mci_state = MCIS_ERROR; 41854967Seric else if (REPLYTYPE(r) == 2) 41957734Seric { 42057734Seric mci->mci_state = MCIS_OPEN; 42157734Seric return; 42257734Seric } 42357734Seric smtpquit(m, mci, e); 42454967Seric } 42554967Seric /* 42654967Seric ** SMTPNOOP -- send a NOOP (no operation) command to check the connection state 42754967Seric */ 42854967Seric 42954967Seric smtpnoop(mci) 43054967Seric register MCI *mci; 43154967Seric { 43254967Seric int r; 43354967Seric MAILER *m = mci->mci_mailer; 43454967Seric extern ENVELOPE BlankEnvelope; 43554967Seric ENVELOPE *e = &BlankEnvelope; 43654967Seric 43754967Seric smtpmessage("NOOP", m, mci); 43857379Seric r = reply(m, mci, e, ReadTimeout); 43954967Seric if (REPLYTYPE(r) != 2) 44054967Seric smtpquit(m, mci, e); 44154967Seric return r; 44254967Seric } 44354967Seric /* 4444684Seric ** REPLY -- read arpanet reply 4454684Seric ** 4464684Seric ** Parameters: 44710175Seric ** m -- the mailer we are reading the reply from. 44857379Seric ** mci -- the mailer connection info structure. 44957379Seric ** e -- the current envelope. 45057379Seric ** timeout -- the timeout for reads. 4514684Seric ** 4524684Seric ** Returns: 4534684Seric ** reply code it reads. 4544684Seric ** 4554684Seric ** Side Effects: 4564684Seric ** flushes the mail file. 4574684Seric */ 4584684Seric 45957379Seric reply(m, mci, e, timeout) 46053751Seric MAILER *m; 46154967Seric MCI *mci; 46253751Seric ENVELOPE *e; 4634684Seric { 46457379Seric if (mci->mci_out != NULL) 46557379Seric (void) fflush(mci->mci_out); 4664684Seric 4677677Seric if (tTd(18, 1)) 4684796Seric printf("reply\n"); 4694796Seric 4707356Seric /* 4717356Seric ** Read the input line, being careful not to hang. 4727356Seric */ 4737356Seric 4744684Seric for (;;) 4754684Seric { 4764684Seric register int r; 4777356Seric register char *p; 47853751Seric extern time_t curtime(); 4794684Seric 4807685Seric /* actually do the read */ 48153751Seric if (e->e_xfp != NULL) 48253751Seric (void) fflush(e->e_xfp); /* for debugging */ 4837356Seric 48410054Seric /* if we are in the process of closing just give the code */ 48553740Seric if (mci->mci_state == MCIS_CLOSED) 48610054Seric return (SMTPCLOSING); 48710054Seric 48810054Seric /* get the line from the other side */ 48957379Seric p = sfgets(SmtpReplyBuffer, sizeof SmtpReplyBuffer, mci->mci_in, 49057379Seric timeout); 49153751Seric mci->mci_lastuse = curtime(); 49253751Seric 49310054Seric if (p == NULL) 49410131Seric { 49510148Seric extern char MsgBuf[]; /* err.c */ 49610148Seric extern char Arpa_TSyserr[]; /* conf.c */ 49710148Seric 49821065Seric /* if the remote end closed early, fake an error */ 49921065Seric if (errno == 0) 50021065Seric # ifdef ECONNRESET 50121065Seric errno = ECONNRESET; 50256795Seric # else /* ECONNRESET */ 50321065Seric errno = EPIPE; 50456795Seric # endif /* ECONNRESET */ 50521065Seric 50657379Seric mci->mci_errno = errno; 50757642Seric mci->mci_exitstat = EX_TEMPFAIL; 50857642Seric message(Arpa_TSyserr, "%s: reply: read error from %s", 50957642Seric e->e_id == NULL ? "NOQUEUE" : e->e_id, 51057203Seric mci->mci_host); 51110420Seric /* if debugging, pause so we can see state */ 51210420Seric if (tTd(18, 100)) 51310420Seric pause(); 51410148Seric # ifdef LOG 51557203Seric if (LogLevel > 0) 51657203Seric syslog(LOG_INFO, "%s", &MsgBuf[4]); 51756795Seric # endif /* LOG */ 51854967Seric mci->mci_state = MCIS_ERROR; 51953751Seric smtpquit(m, mci, e); 52010054Seric return (-1); 52110131Seric } 52210054Seric fixcrlf(SmtpReplyBuffer, TRUE); 52310054Seric 52456795Seric if (e->e_xfp != NULL && strchr("45", SmtpReplyBuffer[0]) != NULL) 52514900Seric { 52614900Seric /* serious error -- log the previous command */ 52714900Seric if (SmtpMsgBuffer[0] != '\0') 52853751Seric fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer); 52914900Seric SmtpMsgBuffer[0] = '\0'; 53014900Seric 53114900Seric /* now log the message as from the other side */ 53253751Seric fprintf(e->e_xfp, "<<< %s\n", SmtpReplyBuffer); 53314900Seric } 53414900Seric 53514900Seric /* display the input for verbose mode */ 5367229Seric if (Verbose && !HoldErrs) 5379391Seric nmessage(Arpa_Info, "%s", SmtpReplyBuffer); 5387356Seric 5397356Seric /* if continuation is required, we can go on */ 5409391Seric if (SmtpReplyBuffer[3] == '-' || !isdigit(SmtpReplyBuffer[0])) 5414684Seric continue; 5427356Seric 5437356Seric /* decode the reply code */ 5449391Seric r = atoi(SmtpReplyBuffer); 5457356Seric 5467356Seric /* extra semantics: 0xx codes are "informational" */ 5474684Seric if (r < 100) 5484684Seric continue; 5497356Seric 5509391Seric /* reply code 421 is "Service Shutting Down" */ 55153740Seric if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD) 5529391Seric { 55310054Seric /* send the quit protocol */ 55453740Seric mci->mci_state = MCIS_SSD; 55553751Seric smtpquit(m, mci, e); 5569391Seric } 5579391Seric 55821065Seric /* save temporary failure messages for posterity */ 55921065Seric if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0') 56021065Seric (void) strcpy(SmtpError, &SmtpReplyBuffer[4]); 56121065Seric 5624684Seric return (r); 5634684Seric } 5644684Seric } 5654796Seric /* 5664865Seric ** SMTPMESSAGE -- send message to server 5674796Seric ** 5684796Seric ** Parameters: 5694796Seric ** f -- format 57010175Seric ** m -- the mailer to control formatting. 5714796Seric ** a, b, c -- parameters 5724796Seric ** 5734796Seric ** Returns: 5744796Seric ** none. 5754796Seric ** 5764796Seric ** Side Effects: 57753740Seric ** writes message to mci->mci_out. 5784796Seric */ 5794796Seric 5804865Seric /*VARARGS1*/ 58157642Seric #ifdef __STDC__ 58257642Seric smtpmessage(char *f, MAILER *m, MCI *mci, ...) 58357642Seric #else 58457642Seric smtpmessage(f, m, mci, va_alist) 5854796Seric char *f; 58610175Seric MAILER *m; 58754967Seric MCI *mci; 58857642Seric va_dcl 58957642Seric #endif 5904796Seric { 59156852Seric VA_LOCAL_DECL 59256852Seric 59357135Seric VA_START(mci); 59456852Seric (void) vsprintf(SmtpMsgBuffer, f, ap); 59556852Seric VA_END; 5967677Seric if (tTd(18, 1) || (Verbose && !HoldErrs)) 59714900Seric nmessage(Arpa_Info, ">>> %s", SmtpMsgBuffer); 59853740Seric if (mci->mci_out != NULL) 59953740Seric fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer, 60054967Seric m == NULL ? "\r\n" : m->m_eol); 6014796Seric } 6025182Seric 60356795Seric # endif /* SMTP */ 604