#ifndef lint
#ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.20 (Berkeley) %G% (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.40 (Berkeley) %G% (with SMTP)";
#else
-static char sccsid[] = "@(#)usersmtp.c 8.20 (Berkeley) %G% (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.40 (Berkeley) %G% (without SMTP)";
#endif
#endif /* not lint */
SmtpError[0] = '\0';
CurHostName = mci->mci_host; /* XXX UGLY XXX */
+ if (CurHostName == NULL)
+ CurHostName = MyHostName;
SmtpNeedIntro = TRUE;
switch (mci->mci_state)
{
\f/*
** ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
**
-**
** Parameters:
** line -- the response line.
+** firstline -- set if this is the first line of the reply.
** m -- the mailer.
** mci -- the mailer connection info.
** e -- the envelope.
*/
void
-esmtp_check(line, m, mci, e)
+esmtp_check(line, firstline, m, mci, e)
char *line;
+ bool firstline;
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;
+ register char *l;
+
+ for (l = line; (l = strchr(++l, 'E')) != NULL; )
+ {
+ if (strncmp(l, "ESMTP ", 6) == 0)
+ {
+ mci->mci_flags |= MCIF_ESMTP;
+ break;
+ }
+ }
+ for (l = line; (l = strchr(++l, '8')) != NULL; )
+ {
+ if (strncmp(l, "8BIT OK", 7) == 0)
+ {
+ mci->mci_flags |= MCIF_8BITOK;
+ break;
+ }
+ }
}
\f/*
** HELO_OPTIONS -- process the options on a HELO line.
**
** Parameters:
** line -- the response line.
+** firstline -- set if this is the first line of the reply.
** m -- the mailer.
** mci -- the mailer connection info.
** e -- the envelope.
*/
void
-helo_options(line, m, mci, e)
+helo_options(line, firstline, m, mci, e)
char *line;
+ bool firstline;
MAILER *m;
register MCI *mci;
ENVELOPE *e;
{
register char *p;
+ if (firstline)
+ return;
+
if (strlen(line) < 5)
return;
line += 4;
}
else if (strcasecmp(line, "expn") == 0)
mci->mci_flags |= MCIF_EXPN;
+ else if (strcasecmp(line, "x-dsn-3") == 0)
+ mci->mci_flags |= MCIF_DSN;
}
\f/*
** SMTPMAILFROM -- send MAIL command
{
int r;
char *bufp;
- char buf[MAXNAME];
+ char *bodytype;
+ char buf[MAXNAME + 1];
char optbuf[MAXLINE];
if (tTd(18, 2))
else
strcpy(optbuf, "");
- if (e->e_bodytype != NULL)
+ bodytype = e->e_bodytype;
+ if (bitset(MCIF_8BITMIME, mci->mci_flags))
{
- if (bitset(MCIF_8BITMIME, mci->mci_flags))
+ if (bodytype == NULL &&
+ bitset(MM_MIME8BIT, MimeMode) &&
+ bitset(EF_HAS8BIT, e->e_flags) &&
+ !bitnset(M_8BITS, m->m_flags))
+ bodytype = "8BITMIME";
+ if (bodytype != NULL)
{
strcat(optbuf, " BODY=");
- strcat(optbuf, e->e_bodytype);
+ strcat(optbuf, bodytype);
}
- else if (strcasecmp(e->e_bodytype, "7bit") != 0)
+ }
+ else if (bitnset(M_8BITS, m->m_flags) ||
+ !bitset(EF_HAS8BIT, e->e_flags) ||
+ (e->e_bodytype != NULL &&
+ strcasecmp(e->e_bodytype, "7bit") == 0))
+ {
+ /* just pass it through */
+ }
+ else if (bitset(MM_CVTMIME, MimeMode) &&
+ (e->e_bodytype != NULL || !bitset(MM_PASS8BIT, MimeMode)))
+ {
+ /* must convert from 8bit MIME format to 7bit encoded */
+ mci->mci_flags |= MCIF_CVT8TO7;
+ }
+ else if (!bitset(MM_PASS8BIT, MimeMode))
+ {
+ /* cannot just send a 8-bit version */
+ usrerr("%s does not support 8BITMIME", mci->mci_host);
+ return EX_DATAERR;
+ }
+
+ if (bitset(MCIF_DSN, mci->mci_flags))
+ {
+ if (e->e_envid != NULL)
{
- /* cannot just send a 7-bit version */
- usrerr("%s does not support 8BITMIME", mci->mci_host);
- return EX_DATAERR;
+ strcat(optbuf, " ENVID=");
+ strcat(optbuf, e->e_envid);
+ }
+
+ /* RET= parameter */
+ if (bitset(EF_RET_PARAM, e->e_flags))
+ {
+ strcat(optbuf, " RET=");
+ if (bitset(EF_NO_BODY_RETN, e->e_flags))
+ strcat(optbuf, "HDRS");
+ else
+ strcat(optbuf, "FULL");
}
}
!bitnset(M_NO_NULL_FROM, m->m_flags))
(void) strcpy(buf, "");
else
- expand("\201g", buf, &buf[sizeof buf - 1], e);
+ expand("\201g", buf, sizeof buf, e);
if (buf[0] == '<')
{
/* strip off <angle brackets> (put back on below) */
}
else if (r == 250)
{
- mci->mci_exitstat = EX_OK;
return EX_OK;
}
+ else if (r == 501 || r == 553)
+ {
+ /* syntax error in arguments */
+ smtpquit(m, mci, e);
+ return EX_DATAERR;
+ }
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);
+ syslog(LOG_CRIT, "%s: %s: SMTP MAIL protocol error: %s",
+ e->e_id, mci->mci_host, SmtpReplyBuffer);
}
#endif
/* protocol error -- close up */
smtpquit(m, mci, e);
- mci->mci_exitstat = EX_PROTOCOL;
return EX_PROTOCOL;
}
\f/*
ENVELOPE *e;
{
register int r;
+ char optbuf[MAXLINE];
- smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
+ strcpy(optbuf, "");
+ if (bitset(MCIF_DSN, mci->mci_flags))
+ {
+ /* NOTIFY= parameter */
+ if (bitset(QHASNOTIFY, to->q_flags))
+ {
+ bool firstone = TRUE;
+
+ strcat(optbuf, " NOTIFY=");
+ if (bitset(QPINGONSUCCESS, to->q_flags))
+ {
+ strcat(optbuf, "SUCCESS");
+ firstone = FALSE;
+ }
+ if (bitset(QPINGONFAILURE, to->q_flags))
+ {
+ if (!firstone)
+ strcat(optbuf, ",");
+ strcat(optbuf, "FAILURE");
+ firstone = FALSE;
+ }
+ if (bitset(QPINGONDELAY, to->q_flags))
+ {
+ if (!firstone)
+ strcat(optbuf, ",");
+ strcat(optbuf, "DELAY");
+ firstone = FALSE;
+ }
+ if (firstone)
+ strcat(optbuf, "NEVER");
+ }
+
+ /* ORCPT= parameter */
+ if (to->q_orcpt != NULL)
+ {
+ strcat(optbuf, " ORCPT=");
+ strcat(optbuf, to->q_orcpt);
+ }
+ }
+
+ smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf);
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);
+ setstatus(to, SmtpReplyBuffer);
if (r < 0 || REPLYTYPE(r) == 4)
return (EX_TEMPFAIL);
else if (REPLYTYPE(r) == 2)
#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s",
- e->e_id, SmtpReplyBuffer);
+ syslog(LOG_CRIT, "%s: %s: SMTP RCPT protocol error: %s",
+ e->e_id, mci->mci_host, SmtpReplyBuffer);
}
#endif
*/
static jmp_buf CtxDataTimeout;
-static int datatimeout();
+static void datatimeout();
smtpdata(m, mci, e)
struct mailer *m;
#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s",
- e->e_id, SmtpReplyBuffer);
+ syslog(LOG_CRIT, "%s: %s: SMTP DATA-1 protocol error: %s",
+ e->e_id, mci->mci_host, SmtpReplyBuffer);
}
#endif
smtprset(m, mci, e);
timeout += e->e_nrcpts * 90;
ev = setevent(timeout, datatimeout, 0);
- /* now output the actual message */
- (*e->e_puthdr)(mci, e);
- putline("\n", mci);
+ /*
+ ** Output the actual message.
+ */
+
+ (*e->e_puthdr)(mci, e->e_header, e);
(*e->e_putbody)(mci, e, NULL);
+ /*
+ ** Cleanup after sending message.
+ */
+
clrevent(ev);
if (ferror(mci->mci_out))
#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s",
- e->e_id, SmtpReplyBuffer);
+ syslog(LOG_CRIT, "%s: %s: SMTP DATA-2 protocol error: %s",
+ e->e_id, mci->mci_host, SmtpReplyBuffer);
}
#endif
return (EX_PROTOCOL);
}
-static int
+static void
datatimeout()
{
longjmp(CtxDataTimeout, 1);
nmessage("050 %s", bufp);
/* process the line */
- if (pfunc != NULL && !firstline)
- (*pfunc)(bufp, m, mci, e);
+ if (pfunc != NULL)
+ (*pfunc)(bufp, firstline, m, mci, e);
firstline = FALSE;