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*58957Seric static char sccsid[] = "@(#)usersmtp.c 6.22 (Berkeley) 04/04/93 (with SMTP)"; 1433731Sbostic #else 15*58957Seric static char sccsid[] = "@(#)usersmtp.c 6.22 (Berkeley) 04/04/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 */ 3858671Seric 3958671Seric #ifdef __STDC__ 4058671Seric extern smtpmessage(char *f, MAILER *m, MCI *mci, ...); 4158671Seric #endif 429391Seric /* 434865Seric ** SMTPINIT -- initialize SMTP. 444684Seric ** 454865Seric ** Opens the connection and sends the initial protocol. 464684Seric ** 474684Seric ** Parameters: 484865Seric ** m -- mailer to create connection to. 494865Seric ** pvp -- pointer to parameter vector to pass to 504865Seric ** the mailer. 514684Seric ** 524684Seric ** Returns: 5354967Seric ** none. 544684Seric ** 554684Seric ** Side Effects: 564865Seric ** creates connection and sends initial protocol. 574684Seric */ 584684Seric 5954967Seric smtpinit(m, mci, e) 604865Seric struct mailer *m; 6154967Seric register MCI *mci; 6253751Seric ENVELOPE *e; 634684Seric { 644865Seric register int r; 65*58957Seric register char *p; 6652107Seric extern STAB *stab(); 674684Seric 6857379Seric if (tTd(17, 1)) 6957379Seric { 7057379Seric printf("smtpinit "); 7157379Seric mci_dump(mci); 7257379Seric } 7357379Seric 744865Seric /* 754865Seric ** Open the connection to the mailer. 764865Seric */ 774684Seric 7821065Seric SmtpError[0] = '\0'; 7957379Seric CurHostName = mci->mci_host; /* XXX UGLY XXX */ 8054967Seric switch (mci->mci_state) 816051Seric { 8254967Seric case MCIS_ACTIVE: 8354967Seric /* need to clear old information */ 8454967Seric smtprset(m, mci, e); 8557734Seric /* fall through */ 8615139Seric 8754967Seric case MCIS_OPEN: 8854967Seric return; 8954967Seric 9054967Seric case MCIS_ERROR: 9154967Seric case MCIS_SSD: 9254967Seric /* shouldn't happen */ 9354967Seric smtpquit(m, mci, e); 9457734Seric /* fall through */ 9554967Seric 9654967Seric case MCIS_CLOSED: 9758151Seric syserr("451 smtpinit: state CLOSED"); 9854967Seric return; 9954967Seric 10054967Seric case MCIS_OPENING: 10154967Seric break; 1026051Seric } 1034796Seric 10457379Seric SmtpPhase = mci->mci_phase = "user open"; 10554967Seric mci->mci_state = MCIS_OPENING; 10654967Seric 1074865Seric /* 1084865Seric ** Get the greeting message. 10914913Seric ** This should appear spontaneously. Give it five minutes to 11014886Seric ** happen. 1114865Seric */ 1124797Seric 11357379Seric SmtpPhase = mci->mci_phase = "greeting wait"; 11453751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 11558112Seric r = reply(m, mci, e, TimeOuts.to_initial); 1168005Seric if (r < 0 || REPLYTYPE(r) != 2) 11752104Seric goto tempfail1; 1184684Seric 1194865Seric /* 1204976Seric ** Send the HELO command. 1217963Seric ** My mother taught me to always introduce myself. 1224976Seric */ 1234976Seric 12453751Seric smtpmessage("HELO %s", m, mci, MyHostName); 12557379Seric SmtpPhase = mci->mci_phase = "HELO wait"; 12653751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 12758112Seric r = reply(m, mci, e, TimeOuts.to_helo); 1288005Seric if (r < 0) 12952104Seric goto tempfail1; 1308005Seric else if (REPLYTYPE(r) == 5) 13114913Seric goto unavailable; 1327963Seric else if (REPLYTYPE(r) != 2) 13352104Seric goto tempfail1; 1344976Seric 1354976Seric /* 136*58957Seric ** Check to see if we actually ended up talking to ourself. 137*58957Seric ** This means we didn't know about an alias or MX, or we managed 138*58957Seric ** to connect to an echo server. 139*58957Seric */ 140*58957Seric 141*58957Seric p = strchr(SmtpReplyBuffer, ' '); 142*58957Seric if (p != NULL) 143*58957Seric *p == '\0'; 144*58957Seric if (strcasecmp(SmtpReplyBuffer, MyHostName) == 0) 145*58957Seric { 146*58957Seric syserr("553 %s config error: mail loops back to myself", 147*58957Seric MyHostName); 148*58957Seric mci->mci_exitstat = EX_CONFIG; 149*58957Seric mci->mci_errno = 0; 150*58957Seric smtpquit(m, mci, e); 151*58957Seric return; 152*58957Seric } 153*58957Seric 154*58957Seric /* 1559315Seric ** If this is expected to be another sendmail, send some internal 1569315Seric ** commands. 1579315Seric */ 1589315Seric 15910688Seric if (bitnset(M_INTERNAL, m->m_flags)) 1609315Seric { 1619315Seric /* tell it to be verbose */ 16253751Seric smtpmessage("VERB", m, mci); 16358112Seric r = reply(m, mci, e, TimeOuts.to_miscshort); 1649315Seric if (r < 0) 16552104Seric goto tempfail2; 1669315Seric } 1679315Seric 16853751Seric mci->mci_state = MCIS_OPEN; 16954967Seric return; 17053751Seric 17153751Seric tempfail1: 17253751Seric tempfail2: 17353751Seric mci->mci_exitstat = EX_TEMPFAIL; 17457379Seric if (mci->mci_errno == 0) 17557379Seric mci->mci_errno = errno; 17657379Seric if (mci->mci_state != MCIS_CLOSED) 17757379Seric smtpquit(m, mci, e); 17854967Seric return; 17953751Seric 18053751Seric unavailable: 18153751Seric mci->mci_exitstat = EX_UNAVAILABLE; 18253751Seric mci->mci_errno = errno; 18353751Seric smtpquit(m, mci, e); 18454967Seric return; 18553751Seric } 18653751Seric 18753751Seric smtpmailfrom(m, mci, e) 18853751Seric struct mailer *m; 18954967Seric MCI *mci; 19053751Seric ENVELOPE *e; 19153751Seric { 19253751Seric int r; 19353751Seric char buf[MAXNAME]; 19453751Seric 19557943Seric if (tTd(17, 2)) 19657943Seric printf("smtpmailfrom: CurHost=%s\n", CurHostName); 19757943Seric 1989315Seric /* 1994865Seric ** Send the MAIL command. 2004865Seric ** Designates the sender. 2014865Seric */ 2024796Seric 20353751Seric mci->mci_state = MCIS_ACTIVE; 20453751Seric 20558680Seric if (bitset(EF_RESPONSE, e->e_flags)) 20658680Seric (void) strcpy(buf, ""); 20758680Seric else 20858680Seric expand("\201g", buf, &buf[sizeof buf - 1], e); 20953751Seric if (e->e_from.q_mailer == LocalMailer || 21010688Seric !bitnset(M_FROMPATH, m->m_flags)) 2118436Seric { 21253751Seric smtpmessage("MAIL From:<%s>", m, mci, buf); 2138436Seric } 2148436Seric else 2158436Seric { 21653751Seric smtpmessage("MAIL From:<@%s%c%s>", m, mci, MyHostName, 21710308Seric buf[0] == '@' ? ',' : ':', buf); 2188436Seric } 21957379Seric SmtpPhase = mci->mci_phase = "MAIL wait"; 22053751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 22158112Seric r = reply(m, mci, e, TimeOuts.to_mail); 2228005Seric if (r < 0 || REPLYTYPE(r) == 4) 22353751Seric { 22453751Seric mci->mci_exitstat = EX_TEMPFAIL; 22553751Seric mci->mci_errno = errno; 22653751Seric smtpquit(m, mci, e); 22753751Seric return EX_TEMPFAIL; 22853751Seric } 2297963Seric else if (r == 250) 23053751Seric { 23153751Seric mci->mci_exitstat = EX_OK; 23253751Seric return EX_OK; 23353751Seric } 2347963Seric else if (r == 552) 23553751Seric { 23653751Seric /* signal service unavailable */ 23753751Seric mci->mci_exitstat = EX_UNAVAILABLE; 23853751Seric smtpquit(m, mci, e); 23953751Seric return EX_UNAVAILABLE; 24053751Seric } 24114913Seric 24258008Seric #ifdef LOG 24358020Seric if (LogLevel > 1) 24458008Seric { 24558008Seric syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s", 24658008Seric e->e_id, SmtpReplyBuffer); 24758008Seric } 24858008Seric #endif 24958008Seric 25014913Seric /* protocol error -- close up */ 25153751Seric smtpquit(m, mci, e); 25253751Seric mci->mci_exitstat = EX_PROTOCOL; 25353751Seric return EX_PROTOCOL; 2544684Seric } 2554684Seric /* 2564976Seric ** SMTPRCPT -- designate recipient. 2574797Seric ** 2584797Seric ** Parameters: 2594865Seric ** to -- address of recipient. 26010175Seric ** m -- the mailer we are sending to. 26157379Seric ** mci -- the connection info for this transaction. 26257379Seric ** e -- the envelope for this transaction. 2634797Seric ** 2644797Seric ** Returns: 2654865Seric ** exit status corresponding to recipient status. 2664797Seric ** 2674797Seric ** Side Effects: 2684865Seric ** Sends the mail via SMTP. 2694797Seric */ 2704797Seric 27153751Seric smtprcpt(to, m, mci, e) 2724865Seric ADDRESS *to; 27310175Seric register MAILER *m; 27454967Seric MCI *mci; 27553751Seric ENVELOPE *e; 2764797Seric { 2774797Seric register int r; 2784797Seric 27953751Seric smtpmessage("RCPT To:<%s>", m, mci, to->q_user); 2804865Seric 28157379Seric SmtpPhase = mci->mci_phase = "RCPT wait"; 28253751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 28358112Seric r = reply(m, mci, e, TimeOuts.to_rcpt); 2848005Seric if (r < 0 || REPLYTYPE(r) == 4) 2854865Seric return (EX_TEMPFAIL); 2867963Seric else if (REPLYTYPE(r) == 2) 2877963Seric return (EX_OK); 2887964Seric else if (r == 550 || r == 551 || r == 553) 2897964Seric return (EX_NOUSER); 2907964Seric else if (r == 552 || r == 554) 2917964Seric return (EX_UNAVAILABLE); 29258008Seric 29358008Seric #ifdef LOG 29458020Seric if (LogLevel > 1) 29558008Seric { 29658008Seric syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s", 29758008Seric e->e_id, SmtpReplyBuffer); 29858008Seric } 29958008Seric #endif 30058008Seric 3017964Seric return (EX_PROTOCOL); 3024797Seric } 3034797Seric /* 30410175Seric ** SMTPDATA -- send the data and clean up the transaction. 3054684Seric ** 3064684Seric ** Parameters: 3074865Seric ** m -- mailer being sent to. 3086980Seric ** e -- the envelope for this message. 3094684Seric ** 3104684Seric ** Returns: 3114976Seric ** exit status corresponding to DATA command. 3124684Seric ** 3134684Seric ** Side Effects: 3144865Seric ** none. 3154684Seric */ 3164684Seric 31753740Seric smtpdata(m, mci, e) 3184865Seric struct mailer *m; 31954967Seric register MCI *mci; 3206980Seric register ENVELOPE *e; 3214684Seric { 3224684Seric register int r; 3234684Seric 3244797Seric /* 3254797Seric ** Send the data. 32610175Seric ** First send the command and check that it is ok. 32710175Seric ** Then send the data. 32810175Seric ** Follow it up with a dot to terminate. 32910175Seric ** Finally get the results of the transaction. 3304797Seric */ 3314797Seric 33210175Seric /* send the command and check ok to proceed */ 33353751Seric smtpmessage("DATA", m, mci); 33457379Seric SmtpPhase = mci->mci_phase = "DATA wait"; 33553751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 33658112Seric r = reply(m, mci, e, TimeOuts.to_datainit); 3378005Seric if (r < 0 || REPLYTYPE(r) == 4) 33857990Seric { 33957990Seric smtpquit(m, mci, e); 3404797Seric return (EX_TEMPFAIL); 34157990Seric } 3427963Seric else if (r == 554) 34357990Seric { 34457990Seric smtprset(m, mci, e); 3457963Seric return (EX_UNAVAILABLE); 34657990Seric } 3477963Seric else if (r != 354) 34857990Seric { 34958008Seric #ifdef LOG 35058020Seric if (LogLevel > 1) 35158008Seric { 35258008Seric syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s", 35358008Seric e->e_id, SmtpReplyBuffer); 35458008Seric } 35558008Seric #endif 35657990Seric smtprset(m, mci, e); 3577964Seric return (EX_PROTOCOL); 35857990Seric } 35910175Seric 36010175Seric /* now output the actual message */ 36153751Seric (*e->e_puthdr)(mci->mci_out, m, e); 36253740Seric putline("\n", mci->mci_out, m); 36353751Seric (*e->e_putbody)(mci->mci_out, m, e); 36410175Seric 36510175Seric /* terminate the message */ 36653740Seric fprintf(mci->mci_out, ".%s", m->m_eol); 36758120Seric if (Verbose) 36858151Seric nmessage(">>> ."); 36910175Seric 37010175Seric /* check for the results of the transaction */ 37157379Seric SmtpPhase = mci->mci_phase = "result wait"; 37253751Seric setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 37358112Seric r = reply(m, mci, e, TimeOuts.to_datafinal); 37453751Seric if (r < 0) 37557990Seric { 37657990Seric smtpquit(m, mci, e); 3774797Seric return (EX_TEMPFAIL); 37857990Seric } 37953751Seric mci->mci_state = MCIS_OPEN; 38058917Seric e->e_statmsg = newstr(&SmtpReplyBuffer[4]); 38153751Seric if (REPLYTYPE(r) == 4) 38253751Seric return (EX_TEMPFAIL); 3837963Seric else if (r == 250) 3847963Seric return (EX_OK); 3857963Seric else if (r == 552 || r == 554) 3867963Seric return (EX_UNAVAILABLE); 38758008Seric #ifdef LOG 38858020Seric if (LogLevel > 1) 38958008Seric { 39058008Seric syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s", 39158008Seric e->e_id, SmtpReplyBuffer); 39258008Seric } 39358008Seric #endif 3947964Seric return (EX_PROTOCOL); 3954684Seric } 3964684Seric /* 3974865Seric ** SMTPQUIT -- close the SMTP connection. 3984865Seric ** 3994865Seric ** Parameters: 40015535Seric ** m -- a pointer to the mailer. 4014865Seric ** 4024865Seric ** Returns: 4034865Seric ** none. 4044865Seric ** 4054865Seric ** Side Effects: 4064865Seric ** sends the final protocol and closes the connection. 4074865Seric */ 4084865Seric 40953751Seric smtpquit(m, mci, e) 41053751Seric register MAILER *m; 41154967Seric register MCI *mci; 41253751Seric ENVELOPE *e; 4134865Seric { 4149391Seric int i; 4154865Seric 41654967Seric /* send the quit message if we haven't gotten I/O error */ 41753751Seric if (mci->mci_state != MCIS_ERROR) 4189391Seric { 41953751Seric smtpmessage("QUIT", m, mci); 42058112Seric (void) reply(m, mci, e, TimeOuts.to_quit); 42153740Seric if (mci->mci_state == MCIS_CLOSED) 42210159Seric return; 4239391Seric } 4249391Seric 42552676Seric /* now actually close the connection and pick up the zombie */ 42658846Seric i = endmailer(mci, e, m->m_argv); 4279391Seric if (i != EX_OK) 42858151Seric syserr("451 smtpquit %s: stat %d", m->m_argv[0], i); 4294865Seric } 4304865Seric /* 43154967Seric ** SMTPRSET -- send a RSET (reset) command 43254967Seric */ 43354967Seric 43454967Seric smtprset(m, mci, e) 43554967Seric register MAILER *m; 43654967Seric register MCI *mci; 43754967Seric ENVELOPE *e; 43854967Seric { 43954967Seric int r; 44054967Seric 44154967Seric smtpmessage("RSET", m, mci); 44258112Seric r = reply(m, mci, e, TimeOuts.to_rset); 44357734Seric if (r < 0) 44457734Seric mci->mci_state = MCIS_ERROR; 44554967Seric else if (REPLYTYPE(r) == 2) 44657734Seric { 44757734Seric mci->mci_state = MCIS_OPEN; 44857734Seric return; 44957734Seric } 45057734Seric smtpquit(m, mci, e); 45154967Seric } 45254967Seric /* 45358867Seric ** SMTPPROBE -- check the connection state 45454967Seric */ 45554967Seric 45658867Seric smtpprobe(mci) 45754967Seric register MCI *mci; 45854967Seric { 45954967Seric int r; 46054967Seric MAILER *m = mci->mci_mailer; 46154967Seric extern ENVELOPE BlankEnvelope; 46254967Seric ENVELOPE *e = &BlankEnvelope; 46354967Seric 46458867Seric smtpmessage("RSET", m, mci); 46558112Seric r = reply(m, mci, e, TimeOuts.to_miscshort); 46658061Seric if (r < 0 || REPLYTYPE(r) != 2) 46754967Seric smtpquit(m, mci, e); 46854967Seric return r; 46954967Seric } 47054967Seric /* 4714684Seric ** REPLY -- read arpanet reply 4724684Seric ** 4734684Seric ** Parameters: 47410175Seric ** m -- the mailer we are reading the reply from. 47557379Seric ** mci -- the mailer connection info structure. 47657379Seric ** e -- the current envelope. 47757379Seric ** timeout -- the timeout for reads. 4784684Seric ** 4794684Seric ** Returns: 4804684Seric ** reply code it reads. 4814684Seric ** 4824684Seric ** Side Effects: 4834684Seric ** flushes the mail file. 4844684Seric */ 4854684Seric 48657379Seric reply(m, mci, e, timeout) 48753751Seric MAILER *m; 48854967Seric MCI *mci; 48953751Seric ENVELOPE *e; 4904684Seric { 491*58957Seric char *bufp = SmtpReplyBuffer; 492*58957Seric char junkbuf[MAXLINE]; 493*58957Seric 49457379Seric if (mci->mci_out != NULL) 49557379Seric (void) fflush(mci->mci_out); 4964684Seric 4977677Seric if (tTd(18, 1)) 4984796Seric printf("reply\n"); 4994796Seric 5007356Seric /* 5017356Seric ** Read the input line, being careful not to hang. 5027356Seric */ 5037356Seric 504*58957Seric for (;; bufp = junkbuf) 5054684Seric { 5064684Seric register int r; 5077356Seric register char *p; 50853751Seric extern time_t curtime(); 5094684Seric 5107685Seric /* actually do the read */ 51153751Seric if (e->e_xfp != NULL) 51253751Seric (void) fflush(e->e_xfp); /* for debugging */ 5137356Seric 51410054Seric /* if we are in the process of closing just give the code */ 51553740Seric if (mci->mci_state == MCIS_CLOSED) 51610054Seric return (SMTPCLOSING); 51710054Seric 51858680Seric if (mci->mci_out != NULL) 51958680Seric fflush(mci->mci_out); 52058680Seric 52110054Seric /* get the line from the other side */ 522*58957Seric p = sfgets(bufp, MAXLINE, mci->mci_in, timeout); 52353751Seric mci->mci_lastuse = curtime(); 52453751Seric 52510054Seric if (p == NULL) 52610131Seric { 52710148Seric extern char MsgBuf[]; /* err.c */ 52810148Seric 52921065Seric /* if the remote end closed early, fake an error */ 53021065Seric if (errno == 0) 53121065Seric # ifdef ECONNRESET 53221065Seric errno = ECONNRESET; 53356795Seric # else /* ECONNRESET */ 53421065Seric errno = EPIPE; 53556795Seric # endif /* ECONNRESET */ 53621065Seric 53757379Seric mci->mci_errno = errno; 53857642Seric mci->mci_exitstat = EX_TEMPFAIL; 53958151Seric message("451 %s: reply: read error from %s", 54057642Seric e->e_id == NULL ? "NOQUEUE" : e->e_id, 54157203Seric mci->mci_host); 54210420Seric /* if debugging, pause so we can see state */ 54310420Seric if (tTd(18, 100)) 54410420Seric pause(); 54510148Seric # ifdef LOG 54658020Seric if (LogLevel > 1) 54757203Seric syslog(LOG_INFO, "%s", &MsgBuf[4]); 54856795Seric # endif /* LOG */ 54954967Seric mci->mci_state = MCIS_ERROR; 55053751Seric smtpquit(m, mci, e); 55110054Seric return (-1); 55210131Seric } 553*58957Seric fixcrlf(bufp, TRUE); 55410054Seric 55556795Seric if (e->e_xfp != NULL && strchr("45", SmtpReplyBuffer[0]) != NULL) 55614900Seric { 55714900Seric /* serious error -- log the previous command */ 558*58957Seric if (bufp[0] != '\0') 559*58957Seric fprintf(e->e_xfp, ">>> %s\n", bufp); 560*58957Seric bufp[0] = '\0'; 56114900Seric 56214900Seric /* now log the message as from the other side */ 563*58957Seric fprintf(e->e_xfp, "<<< %s\n", bufp); 56414900Seric } 56514900Seric 56614900Seric /* display the input for verbose mode */ 56758120Seric if (Verbose) 568*58957Seric nmessage("%s", bufp); 5697356Seric 5707356Seric /* if continuation is required, we can go on */ 571*58957Seric if (bufp[3] == '-' || 572*58957Seric !(isascii(bufp[0]) && isdigit(bufp[0]))) 5734684Seric continue; 5747356Seric 5757356Seric /* decode the reply code */ 5769391Seric r = atoi(SmtpReplyBuffer); 5777356Seric 5787356Seric /* extra semantics: 0xx codes are "informational" */ 5794684Seric if (r < 100) 5804684Seric continue; 5817356Seric 58258061Seric /* save temporary failure messages for posterity */ 58358061Seric if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0') 58458061Seric (void) strcpy(SmtpError, SmtpReplyBuffer); 58558061Seric 5869391Seric /* reply code 421 is "Service Shutting Down" */ 58753740Seric if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD) 5889391Seric { 58910054Seric /* send the quit protocol */ 59053740Seric mci->mci_state = MCIS_SSD; 59153751Seric smtpquit(m, mci, e); 5929391Seric } 5939391Seric 5944684Seric return (r); 5954684Seric } 5964684Seric } 5974796Seric /* 5984865Seric ** SMTPMESSAGE -- send message to server 5994796Seric ** 6004796Seric ** Parameters: 6014796Seric ** f -- format 60210175Seric ** m -- the mailer to control formatting. 6034796Seric ** a, b, c -- parameters 6044796Seric ** 6054796Seric ** Returns: 6064796Seric ** none. 6074796Seric ** 6084796Seric ** Side Effects: 60953740Seric ** writes message to mci->mci_out. 6104796Seric */ 6114796Seric 6124865Seric /*VARARGS1*/ 61357642Seric #ifdef __STDC__ 61457642Seric smtpmessage(char *f, MAILER *m, MCI *mci, ...) 61557642Seric #else 61657642Seric smtpmessage(f, m, mci, va_alist) 6174796Seric char *f; 61810175Seric MAILER *m; 61954967Seric MCI *mci; 62057642Seric va_dcl 62157642Seric #endif 6224796Seric { 62356852Seric VA_LOCAL_DECL 62456852Seric 62557135Seric VA_START(mci); 62656852Seric (void) vsprintf(SmtpMsgBuffer, f, ap); 62756852Seric VA_END; 62858680Seric 62958120Seric if (tTd(18, 1) || Verbose) 63058151Seric nmessage(">>> %s", SmtpMsgBuffer); 63153740Seric if (mci->mci_out != NULL) 63258680Seric { 63353740Seric fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer, 63454967Seric m == NULL ? "\r\n" : m->m_eol); 63558680Seric } 63658680Seric else 63758725Seric { 63858680Seric syserr("smtpmessage: NULL mci_out"); 63958725Seric } 6404796Seric } 6415182Seric 64256795Seric # endif /* SMTP */ 643