batchcount = 0;
}
-int smtp_open(struct query *ctl)
+static void smtp_rset(struct query *ctl)
+/* reset the mail transaction */
+{
+ if (SMTP_rset(ctl->smtp_socket, ctl->smtphostmode) == SM_UNRECOVERABLE)
+ {
+ /* close the bad connection. fetchmail will reconnect for the
+ * next mail */
+ smtp_close(ctl, 0);
+ }
+}
+
+int smtp_setup(struct query *ctl)
/* try to open a socket to the appropriate SMTP server for this query */
{
/* maybe it's time to close the socket in order to force delivery */
}
/* first, probe for ESMTP */
- if (SMTP_ok(ctl->smtp_socket, ctl->smtphostmode) == SM_OK &&
+ if (SMTP_ok(ctl->smtp_socket, ctl->smtphostmode, TIMEOUT_STARTSMTP) == SM_OK &&
SMTP_ehlo(ctl->smtp_socket, ctl->smtphostmode, id_me,
ctl->server.esmtp_name, ctl->server.esmtp_password,
&ctl->server.esmtp_options) == SM_OK)
}
}
- if (SMTP_ok(ctl->smtp_socket, ctl->smtphostmode) == SM_OK &&
+ if (SMTP_ok(ctl->smtp_socket, ctl->smtphostmode, TIMEOUT_STARTSMTP) == SM_OK &&
SMTP_helo(ctl->smtp_socket, ctl->smtphostmode, id_me) == SM_OK)
break; /* success */
}
static int send_bouncemail(struct query *ctl, struct msgblk *msg,
- int userclass, char *message,
+ int userclass, char *message /* should have \r\n at the end */,
int nerrors, char *errors[])
/* bounce back an error report a la RFC 1892 */
{
const char *md1 = "MAILER-DAEMON", *md2 = "MAILER-DAEMON@";
/* don't bounce in reply to undeliverable bounces */
- if (!msg->return_path[0] ||
+ if (!msg || !msg->return_path[0] ||
strcmp(msg->return_path, "<>") == 0 ||
strcasecmp(msg->return_path, md1) == 0 ||
strncasecmp(msg->return_path, md2, strlen(md2)) == 0)
if ((sock = SockOpen("localhost", SMTP_PORT, NULL, &ai1)) == -1)
return(FALSE);
- if (SMTP_ok(sock, SMTP_MODE) != SM_OK)
+ if (SMTP_ok(sock, SMTP_MODE, TIMEOUT_STARTSMTP) != SM_OK)
{
SockClose(sock);
return FALSE;
SockPrintf(sock, "--%s\r\n", boundary);
SockPrintf(sock,"Content-Type: text/plain\r\n");
SockPrintf(sock, "\r\n");
- SockPrintf(sock, "This message was created automatically by mail delivery software.\r\n\r\n");
+ SockPrintf(sock, "This message was created automatically by mail delivery software.\r\n");
+ SockPrintf(sock, "\r\n");
SockPrintf(sock, "A message that you sent could not be delivered to one or more of its\r\n");
- SockPrintf(sock, "recipients. This is a permanent error. The following address(es) failed:\r\n");
+ SockPrintf(sock, "recipients. This is a permanent error.\r\n");
+ SockPrintf(sock, "\r\n");
+ SockPrintf(sock, "Reason: %s", message);
SockPrintf(sock, "\r\n");
+ SockPrintf(sock, "The following address(es) failed:\r\n");
if (nerrors)
{
* RSET discards the message body and it doesn't get sent to the
* valid recipients.
*/
- SMTP_rset(ctl->smtp_socket); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
if (outlevel >= O_DEBUG)
report(stdout, GT_("Saved error is still %d\n"), smtperr);
#endif /* __UNUSED */
free(responses[0]);
return(PS_REFUSED);
+ case 530: /* must issue STARTTLS error */
+ /*
+ * Some SMTP servers insist on encrypted communication
+ * Let's set PS_TRANSIENT, otherwise all messages to be sent
+ * over such server would be blackholed - see RFC 3207.
+ */
+ if (outlevel > O_SILENT)
+ report_complete(stdout,
+ GT_("SMTP server requires STARTTLS, keeping message.\n"));
+ free(responses[0]);
+ return(PS_TRANSIENT);
+
default:
/* bounce non-transient errors back to the sender */
if (smtperr >= 500 && smtperr <= 599)
{
int smtperr = atoi(smtp_response);
+ (void)msg;
+
if (str_find(&ctl->antispam, smtperr))
{
if (run.spambounce)
n = 0;
if (ctl->mda || ctl->bsmtp) {
- n = fwrite(buf, last - buf, 1, sinkfp);
+ n = fwrite(buf, 1, last - buf, sinkfp);
if (ferror(sinkfp)) n = -1;
} else if (ctl->smtp_socket != -1)
n = SockWrite(ctl->smtp_socket, buf, last - buf);
else
sinkfp = fopen(ctl->bsmtp, "a");
+ if (!sinkfp || ferror(sinkfp)) {
+ report(stderr, GT_("BSMTP file open failed: %s\n"),
+ strerror(errno));
+ return(PS_BSMTP);
+ }
+
/* see the ap computation under the SMTP branch */
need_anglebrs = (msg->return_path[0] != '<');
fprintf(sinkfp,
fputs("DATA\r\n", sinkfp);
- if (ferror(sinkfp))
+ if (fflush(sinkfp) || ferror(sinkfp))
{
- report(stderr, GT_("BSMTP file open or preamble write failed\n"));
+ report(stderr, GT_("BSMTP preamble write failed.\n"));
return(PS_BSMTP);
}
{
int err = handle_smtp_report(ctl, msg); /* map to PS_TRANSIENT or PS_REFUSED */
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(err);
}
case PS_SUCCESS:
#ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS
from_responses[*bad_addresses] = xstrdup(smtp_response);
- strcpy(from_responses[*bad_addresses], smtp_response);
#endif /* EXPLICIT_BOUNCE_ON_BAD_ADDRESS */
(*bad_addresses)++;
* crap. If one of the recipients returned PS_TRANSIENT,
* we return exactly that.
*/
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* required by RFC1870 */
+ smtp_rset(ctl); /* required by RFC1870 */
goto transient;
}
#ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS
{
if (outlevel >= O_VERBOSE)
report(stderr, GT_("no address matches; no postmaster set.\n"));
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* required by RFC1870 */
+ smtp_rset(ctl); /* required by RFC1870 */
return(PS_REFUSED);
}
if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, ctl->smtphostmode,
if (smtp_err != SM_OK)
{
report(stderr, GT_("can't even send to %s!\n"), run.postmaster);
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* required by RFC1870 */
+ smtp_rset(ctl); /* required by RFC1870 */
return(PS_REFUSED);
}
if (smtp_err != SM_OK)
{
int err = handle_smtp_report(ctl, msg);
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(err);
}
sp += 2;
}
- after = xmalloc(length + 1);
+ after = (char *)xmalloc(length + 1);
/* copy mda source string to after, while expanding %[sTF] */
for (dp = after, sp = before; (*dp = *sp); dp++, sp++) {
* open a socket fails, fall through to attempt delivery via
* local MDA.
*/
- else if (!ctl->mda && smtp_open(ctl) != -1)
+ else if (!ctl->mda && smtp_setup(ctl) != -1)
return(open_smtp_sink(ctl, msg, good_addresses, bad_addresses));
/*
int smtp_err;
if (ctl->mda)
{
- int rc,e,e2,err = 0;
+ int rc = 0, e = 0, e2 = 0, err = 0;
/* close the delivery pipe, we'll reopen before next message */
if (sinkfp)
{
if (handle_smtp_report(ctl, msg) != PS_REFUSED)
{
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(FALSE);
}
else
{
report(stderr, GT_("SMTP listener refused delivery\n"));
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(TRUE);
}
}
{
if (lmtp_responses == 0)
{
- SMTP_ok(ctl->smtp_socket, ctl->smtphostmode);
+ SMTP_ok(ctl->smtp_socket, ctl->smtphostmode, TIMEOUT_EOM);
/*
* According to RFC2033, 503 is the only legal response
responses = (char **)xmalloc(sizeof(char *) * lmtp_responses);
for (errors = i = 0; i < lmtp_responses; i++)
{
- if ((smtp_err = SMTP_ok(ctl->smtp_socket, ctl->smtphostmode))
+ if ((smtp_err = SMTP_ok(ctl->smtp_socket, ctl->smtphostmode, TIMEOUT_EOM))
== SM_UNRECOVERABLE)
{
smtp_close(ctl, 0);