📄 usersmtp.c
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */# include "sendmail.h"#ifndef lint#ifdef SMTPstatic char sccsid[] = "@(#)usersmtp.c 8.18 (Berkeley) 1/24/94 (with SMTP)";#elsestatic char sccsid[] = "@(#)usersmtp.c 8.18 (Berkeley) 1/24/94 (without SMTP)";#endif#endif /* not lint */# include <sysexits.h># include <errno.h># ifdef SMTP/*** USERSMTP -- run SMTP protocol from the user end.**** This protocol is described in RFC821.*/#define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */#define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */#define SMTPCLOSING 421 /* "Service Shutting Down" */char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */char SmtpError[MAXLINE] = ""; /* save failure error messages */int SmtpPid; /* pid of mailer */bool SmtpNeedIntro; /* need "while talking" in transcript */#ifdef __STDC__extern smtpmessage(char *f, MAILER *m, MCI *mci, ...);#endif/*** SMTPINIT -- initialize SMTP.**** Opens the connection and sends the initial protocol.**** Parameters:** m -- mailer to create connection to.** pvp -- pointer to parameter vector to pass to** the mailer.**** Returns:** none.**** Side Effects:** creates connection and sends initial protocol.*/smtpinit(m, mci, e) struct mailer *m; register MCI *mci; ENVELOPE *e;{ register int r; register char *p; extern void esmtp_check(); extern void helo_options(); if (tTd(18, 1)) { printf("smtpinit "); mci_dump(mci, FALSE); } /* ** Open the connection to the mailer. */ SmtpError[0] = '\0'; CurHostName = mci->mci_host; /* XXX UGLY XXX */ SmtpNeedIntro = TRUE; switch (mci->mci_state) { case MCIS_ACTIVE: /* need to clear old information */ smtprset(m, mci, e); /* fall through */ case MCIS_OPEN: return; case MCIS_ERROR: case MCIS_SSD: /* shouldn't happen */ smtpquit(m, mci, e); /* fall through */ case MCIS_CLOSED: syserr("451 smtpinit: state CLOSED"); return; case MCIS_OPENING: break; } mci->mci_state = MCIS_OPENING; /* ** Get the greeting message. ** This should appear spontaneously. Give it five minutes to ** happen. */ SmtpPhase = mci->mci_phase = "client greeting"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check); if (r < 0 || REPLYTYPE(r) == 4) goto tempfail1; if (REPLYTYPE(r) != 2) goto unavailable; /* ** Send the HELO command. ** My mother taught me to always introduce myself. */ if (bitnset(M_ESMTP, m->m_flags)) mci->mci_flags |= MCIF_ESMTP;tryhelo: if (bitset(MCIF_ESMTP, mci->mci_flags)) { smtpmessage("EHLO %s", m, mci, MyHostName); SmtpPhase = mci->mci_phase = "client EHLO"; } else { smtpmessage("HELO %s", m, mci, MyHostName); SmtpPhase = mci->mci_phase = "client HELO"; } setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_helo, helo_options); if (r < 0) goto tempfail1; else if (REPLYTYPE(r) == 5) { if (bitset(MCIF_ESMTP, mci->mci_flags)) { /* try old SMTP instead */ mci->mci_flags &= ~MCIF_ESMTP; goto tryhelo; } goto unavailable; } else if (REPLYTYPE(r) != 2) goto tempfail1; /* ** Check to see if we actually ended up talking to ourself. ** This means we didn't know about an alias or MX, or we managed ** to connect to an echo server. ** ** If this code remains at all, "CheckLoopBack" should be ** a mailer flag. This is a MAYBENEXTRELEASE feature. */ p = strchr(&SmtpReplyBuffer[4], ' '); if (p != NULL) *p = '\0'; if (CheckLoopBack && strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0) { syserr("553 %s config error: mail loops back to myself", MyHostName); mci->mci_exitstat = EX_CONFIG; mci->mci_errno = 0; smtpquit(m, mci, e); return; } /* ** If this is expected to be another sendmail, send some internal ** commands. */ if (bitnset(M_INTERNAL, m->m_flags)) { /* tell it to be verbose */ smtpmessage("VERB", m, mci); r = reply(m, mci, e, TimeOuts.to_miscshort, NULL); if (r < 0) goto tempfail2; } if (mci->mci_state != MCIS_CLOSED) { mci->mci_state = MCIS_OPEN; return; } /* got a 421 error code during startup */ tempfail1: tempfail2: mci->mci_exitstat = EX_TEMPFAIL; if (mci->mci_errno == 0) mci->mci_errno = errno; if (mci->mci_state != MCIS_CLOSED) smtpquit(m, mci, e); return; unavailable: mci->mci_exitstat = EX_UNAVAILABLE; mci->mci_errno = errno; smtpquit(m, mci, e); return;}/*** ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol****** Parameters:** line -- the response line.** m -- the mailer.** mci -- the mailer connection info.** e -- the envelope.**** Returns:** none.*/voidesmtp_check(line, m, mci, e) char *line; MAILER *m; register MCI *mci; ENVELOPE *e;{ if (strlen(line) < 5) return; line += 4; if (strncmp(line, "ESMTP ", 6) == 0) mci->mci_flags |= MCIF_ESMTP;}/*** HELO_OPTIONS -- process the options on a HELO line.**** Parameters:** line -- the response line.** m -- the mailer.** mci -- the mailer connection info.** e -- the envelope.**** Returns:** none.*/voidhelo_options(line, m, mci, e) char *line; MAILER *m; register MCI *mci; ENVELOPE *e;{ register char *p; if (strlen(line) < 5) return; line += 4; p = strchr(line, ' '); if (p != NULL) *p++ = '\0'; if (strcasecmp(line, "size") == 0) { mci->mci_flags |= MCIF_SIZE; if (p != NULL) mci->mci_maxsize = atol(p); } else if (strcasecmp(line, "8bitmime") == 0) { mci->mci_flags |= MCIF_8BITMIME; mci->mci_flags &= ~MCIF_7BIT; } else if (strcasecmp(line, "expn") == 0) mci->mci_flags |= MCIF_EXPN;}/*** SMTPMAILFROM -- send MAIL command**** Parameters:** m -- the mailer.** mci -- the mailer connection structure.** e -- the envelope (including the sender to specify).*/smtpmailfrom(m, mci, e) struct mailer *m; MCI *mci; ENVELOPE *e;{ int r; char *bufp; char buf[MAXNAME]; char optbuf[MAXLINE]; if (tTd(18, 2)) printf("smtpmailfrom: CurHost=%s\n", CurHostName); /* set up appropriate options to include */ if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0) sprintf(optbuf, " SIZE=%ld", e->e_msgsize); else strcpy(optbuf, ""); /* ** Send the MAIL command. ** Designates the sender. */ mci->mci_state = MCIS_ACTIVE; if (bitset(EF_RESPONSE, e->e_flags) && !bitnset(M_NO_NULL_FROM, m->m_flags)) (void) strcpy(buf, ""); else expand("\201g", buf, &buf[sizeof buf - 1], e); if (buf[0] == '<') { /* strip off <angle brackets> (put back on below) */ bufp = &buf[strlen(buf) - 1]; if (*bufp == '>') *bufp = '\0'; bufp = &buf[1]; } else bufp = buf; if (e->e_from.q_mailer == LocalMailer || !bitnset(M_FROMPATH, m->m_flags)) { smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf); } else { smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName, *bufp == '@' ? ',' : ':', bufp, optbuf); } SmtpPhase = mci->mci_phase = "client MAIL"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_mail, NULL); if (r < 0 || REPLYTYPE(r) == 4) { mci->mci_exitstat = EX_TEMPFAIL; mci->mci_errno = errno; smtpquit(m, mci, e); return EX_TEMPFAIL; } else if (r == 250) { mci->mci_exitstat = EX_OK; return EX_OK; } else if (r == 552) { /* signal service unavailable */ mci->mci_exitstat = EX_UNAVAILABLE; smtpquit(m, mci, e); return EX_UNAVAILABLE; }#ifdef LOG if (LogLevel > 1) { syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s", e->e_id, SmtpReplyBuffer); }#endif /* protocol error -- close up */ smtpquit(m, mci, e); mci->mci_exitstat = EX_PROTOCOL; return EX_PROTOCOL;}/*** SMTPRCPT -- designate recipient.**** Parameters:** to -- address of recipient.** m -- the mailer we are sending to.** mci -- the connection info for this transaction.** e -- the envelope for this transaction.**** Returns:** exit status corresponding to recipient status.**** Side Effects:** Sends the mail via SMTP.*/smtprcpt(to, m, mci, e) ADDRESS *to; register MAILER *m; MCI *mci; ENVELOPE *e;{ register int r; smtpmessage("RCPT To:<%s>", m, mci, to->q_user); SmtpPhase = mci->mci_phase = "client RCPT"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_rcpt, NULL); if (r < 0 || REPLYTYPE(r) == 4) return (EX_TEMPFAIL); else if (REPLYTYPE(r) == 2) return (EX_OK); else if (r == 550 || r == 551 || r == 553) return (EX_NOUSER); else if (r == 552 || r == 554) return (EX_UNAVAILABLE);#ifdef LOG if (LogLevel > 1) { syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s", e->e_id, SmtpReplyBuffer); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -