aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--driver.c144
-rw-r--r--fetchmail.h9
-rw-r--r--sink.c153
3 files changed, 162 insertions, 144 deletions
diff --git a/driver.c b/driver.c
index 2c561a61..cc167c75 100644
--- a/driver.c
+++ b/driver.c
@@ -334,6 +334,7 @@ static char *parse_received(struct query *ctl, char *bufp)
/* shared by readheaders and readbody */
static int sizeticker;
+static struct msgblk msgblk;
#define EMPTYLINE(s) ((s)[0] == '\r' && (s)[1] == '\n' && (s)[2] == '\0')
@@ -365,16 +366,15 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
flag no_local_matches = FALSE;
flag headers_ok, has_nuls;
int olderrs, good_addresses, bad_addresses;
- struct msgblk msg;
sizeticker = 0;
has_nuls = headers_ok = FALSE;
- msg.return_path[0] = '\0';
+ msgblk.return_path[0] = '\0';
olderrs = ctl->errcount;
/* read message headers */
- msg.reallen = reallen;
- msg.headers = received_for = NULL;
+ msgblk.reallen = reallen;
+ msgblk.headers = received_for = NULL;
from_offs = reply_to_offs = resent_from_offs = app_from_offs =
sender_offs = resent_sender_offs = env_offs = -1;
oldlen = 0;
@@ -394,7 +394,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
if ((n = SockRead(sock, buf, sizeof(buf)-1)) == -1) {
set_timeout(0);
free(line);
- free(msg.headers);
+ free(msgblk.headers);
return(PS_SOCKET);
}
set_timeout(0);
@@ -478,7 +478,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
#endif /* POP2_ENABLE */
if (num == 1 && !strncasecmp(line, "X-IMAP:", 7)) {
free(line);
- free(msg.headers);
+ free(msgblk.headers);
return(PS_RETAINED);
}
@@ -569,49 +569,49 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
*/
if (!strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
{
- strcpy(msg.return_path, cp);
+ strcpy(msgblk.return_path, cp);
if (!ctl->mda) {
free(line);
continue;
}
}
- if (!msg.headers)
+ if (!msgblk.headers)
{
oldlen = strlen(line);
- msg.headers = xmalloc(oldlen + 1);
- (void) strcpy(msg.headers, line);
+ msgblk.headers = xmalloc(oldlen + 1);
+ (void) strcpy(msgblk.headers, line);
free(line);
- line = msg.headers;
+ line = msgblk.headers;
}
else
{
int newlen;
newlen = oldlen + strlen(line);
- msg.headers = (char *) realloc(msg.headers, newlen + 1);
- if (msg.headers == NULL) {
+ msgblk.headers = (char *) realloc(msgblk.headers, newlen + 1);
+ if (msgblk.headers == NULL) {
free(line);
return(PS_IOERR);
}
- strcpy(msg.headers + oldlen, line);
+ strcpy(msgblk.headers + oldlen, line);
free(line);
- line = msg.headers + oldlen;
+ line = msgblk.headers + oldlen;
oldlen = newlen;
}
if (!strncasecmp("From:", line, 5))
- from_offs = (line - msg.headers);
+ from_offs = (line - msgblk.headers);
else if (!strncasecmp("Reply-To:", line, 9))
- reply_to_offs = (line - msg.headers);
+ reply_to_offs = (line - msgblk.headers);
else if (!strncasecmp("Resent-From:", line, 12))
- resent_from_offs = (line - msg.headers);
+ resent_from_offs = (line - msgblk.headers);
else if (!strncasecmp("Apparently-From:", line, 16))
- app_from_offs = (line - msg.headers);
+ app_from_offs = (line - msgblk.headers);
else if (!strncasecmp("Sender:", line, 7))
- sender_offs = (line - msg.headers);
+ sender_offs = (line - msgblk.headers);
else if (!strncasecmp("Resent-Sender:", line, 14))
- resent_sender_offs = (line - msg.headers);
+ resent_sender_offs = (line - msgblk.headers);
else if (!strncasecmp("Message-Id:", buf, 11))
{
@@ -638,7 +638,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
|| !strncasecmp("Apparently-To:", line, 14))
{
*to_chainptr = xmalloc(sizeof(struct addrblk));
- (*to_chainptr)->offset = (line - msg.headers);
+ (*to_chainptr)->offset = (line - msgblk.headers);
to_chainptr = &(*to_chainptr)->next;
*to_chainptr = NULL;
}
@@ -648,7 +648,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
|| !strncasecmp("Resent-Bcc:", line, 11))
{
*resent_to_chainptr = xmalloc(sizeof(struct addrblk));
- (*resent_to_chainptr)->offset = (line - msg.headers);
+ (*resent_to_chainptr)->offset = (line - msgblk.headers);
resent_to_chainptr = &(*resent_to_chainptr)->next;
*resent_to_chainptr = NULL;
}
@@ -664,7 +664,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
{
if (skipcount++ != ctl->server.envskip)
continue;
- env_offs = (line - msg.headers);
+ env_offs = (line - msgblk.headers);
}
}
else if (!received_for && !strncasecmp("Received:", line, 9))
@@ -696,7 +696,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
* make either From or To address @-less, otherwise the reply_hack
* logic will do bad things.
*/
- if (msg.headers == (char *)NULL)
+ if (msgblk.headers == (char *)NULL)
{
#ifdef HAVE_SNPRINTF
snprintf(buf, sizeof(buf),
@@ -705,7 +705,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
#endif /* HAVE_SNPRINTF */
"From: FETCHMAIL-DAEMON\r\nTo: %s@%s\r\nSubject: Headerless mail from %s's mailbox on %s\r\n",
user, fetchmailhost, ctl->remotename, ctl->server.truename);
- msg.headers = xstrdup(buf);
+ msgblk.headers = xstrdup(buf);
}
/*
@@ -718,10 +718,10 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
* headers (RFC 2046).
*/
if (ctl->mimedecode) {
- UnMimeHeader(msg.headers);
+ UnMimeHeader(msgblk.headers);
}
/* Check for MIME headers indicating possible 8-bit data */
- ctl->mimemsg = MimeBodyType(msg.headers, ctl->mimedecode);
+ ctl->mimemsg = MimeBodyType(msgblk.headers, ctl->mimedecode);
/*
* If there is a Return-Path address on the message, this was
@@ -738,25 +738,25 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
* (ex: specified by "Sender:") which is much less annoying. This
* is true for most mailing list packages.
*/
- if( !msg.return_path[0] ){
+ if( !msgblk.return_path[0] ){
char *ap = NULL;
- if (resent_sender_offs >= 0 && (ap = nxtaddr(msg.headers + resent_sender_offs)));
- else if (sender_offs >= 0 && (ap = nxtaddr(msg.headers + sender_offs)));
- else if (resent_from_offs >= 0 && (ap = nxtaddr(msg.headers + resent_from_offs)));
- else if (from_offs >= 0 && (ap = nxtaddr(msg.headers + from_offs)));
- else if (reply_to_offs >= 0 && (ap = nxtaddr(msg.headers + reply_to_offs)));
- else if (app_from_offs >= 0 && (ap = nxtaddr(msg.headers + app_from_offs)));
- if (ap) strcpy( msg.return_path, ap );
+ if (resent_sender_offs >= 0 && (ap = nxtaddr(msgblk.headers + resent_sender_offs)));
+ else if (sender_offs >= 0 && (ap = nxtaddr(msgblk.headers + sender_offs)));
+ else if (resent_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + resent_from_offs)));
+ else if (from_offs >= 0 && (ap = nxtaddr(msgblk.headers + from_offs)));
+ else if (reply_to_offs >= 0 && (ap = nxtaddr(msgblk.headers + reply_to_offs)));
+ else if (app_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + app_from_offs)));
+ if (ap) strcpy( msgblk.return_path, ap );
}
/* cons up a list of local recipients */
- msg.recipients = (struct idlist *)NULL;
+ msgblk.recipients = (struct idlist *)NULL;
accept_count = reject_count = 0;
/* is this a multidrop box? */
if (MULTIDROP(ctl))
{
if (env_offs > -1) /* We have the actual envelope addressee */
- find_server_names(msg.headers + env_offs, ctl, &msg.recipients);
+ find_server_names(msgblk.headers + env_offs, ctl, &msgblk.recipients);
else if (received_for)
/*
* We have the Received for addressee.
@@ -765,11 +765,11 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
* We use find_server_names() to let local
* hostnames go through.
*/
- find_server_names(received_for, ctl, &msg.recipients);
+ find_server_names(received_for, ctl, &msgblk.recipients);
#ifdef SDPS_ENABLE
else if (sdps_envto)
{
- find_server_names(sdps_envto, ctl, &msg.recipients);
+ find_server_names(sdps_envto, ctl, &msgblk.recipients);
free(sdps_envto);
}
#endif /* SDPS_ENABLE */
@@ -796,7 +796,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
}
/* now look for remaining adresses */
while (to_addrchain) {
- find_server_names(msg.headers+to_addrchain->offset, ctl, &msg.recipients);
+ find_server_names(msgblk.headers+to_addrchain->offset, ctl, &msgblk.recipients);
nextptr = to_addrchain->next;
free(to_addrchain);
to_addrchain = nextptr;
@@ -805,7 +805,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
if (!accept_count)
{
no_local_matches = TRUE;
- save_str(&msg.recipients, run.postmaster, XMIT_ACCEPT);
+ save_str(&msgblk.recipients, run.postmaster, XMIT_ACCEPT);
if (outlevel >= O_DEBUG)
error(0, 0,
_("no local matches, forwarding to %s"),
@@ -813,7 +813,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
}
}
else /* it's a single-drop box, use first localname */
- save_str(&msg.recipients, ctl->localnames->id, XMIT_ACCEPT);
+ save_str(&msgblk.recipients, ctl->localnames->id, XMIT_ACCEPT);
/*
@@ -823,18 +823,18 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
{
if (outlevel >= O_DEBUG)
error(0,0, _("forwarding and deletion suppressed due to DNS errors"));
- free(msg.headers);
- free_str_list(&msg.recipients);
+ free(msgblk.headers);
+ free_str_list(&msgblk.recipients);
return(PS_TRANSIENT);
}
else
{
/* set up stuffline() so we can deliver the message body through it */
- if ((n = open_sink(ctl, &msg,
+ if ((n = open_sink(ctl, &msgblk,
&good_addresses, &bad_addresses)) != PS_SUCCESS)
{
- free(msg.headers);
- free_str_list(&msg.recipients);
+ free(msgblk.headers);
+ free_str_list(&msgblk.recipients);
return(n);
}
}
@@ -845,17 +845,17 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
* synthetic Received line is before the From header. Cope
* with this...
*/
- if ((rcv = strstr(msg.headers, "Received:")) == (char *)NULL)
- rcv = msg.headers;
+ if ((rcv = strstr(msgblk.headers, "Received:")) == (char *)NULL)
+ rcv = msgblk.headers;
/* handle ">Received:" lines too */
- while (rcv > msg.headers && rcv[-1] != '\n')
+ while (rcv > msgblk.headers && rcv[-1] != '\n')
rcv--;
- if (rcv > msg.headers)
+ if (rcv > msgblk.headers)
{
char c = *rcv;
*rcv = '\0';
- n = stuffline(ctl, msg.headers);
+ n = stuffline(ctl, msgblk.headers);
*rcv = c;
}
if (!run.invisible && n != -1)
@@ -885,7 +885,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
}
else if (good_addresses == 1)
{
- for (idp = msg.recipients; idp; idp = idp->next)
+ for (idp = msgblk.recipients; idp; idp = idp->next)
if (idp->val.status.mark == XMIT_ACCEPT)
break; /* only report first address */
if (strchr(idp->id, '@'))
@@ -906,14 +906,14 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
}
if (n != -1)
- n = stuffline(ctl, rcv); /* ship out rest of msg.headers */
+ n = stuffline(ctl, rcv); /* ship out rest of msgblk.headers */
if (n == -1)
{
- error(0, errno, _("writing RFC822 msg.headers"));
+ error(0, errno, _("writing RFC822 msgblk.headers"));
release_sink(ctl);
- free(msg.headers);
- free_str_list(&msg.recipients);
+ free(msgblk.headers);
+ free_str_list(&msgblk.recipients);
return(PS_IOERR);
}
else if (!run.use_syslog && outlevel >= O_VERBOSE)
@@ -933,7 +933,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
strcat(errhd, _("no recipient addresses matched declared local names"));
else
{
- for (idp = msg.recipients; idp; idp = idp->next)
+ for (idp = msgblk.recipients; idp; idp = idp->next)
if (idp->val.status.mark == XMIT_REJECT)
break;
sprintf(errhd+strlen(errhd), _("recipient address %s didn't match any local name"), idp->id);
@@ -953,13 +953,13 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
strcat(errhd, "; ");
strcat(errhd, _("SMTP listener rejected local recipient addresses: "));
errlen = strlen(errhd);
- for (idp = msg.recipients; idp; idp = idp->next)
+ for (idp = msgblk.recipients; idp; idp = idp->next)
if (idp->val.status.mark == XMIT_ANTISPAM)
errlen += strlen(idp->id) + 2;
xalloca(errmsg, char *, errlen+3);
(void) strcpy(errmsg, errhd);
- for (idp = msg.recipients; idp; idp = idp->next)
+ for (idp = msgblk.recipients; idp; idp = idp->next)
if (idp->val.status.mark == XMIT_ANTISPAM)
{
strcat(errmsg, idp->id);
@@ -982,8 +982,8 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
*cp++ = '\0';
stuffline(ctl, buf);
- free(msg.headers);
- free_str_list(&msg.recipients);
+ free(msgblk.headers);
+ free_str_list(&msgblk.recipients);
return(headers_ok ? PS_SUCCESS : PS_TRUNCATED);
}
@@ -1246,7 +1246,7 @@ static void send_size_warnings(struct query *ctl)
* but it's not a disaster, either, since the skipped mail will not
* be deleted.
*/
- if (open_warning_by_mail(ctl))
+ if (open_warning_by_mail(ctl, (struct msgblk *)NULL))
return;
stuff_warning(ctl, OVERHD);
@@ -1273,7 +1273,7 @@ static void send_size_warnings(struct query *ctl)
current->val.status.num = 0;
}
- close_warning_by_mail(ctl);
+ close_warning_by_mail(ctl, (struct msgblk *)NULL);
#undef OVERHD
}
@@ -1376,7 +1376,8 @@ const struct method *proto; /* protocol method table */
* If we've exceeded our threshold for consecutive timeouts,
* try to notify the user, then mark the connection wedged.
*/
- if (timeoutcount > MAX_TIMEOUTS && !open_warning_by_mail(ctl))
+ if (timeoutcount > MAX_TIMEOUTS
+ && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
{
stuff_warning(ctl,
_("Subject: fetchmail sees repeated timeouts\r\n"));
@@ -1393,7 +1394,7 @@ const struct method *proto; /* protocol method table */
_("a server error. You can run `fetchmail -v -v' to diagnose the problem."));
stuff_warning(ctl,
_("Fetchmail won't poll this mailbox again until you restart it."));
- close_warning_by_mail(ctl);
+ close_warning_by_mail(ctl, (struct msgblk *)NULL);
ctl->wedged = TRUE;
}
@@ -1537,7 +1538,8 @@ const struct method *proto; /* protocol method table */
* failure the first time it happens.
*/
if (run.poll_interval
- && !ctl->wedged && !open_warning_by_mail(ctl))
+ && !ctl->wedged
+ && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
{
stuff_warning(ctl,
_("Subject: fetchmail authentication failed\r\n"));
@@ -1549,7 +1551,7 @@ const struct method *proto; /* protocol method table */
_("The attempt to get authorization failed."));
stuff_warning(ctl,
_("This probably means your password is invalid."));
- close_warning_by_mail(ctl);
+ close_warning_by_mail(ctl, (struct msgblk *)NULL);
ctl->wedged = TRUE;
}
}
@@ -1821,7 +1823,7 @@ const struct method *proto; /* protocol method table */
* it's time to request the body now. This
* fetch may be skipped if we got an anti-spam
* or other PS_REFUSED error response during
- * read_headers.
+ * readheaders.
*/
if (protocol->fetch_body && !suppress_readbody)
{
@@ -1910,7 +1912,7 @@ const struct method *proto; /* protocol method table */
}
/* end-of-message processing starts here */
- if (!close_sink(ctl, !suppress_forward))
+ if (!close_sink(ctl, &msgblk, !suppress_forward))
{
ctl->errcount++;
suppress_delete = TRUE;
diff --git a/fetchmail.h b/fetchmail.h
index 26bf4c26..2f97a016 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -278,6 +278,9 @@ struct msgblk /* message header parsed for open_sink() */
struct idlist *recipients; /* addressees */
char return_path[HOSTLEN + USERNAMELEN + 4];
int reallen;
+
+ /* this is written by open_sink */
+ int lmtp_responses; /* count of LMTP responses expected */
};
@@ -378,14 +381,14 @@ extern int phase;
int stuffline(struct query *, char *);
int open_sink(struct query*, struct msgblk *, int*, int*);
void release_sink(struct query *);
-int close_sink(struct query *, flag);
-int open_warning_by_mail(struct query *);
+int close_sink(struct query *, struct msgblk *, flag);
+int open_warning_by_mail(struct query *, struct msgblk *);
#if defined(HAVE_STDARG_H)
void stuff_warning(struct query *, const char *, ... );
#else
void stuff_warning();
#endif
-void close_warning_by_mail(struct query *);
+void close_warning_by_mail(struct query *, struct msgblk *);
/* rfc822.c: RFC822 header parsing */
char *reply_hack(char *, const char *);
diff --git a/sink.c b/sink.c
index ad9b0240..ff213e74 100644
--- a/sink.c
+++ b/sink.c
@@ -42,9 +42,6 @@
#define SIGCHLD SIGCLD
#endif
-static int lmtp_responses; /* how many should we expect? */
-static struct msgblk msgcopy; /* copies of various message internals */
-
static int smtp_open(struct query *ctl)
/* try to open a socket to the appropriate SMTP server for this query */
{
@@ -252,6 +249,46 @@ static void sanitize(char *s)
*cp = '_';
}
+static int send_bouncemail(struct query *ctl, struct msgblk *msgcopy,
+ int nerrors, char *errors[])
+{
+ char buf[MSGBUFSIZE];
+ int i;
+
+ if (open_warning_by_mail(ctl, msgcopy))
+ return(FALSE);
+
+ /* generate an error report a la RFC 1892 */
+ stuff_warning(ctl, "MIME-Version: 1.0");
+ stuff_warning(ctl, "Content-Type: multipart/report report-type=text/plain boundary=\"om-mani-padme-hum\"");
+ stuff_warning(ctl, "Content-Transfer-Encoding: 7bit");
+ stuff_warning(ctl, "");
+
+
+ /* RFC1892 part 1 -- human-readable message */
+ stuff_warning(ctl, "-- om-mani-padme-hum");
+ stuff_warning(ctl, "");
+
+ /* RFC1892 part 2 -- machine-readable responses */
+ stuff_warning(ctl, "-- om-mani-padme-hum");
+ stuff_warning(ctl,"Content-Type: message/delivery-status");
+ stuff_warning(ctl, "");
+ for (i = 0; i < nerrors; i++)
+ stuff_warning(ctl, errors[i]);
+
+ /* RFC1892 part 3 -- headers of undelivered message */
+ stuff_warning(ctl, "-- om-mani-padme-hum");
+ stuff_warning(ctl, "Content-Type: text/rfc822-headers");
+ stuff_warning(ctl, "");
+ stuffline(ctl, msgcopy->headers);
+
+ stuff_warning(ctl, "-- om-mani-padme-hum --");
+
+ close_warning_by_mail(ctl, msgcopy);
+
+ return(TRUE);
+}
+
int open_sink(struct query *ctl, struct msgblk *msg,
int *good_addresses, int *bad_addresses)
/* set up sinkfp to be an input sink we can ship a message to */
@@ -454,7 +491,7 @@ int open_sink(struct query *ctl, struct msgblk *msg,
sigchld = signal(SIGCHLD, SIG_DFL);
}
- else /* forward to an SMTP listener */
+ else /* forward to an SMTP or LMTP listener */
{
const char *ap;
char options[MSGBUFSIZE], addr[128];
@@ -469,12 +506,6 @@ int open_sink(struct query *ctl, struct msgblk *msg,
}
/*
- * Stash a copy of the parsed message block
- * for use by close_sink().
- */
- memcpy(&msgcopy, msg, sizeof(struct msgblk));
-
- /*
* Compute ESMTP options.
*/
options[0] = '\0';
@@ -638,7 +669,7 @@ int open_sink(struct query *ctl, struct msgblk *msg,
* We need to stash this away in order to know how many
* response lines to expect after the LMTP end-of-message.
*/
- lmtp_responses = *good_addresses;
+ msg->lmtp_responses = *good_addresses;
return(PS_SUCCESS);
}
@@ -659,7 +690,7 @@ void release_sink(struct query *ctl)
}
}
-int close_sink(struct query *ctl, flag forward)
+int close_sink(struct query *ctl, struct msgblk *msg, flag forward)
/* perform end-of-message actions on the current output sink */
{
if (ctl->mda)
@@ -713,7 +744,7 @@ int close_sink(struct query *ctl, flag forward)
* to people who got it the first time.
*/
if (ctl->listener == LMTP_MODE)
- if (lmtp_responses == 0)
+ if (msg->lmtp_responses == 0)
{
SMTP_ok(ctl->smtp_socket);
@@ -745,8 +776,8 @@ int close_sink(struct query *ctl, flag forward)
char **responses;
/* eat the RFC2033-required responses, saving errors */
- xalloca(responses, char **, sizeof(char *) * lmtp_responses);
- for (errors = i = 0; i < lmtp_responses; i++)
+ xalloca(responses, char **, sizeof(char *) * msg->lmtp_responses);
+ for (errors = i = 0; i < msg->lmtp_responses; i++)
{
if (SMTP_ok(ctl->smtp_socket) == SM_OK)
responses[i] = (char *)NULL;
@@ -762,7 +793,7 @@ int close_sink(struct query *ctl, flag forward)
if (errors == 0)
return(TRUE); /* all deliveries succeeded */
- else if (errors == lmtp_responses)
+ else if (errors == msg->lmtp_responses)
return(FALSE); /* all deliveries failed */
else
{
@@ -772,47 +803,18 @@ int close_sink(struct query *ctl, flag forward)
*
* What we'd really like to do is bounce a
* failures list back to the sender and return
- * TRUE, deleting the message from the server so
- * it won't be re-forwarded on subsequent poll
- * cycles.
+ * TRUE, deleting the message from the server so
+ * it won't be re-forwarded on subsequent poll
+ * cycles.
*
* We can't do that yet, so instead we report
* failures to the calling-user/postmaster. If we can't,
* there's a transient error in local delivery; leave
* the message on the server.
*/
- char buf[MSGBUFSIZE];
-
- if (open_warning_by_mail(ctl))
- return(FALSE);
-
- /* generate an error report a la RFC 1892 */
- stuff_warning(ctl, "MIME-Version: 1.0");
- stuff_warning(ctl, "Content-Type: multipart/report report-type=text/plain boundary=\"om-mani-padme-hum\"");
- stuff_warning(ctl, "Content-Transfer-Encoding: 7bit");
- stuff_warning(ctl, "");
-
-
- /* RFC1892 part 1 -- human-readable message */
- stuff_warning(ctl, "-- om-mani-padme-hum");
- stuff_warning(ctl, "");
-
- /* RFC1892 part 2 -- machine-readable responses */
- stuff_warning(ctl, "-- om-mani-padme-hum");
- stuff_warning(ctl,"Content-Type: message/delivery-status");
- stuff_warning(ctl, "");
- for (i = 0; i < errors; i++)
- stuff_warning(ctl, responses[i]);
-
- /* RFC1892 part 3 -- headers of undelivered message */
- stuff_warning(ctl, "-- om-mani-padme-hum");
- stuff_warning(ctl, "Content-Type: text/rfc822-headers");
- stuff_warning(ctl, "");
- stuffline(ctl, msgcopy.headers);
-
- stuff_warning(ctl, "-- om-mani-padme-hum --");
-
- close_warning_by_mail(ctl);
+ send_bouncemail(ctl,
+ (struct msgblk *)NULL,
+ errors, responses);
/*
* It's not completely clear what to do here,
@@ -834,45 +836,56 @@ int close_sink(struct query *ctl, flag forward)
return(TRUE);
}
-int open_warning_by_mail(struct query *ctl)
+int open_warning_by_mail(struct query *ctl, struct msgblk *msg)
/* set up output sink for a mailed warning to calling user */
{
int good, bad;
/*
* Dispatching warning email is a little complicated. The problem is
- * that we have to deal with three distinct cases:
- *
- * 1. Single-drop running from user account. Warning mail should
+ * that we have to deal with four distinct cases:
+ *
+ * 1. Non-null msg argument. We're trying to generate bouncemail
+ * about the given message. Address using the Return-Path member.
+ *
+ * 2. Single-drop running from user account. Warning mail should
* go to the local name for which we're collecting (coincides
* with calling user).
*
- * 2. Single-drop running from root or other privileged ID, with rc
+ * 3. Single-drop running from root or other privileged ID, with rc
* file generated on the fly (Ken Estes's weird setup...) Mail
* should go to the local name for which we're collecting (does not
* coincide with calling user).
*
- * 3. Multidrop. Mail must go to postmaster. We leave the recipients
+ * 4. Multidrop. Mail must go to postmaster. We leave the recipients
* member null so this message will fall through to run.postmaster.
*
* The zero in the reallen element means we won't pass a SIZE
* option to ESMTP; the message length would be more trouble than
* it's worth to compute.
*/
- struct msgblk msg = {NULL, NULL, "FETCHMAIL-DAEMON", 0};
+ struct msgblk reply = {NULL, NULL, "FETCHMAIL-DAEMON", 0};
+ int status;
- if (!MULTIDROP(ctl))
+ if (msg) /* send bouncemail (not used yet) */
{
- msg.recipients = ctl->localnames;
-
- /*
- * Ick. This could get us in trouble someday, but
- * it's necessary in order to fool open_sink().
- */
- msg.recipients->val.status.mark = XMIT_ACCEPT;
+ if (!msg->return_path[0])
+ return(PS_REFUSED);
+
+ save_str(&reply.recipients, msg->return_path, XMIT_ACCEPT);
+ status = open_sink(ctl, &reply, &good, &bad);
+ free_str_list(&reply.recipients);
+ return(status);
}
-
- return(open_sink(ctl, &msg, &good, &bad));
+ else if (!MULTIDROP(ctl)) /* send to calling user */
+ {
+ save_str(&reply.recipients, ctl->localnames->id, XMIT_ACCEPT);
+ status = open_sink(ctl, &reply, &good, &bad);
+ free_str_list(&reply.recipients);
+ return(status);
+ }
+ else /* send to postmaster */
+ return(open_sink(ctl, &reply, &good, &bad));
}
#if defined(HAVE_STDARG_H)
@@ -911,11 +924,11 @@ va_dcl
stuffline(ctl, buf);
}
-void close_warning_by_mail(struct query *ctl)
+void close_warning_by_mail(struct query *ctl, struct msgblk *msg)
/* sign and send mailed warnings */
{
stuff_warning(ctl, "--\r\n\t\t\t\tThe Fetchmail Daemon\r\n");
- close_sink(ctl, TRUE);
+ close_sink(ctl, msg, TRUE);
}
/* sink.c ends here */