📄 usersmtp.c
字号:
return (EX_PROTOCOL);}/*** SMTPDATA -- send the data and clean up the transaction.**** Parameters:** m -- mailer being sent to.** e -- the envelope for this message.**** Returns:** exit status corresponding to DATA command.**** Side Effects:** none.*/static jmp_buf CtxDataTimeout;static int datatimeout();smtpdata(m, mci, e) struct mailer *m; register MCI *mci; register ENVELOPE *e;{ register int r; register EVENT *ev; time_t timeout; /* ** Send the data. ** First send the command and check that it is ok. ** Then send the data. ** Follow it up with a dot to terminate. ** Finally get the results of the transaction. */ /* send the command and check ok to proceed */ smtpmessage("DATA", m, mci); SmtpPhase = mci->mci_phase = "client DATA 354"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_datainit, NULL); if (r < 0 || REPLYTYPE(r) == 4) { smtpquit(m, mci, e); return (EX_TEMPFAIL); } else if (r == 554) { smtprset(m, mci, e); return (EX_UNAVAILABLE); } else if (r != 354) {#ifdef LOG if (LogLevel > 1) { syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s", e->e_id, SmtpReplyBuffer); }#endif smtprset(m, mci, e); return (EX_PROTOCOL); } /* ** Set timeout around data writes. Make it at least large ** enough for DNS timeouts on all recipients plus some fudge ** factor. The main thing is that it should not be infinite. */ if (setjmp(CtxDataTimeout) != 0) { mci->mci_errno = errno; mci->mci_exitstat = EX_TEMPFAIL; mci->mci_state = MCIS_ERROR; syserr("451 timeout writing message to %s", mci->mci_host); smtpquit(m, mci, e); return EX_TEMPFAIL; } timeout = e->e_msgsize / 16; if (timeout < (time_t) 60) timeout = (time_t) 60; timeout += e->e_nrcpts * 90; ev = setevent(timeout, datatimeout, 0); /* now output the actual message */ (*e->e_puthdr)(mci, e); putline("\n", mci); (*e->e_putbody)(mci, e, NULL); clrevent(ev); if (ferror(mci->mci_out)) { /* error during processing -- don't send the dot */ mci->mci_errno = EIO; mci->mci_exitstat = EX_IOERR; mci->mci_state = MCIS_ERROR; smtpquit(m, mci, e); return EX_IOERR; } /* terminate the message */ fprintf(mci->mci_out, ".%s", m->m_eol); if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%05d >>> .\n", getpid()); if (Verbose) nmessage(">>> ."); /* check for the results of the transaction */ SmtpPhase = mci->mci_phase = "client DATA 250"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_datafinal, NULL); if (r < 0) { smtpquit(m, mci, e); return (EX_TEMPFAIL); } mci->mci_state = MCIS_OPEN; e->e_statmsg = newstr(&SmtpReplyBuffer[4]); if (REPLYTYPE(r) == 4) return (EX_TEMPFAIL); else if (r == 250) return (EX_OK); else if (r == 552 || r == 554) return (EX_UNAVAILABLE);#ifdef LOG if (LogLevel > 1) { syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s", e->e_id, SmtpReplyBuffer); }#endif return (EX_PROTOCOL);}static intdatatimeout(){ longjmp(CtxDataTimeout, 1);}/*** SMTPQUIT -- close the SMTP connection.**** Parameters:** m -- a pointer to the mailer.**** Returns:** none.**** Side Effects:** sends the final protocol and closes the connection.*/smtpquit(m, mci, e) register MAILER *m; register MCI *mci; ENVELOPE *e;{ bool oldSuprErrs = SuprErrs; /* ** Suppress errors here -- we may be processing a different ** job when we do the quit connection, and we don't want the ** new job to be penalized for something that isn't it's ** problem. */ SuprErrs = TRUE; /* send the quit message if we haven't gotten I/O error */ if (mci->mci_state != MCIS_ERROR) { SmtpPhase = "client QUIT"; smtpmessage("QUIT", m, mci); (void) reply(m, mci, e, TimeOuts.to_quit, NULL); SuprErrs = oldSuprErrs; if (mci->mci_state == MCIS_CLOSED) { SuprErrs = oldSuprErrs; return; } } /* now actually close the connection and pick up the zombie */ (void) endmailer(mci, e, NULL); SuprErrs = oldSuprErrs;}/*** SMTPRSET -- send a RSET (reset) command*/smtprset(m, mci, e) register MAILER *m; register MCI *mci; ENVELOPE *e;{ int r; SmtpPhase = "client RSET"; smtpmessage("RSET", m, mci); r = reply(m, mci, e, TimeOuts.to_rset, NULL); if (r < 0) mci->mci_state = MCIS_ERROR; else if (REPLYTYPE(r) == 2) { mci->mci_state = MCIS_OPEN; return; } smtpquit(m, mci, e);}/*** SMTPPROBE -- check the connection state*/smtpprobe(mci) register MCI *mci;{ int r; MAILER *m = mci->mci_mailer; extern ENVELOPE BlankEnvelope; ENVELOPE *e = &BlankEnvelope; SmtpPhase = "client probe"; smtpmessage("RSET", m, mci); r = reply(m, mci, e, TimeOuts.to_miscshort, NULL); if (r < 0 || REPLYTYPE(r) != 2) smtpquit(m, mci, e); return r;}/*** REPLY -- read arpanet reply**** Parameters:** m -- the mailer we are reading the reply from.** mci -- the mailer connection info structure.** e -- the current envelope.** timeout -- the timeout for reads.** pfunc -- processing function for second and subsequent** lines of response -- if null, no special** processing is done.**** Returns:** reply code it reads.**** Side Effects:** flushes the mail file.*/reply(m, mci, e, timeout, pfunc) MAILER *m; MCI *mci; ENVELOPE *e; time_t timeout; void (*pfunc)();{ register char *bufp; register int r; bool firstline = TRUE; char junkbuf[MAXLINE]; if (mci->mci_out != NULL) (void) fflush(mci->mci_out); if (tTd(18, 1)) printf("reply\n"); /* ** Read the input line, being careful not to hang. */ for (bufp = SmtpReplyBuffer;; bufp = junkbuf) { register char *p; extern time_t curtime(); /* actually do the read */ if (e->e_xfp != NULL) (void) fflush(e->e_xfp); /* for debugging */ /* if we are in the process of closing just give the code */ if (mci->mci_state == MCIS_CLOSED) return (SMTPCLOSING); if (mci->mci_out != NULL) fflush(mci->mci_out); /* get the line from the other side */ p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase); mci->mci_lastuse = curtime(); if (p == NULL) { bool oldholderrs; extern char MsgBuf[]; /* err.c */ /* if the remote end closed early, fake an error */ if (errno == 0)# ifdef ECONNRESET errno = ECONNRESET;# else /* ECONNRESET */ errno = EPIPE;# endif /* ECONNRESET */ mci->mci_errno = errno; mci->mci_exitstat = EX_TEMPFAIL; oldholderrs = HoldErrs; HoldErrs = TRUE; usrerr("451 reply: read error from %s", mci->mci_host); /* if debugging, pause so we can see state */ if (tTd(18, 100)) pause(); mci->mci_state = MCIS_ERROR; smtpquit(m, mci, e);#ifdef XDEBUG { char wbuf[MAXLINE]; char *p = wbuf; if (e->e_to != NULL) { sprintf(p, "%s... ", e->e_to); p += strlen(p); } sprintf(p, "reply(%s) during %s", mci->mci_host, SmtpPhase); checkfd012(wbuf); }#endif HoldErrs = oldholderrs; return (-1); } fixcrlf(bufp, TRUE); /* EHLO failure is not a real error */ if (e->e_xfp != NULL && (bufp[0] == '4' || (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0))) { /* serious error -- log the previous command */ if (SmtpNeedIntro) { /* inform user who we are chatting with */ fprintf(CurEnv->e_xfp, "... while talking to %s:\n", CurHostName); SmtpNeedIntro = FALSE; } if (SmtpMsgBuffer[0] != '\0') fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer); SmtpMsgBuffer[0] = '\0'; /* now log the message as from the other side */ fprintf(e->e_xfp, "<<< %s\n", bufp); } /* display the input for verbose mode */ if (Verbose) nmessage("050 %s", bufp); /* process the line */ if (pfunc != NULL && !firstline) (*pfunc)(bufp, m, mci, e); firstline = FALSE; /* if continuation is required, we can go on */ if (bufp[3] == '-') continue; /* ignore improperly formated input */ if (!(isascii(bufp[0]) && isdigit(bufp[0]))) continue; /* decode the reply code */ r = atoi(bufp); /* extra semantics: 0xx codes are "informational" */ if (r >= 100) break; } /* ** Now look at SmtpReplyBuffer -- only care about the first ** line of the response from here on out. */ /* save temporary failure messages for posterity */ if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0') (void) strcpy(SmtpError, SmtpReplyBuffer); /* reply code 421 is "Service Shutting Down" */ if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD) { /* send the quit protocol */ mci->mci_state = MCIS_SSD; smtpquit(m, mci, e); } return (r);}/*** SMTPMESSAGE -- send message to server**** Parameters:** f -- format** m -- the mailer to control formatting.** a, b, c -- parameters**** Returns:** none.**** Side Effects:** writes message to mci->mci_out.*//*VARARGS1*/#ifdef __STDC__smtpmessage(char *f, MAILER *m, MCI *mci, ...)#elsesmtpmessage(f, m, mci, va_alist) char *f; MAILER *m; MCI *mci; va_dcl#endif{ VA_LOCAL_DECL VA_START(mci); (void) vsprintf(SmtpMsgBuffer, f, ap); VA_END; if (tTd(18, 1) || Verbose) nmessage(">>> %s", SmtpMsgBuffer); if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(), SmtpMsgBuffer); if (mci->mci_out != NULL) { fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer, m == NULL ? "\r\n" : m->m_eol); } else if (tTd(18, 1)) { printf("smtpmessage: NULL mci_out\n"); }}# endif /* SMTP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -