--- conf.c.orig Thu Oct 31 10:26:19 2002 +++ conf.c Wed Jul 2 09:53:45 2003 @@ -201,6 +201,7 @@ stringdump("postmaster", runp->postmaster); booldump("bouncemail", runp->bouncemail); booldump("spambounce", runp->spambounce); + stringdump("bouncetext", runp->bouncetext); stringdump("properties", runp->properties); booldump("invisible", runp->invisible); booldump("showdots", runp->showdots); --- fetchmail.c.orig Fri Feb 28 16:16:15 2003 +++ fetchmail.c Wed Jul 2 09:53:45 2003 @@ -1687,6 +1687,11 @@ else if (outlevel >= O_VERBOSE) printf(GT_(" Spam-blocking disabled\n")); } + if (runp->bouncetext) + printf(GT_(" Bounces will include %s%s%s\n"), + (*runp->bouncetext == '/') ? "file " : "\"", + runp->bouncetext, + (*runp->bouncetext == '/') ? "" : "\""); if (ctl->preconnect) printf(GT_(" Server connection will be brought up with \"%s\".\n"), visbuf(ctl->preconnect)); --- fetchmail.h.orig Fri Feb 28 19:43:11 2003 +++ fetchmail.h Wed Jul 2 09:53:45 2003 @@ -134,6 +134,7 @@ char *postmaster; flag bouncemail; flag spambounce; + char *bouncetext; char *properties; flag use_syslog; flag invisible; --- fetchmail.man.orig Fri Feb 28 15:45:09 2003 +++ fetchmail.man Wed Jul 2 09:53:45 2003 @@ -1185,9 +1185,13 @@ quoted nor contains the special characters `,', `;', `:', or `='. .PP Any amount of whitespace separates tokens in server entries, but is -otherwise ignored. You may use standard C-style escapes (\en, \et, -\eb, octal, and hex) to embed non-printable characters or string -delimiters in strings. +otherwise ignored. +.PP +You may use the standard C-style escapes \e\e, \en, \er, and \et, as +well as octal and hex escapes, to embed non-printable characters in +quoted strings (the \ea, \eb, \ef, and \ev escapes are ignored). +Note that embedded double quotes must be represented with '\e042' or +\&'\ex22'; see also \fIascii\fR(7). .PP Each server entry consists of one of the keywords `poll' or `skip', followed by a server name, followed by server options, followed by any @@ -1232,6 +1236,9 @@ T} set no spambounce \& T{ Send spam bounces +T} +set bouncetext \& T{ +Include the specified text or file in bounces T} set logfile \& T{ Name of a file to dump error and status messages to --- options.c.orig Fri Oct 18 05:19:39 2002 +++ options.c Wed Jul 2 09:53:45 2003 @@ -86,6 +86,8 @@ #define LA_SSLFINGERPRINT 60 #endif +#define LA_BOUNCETEXT 61 + /* options still left: CDgGhHjJoORwWxXYz */ static const char *shortoptions = @@ -174,6 +176,8 @@ {"tracepolls",no_argument, (int *) 0, LA_TRACEPOLLS }, + {"bouncetext",required_argument, (int *) 0, LA_BOUNCETEXT }, + {(char *) 0, no_argument, (int *) 0, 0 } }; @@ -635,6 +639,10 @@ ctl->tracepolls = FLAG_TRUE; break; + case LA_BOUNCETEXT: + run.bouncetext = xstrdup(optarg); + break; + case '?': case LA_HELP: default: @@ -663,6 +671,7 @@ P(GT_(" -i, --idfile specify alternate UIDs file\n")); P(GT_(" --postmaster specify recipient of last resort\n")); P(GT_(" --nobounce redirect bounces from user to postmaster.\n")); + P(GT_(" --bouncetext include the specified text or file in bounces\n")); #if (defined(linux) && !INET6_ENABLE) || defined(__FreeBSD__) P(GT_(" -I, --interface interface required specification\n")); P(GT_(" -M, --monitor monitor interface for activity\n")); --- rcfile_l.l.orig Fri Oct 18 05:19:40 2002 +++ rcfile_l.l Wed Jul 2 09:53:45 2003 @@ -70,6 +70,7 @@ postmaster { return POSTMASTER; } bouncemail { return BOUNCEMAIL; } spambounce { return SPAMBOUNCE; } +bouncetext { return BOUNCETEXT; } warnings { return WARNINGS; } tracepolls { return TRACEPOLLS; } @@ -237,6 +238,12 @@ else while ((strchr("0123456789",*cp)!=(char*)NULL)&&(dcount++ < 3)) cval = (cval * 10) + (*cp++ - '0'); + + /* + * It'd be nice to purge inappropriate values here + * (i.e., control characters), but that's hard to do + * in a portable fashion. + */ } else if (*cp == '\\') /* C-style character escapes */ { @@ -245,8 +252,14 @@ case '\\': cval = '\\'; break; case 'n': cval = '\n'; break; case 't': cval = '\t'; break; - case 'b': cval = '\b'; break; case 'r': cval = '\r'; break; + /* purge these values */ + case 'a': + case 'b': + case 'f': + case 'v': + cval = *++cp; + break; default: cval = *cp; } cp++; --- rcfile_y.y.orig Fri Feb 28 04:52:37 2003 +++ rcfile_y.y Wed Jul 2 09:53:45 2003 @@ -69,7 +69,7 @@ %token IS HERE THERE TO MAP WILDCARD %token BATCHLIMIT FETCHLIMIT EXPUNGE PROPERTIES %token SET LOGFILE DAEMON SYSLOG IDFILE INVISIBLE POSTMASTER BOUNCEMAIL -%token SPAMBOUNCE SHOWDOTS +%token SPAMBOUNCE BOUNCETEXT SHOWDOTS %token PROTO AUTHTYPE %token STRING %token NUMBER @@ -101,6 +101,7 @@ | SET NO BOUNCEMAIL {run.bouncemail = FALSE;} | SET SPAMBOUNCE {run.spambounce = TRUE;} | SET NO SPAMBOUNCE {run.spambounce = FALSE;} + | SET BOUNCETEXT optmap STRING {run.bouncetext = xstrdup($4);} | SET PROPERTIES optmap STRING {run.properties =xstrdup($4);} | SET SYSLOG {run.use_syslog = TRUE;} | SET NO SYSLOG {run.use_syslog = FALSE;} --- sink.c.orig Fri Feb 28 20:02:18 2003 +++ sink.c Wed Jul 2 09:53:45 2003 @@ -254,6 +254,52 @@ return addr; } +static void insert_bouncetext(int sock) +/* output an user-specified error message */ +{ + if (run.bouncetext != NULL) + { + if (*run.bouncetext == '/') + { + FILE *fp; + int len; + char buf[BUFSIZ]; + + if ((fp = fopen(run.bouncetext, "r")) != NULL) + { + while (fgets(buf, sizeof(buf), fp) != NULL) + { + escapes(buf, buf); + len = strlen(buf); + if (len && buf[len - 1] == '\n') + --len; + SockPrintf(sock, "%.*s\r\n", len, buf); + } + + (void)fclose(fp); + } + else + return; + } + else + { + char *nl, *lp = run.bouncetext; + + while (*lp && (nl = strchr(lp, '\n')) != NULL) + { + SockPrintf(sock, "%.*s\r\n", nl - lp, lp); + lp = ++nl; + } + + if (*lp && *(lp + strlen(lp) - 1) != '\n') + SockPrintf(sock, "%s\r\n", lp); + } + + SockPrintf(sock, "\r\n"); + SockPrintf(sock, "\r\n"); + } +} + static int send_bouncemail(struct query *ctl, struct msgblk *msg, int userclass, char *message, int nerrors, char *errors[]) @@ -332,6 +378,7 @@ SockWrite(sock, message, strlen(message)); SockPrintf(sock, "\r\n"); SockPrintf(sock, "\r\n"); + insert_bouncetext(sock); if (nerrors) {