From: Wietse Venema Date: Mon, 5 Apr 1999 05:00:00 +0000 (-0500) Subject: snapshot-19990405 X-Git-Tag: v20010228~122 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08307123e834ce17c235b9484d1288e1b99024e9;p=thirdparty%2Fpostfix.git snapshot-19990405 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index cfdaaa506..5515cf174 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -2511,6 +2511,29 @@ Apologies for any names omitted. the extension to recipient addresses. This is more consistent with the way aliases are expanded. File: local/dotforward.c. +19990404 + + Bugfix: after receiving mail, the SMTP server didn't reset + the cleanup error flag, so that multiple deliveries over + the same SMTP session could fail due to errors with previous + deliveries. Found by Lamont Jones, Hewlett-Packard. + +19990405 + + Feature: MIME-encapsulated bounces. Philip A. Prindeville, + Mirapoint, Inc., USA. File: bounce/bounce_notify_service.c + + Cleanup: vstreams now properly look at the EOF flag before + attempting to read, eliminating the need for typing Ctrl-D + twice to test programs; the EOF flag is reset after each + unget or seek operation. Files: util/vstream.c, util/vbuf.c. + + Feature: in preparation for configurable message headers + the mac_parse() routine now balances the parentheses in + ${name} or $(name). We need this in order to support + conditional expressions such as ${name?text} where `text' + contains other ${name} expressions. + Future: Planned: must be able to list the same hash table in diff --git a/postfix/bounce/bounce_notify_service.c b/postfix/bounce/bounce_notify_service.c index ae8889bc8..a7f5d2567 100644 --- a/postfix/bounce/bounce_notify_service.c +++ b/postfix/bounce/bounce_notify_service.c @@ -91,7 +91,8 @@ /* bounce_header - generate bounce message header */ -static int bounce_header(VSTREAM *bounce, VSTRING *buf, const char *dest, int flush) +static int bounce_header(VSTREAM *bounce, VSTRING *buf, const char *dest, + const char *boundary, int flush) { /* @@ -113,15 +114,33 @@ static int bounce_header(VSTREAM *bounce, VSTRING *buf, const char *dest, int fl "Subject: Delayed Mail (still being retried)"); } post_mail_fprintf(bounce, "To: %s", STR(quote_822_local(buf, dest))); + + /* + * MIME header. + */ + post_mail_fprintf(bounce, "MIME-Version: 1.0"); + post_mail_fprintf(bounce, "Content-Type: %s/%s;", "multipart", "mixed"); + post_mail_fprintf(bounce, "\tboundary=\"%s\"", boundary); + post_mail_fputs(bounce, ""); + post_mail_fputs(bounce, "This is a MIME-encapsulated message."); post_mail_fputs(bounce, ""); return (vstream_ferror(bounce)); } /* bounce_boilerplate - generate boiler-plate text */ -static int bounce_boilerplate(VSTREAM *bounce, VSTRING *buf, int flush) +static int bounce_boilerplate(VSTREAM *bounce, VSTRING *buf, + const char *boundary, int flush) { + /* + * MIME header. + */ + post_mail_fprintf(bounce, "--%s", boundary); + post_mail_fprintf(bounce, "Content-Description: %s", "Notification"); + post_mail_fprintf(bounce, "Content-Type: %s/%s", "text", "plain"); + post_mail_fputs(bounce, ""); + /* * Print the message body with the problem report. XXX For now, we use a * fixed bounce template. We could use a site-specific parametrized @@ -166,6 +185,7 @@ static int bounce_boilerplate(VSTREAM *bounce, VSTRING *buf, int flush) } post_mail_fputs(bounce, ""); post_mail_fprintf(bounce, "\t\t\tThe %s program", var_mail_name); + post_mail_fputs(bounce, ""); return (vstream_ferror(bounce)); } @@ -180,10 +200,19 @@ static void bounce_print(const char *str, int len, int indent, char *context) /* bounce_diagnostics - send bounce log report */ -static int bounce_diagnostics(char *service, VSTREAM *bounce, VSTRING *buf, char *queue_id) +static int bounce_diagnostics(char *service, VSTREAM *bounce, VSTRING *buf, + char *queue_id, const char *boundary) { VSTREAM *log; + /* + * MIME header. + */ + post_mail_fprintf(bounce, "--%s", boundary); + post_mail_fprintf(bounce, "Content-Description: %s", "Delivery error report"); + post_mail_fprintf(bounce, "Content-Type: %s/%s", "text", "plain"); + post_mail_fputs(bounce, ""); + /* * If the bounce log cannot be found, do not raise a fatal run-time * error. There is nothing we can do about the error, and all we are @@ -195,7 +224,6 @@ static int bounce_diagnostics(char *service, VSTREAM *bounce, VSTRING *buf, char if ((log = mail_queue_open(service, queue_id, O_RDONLY, 0)) == 0) { if (errno != ENOENT) msg_fatal("open %s %s: %m", service, queue_id); - post_mail_fputs(bounce, ""); post_mail_fputs(bounce, "\t--- Delivery error report unavailable ---"); post_mail_fputs(bounce, ""); } @@ -211,9 +239,6 @@ static int bounce_diagnostics(char *service, VSTREAM *bounce, VSTRING *buf, char #define LENGTH 79 #define INDENT 4 - post_mail_fputs(bounce, ""); - post_mail_fputs(bounce, "\t--- Delivery error report follows ---"); - post_mail_fputs(bounce, ""); while (vstream_ferror(bounce) == 0 && vstring_fgets_nonl(buf, log)) { printable(STR(buf), '_'); line_wrap(STR(buf), LENGTH, INDENT, bounce_print, (char *) bounce); @@ -229,13 +254,22 @@ static int bounce_diagnostics(char *service, VSTREAM *bounce, VSTRING *buf, char /* bounce_original - send a copy of the original to the victim */ static int bounce_original(char *service, VSTREAM *bounce, VSTRING *buf, - char *queue_name, char *queue_id, int headers_only) + char *queue_name, char *queue_id, + const char *boundary, int headers_only) { int status = 0; VSTREAM *src; int rec_type; int bounce_length; + /* + * MIME headers. + */ + post_mail_fprintf(bounce, "--%s", boundary); + post_mail_fprintf(bounce, "Content-Description: %s", "Undelivered Message"); + post_mail_fprintf(bounce, "Content-Type: %s/%s", "message", "rfc822"); + post_mail_fputs(bounce, ""); + /* * If the original message cannot be found, do not raise a run-time * error. There is nothing we can do about the error, and all we are @@ -248,15 +282,10 @@ static int bounce_original(char *service, VSTREAM *bounce, VSTRING *buf, if (errno != ENOENT) msg_fatal("open %s %s: %m", service, queue_id); post_mail_fputs(bounce, "\t--- Undelivered message unavailable ---"); + post_mail_fputs(bounce, ""); return (vstream_ferror(bounce)); } - /* - * Append a copy of the rejected message. - */ - post_mail_fputs(bounce, "\t--- Undelivered message follows ---"); - post_mail_fputs(bounce, ""); - /* * Skip over the original message envelope records. If the envelope is * corrupted just send whatever we can (remember this is a best effort, @@ -285,6 +314,7 @@ static int bounce_original(char *service, VSTREAM *bounce, VSTRING *buf, status = (REC_PUT_BUF(bounce, rec_type, buf) != rec_type); } } + post_mail_fprintf(bounce, "--%s--", boundary); if (headers_only == 0 && rec_type != REC_TYPE_XTRA) status |= mark_corrupt(src); if (vstream_fclose(src)) @@ -302,6 +332,13 @@ int bounce_notify_service(char *service, char *queue_name, int postmaster_status = 1; VSTREAM *bounce; int notify_mask = name_mask(mail_error_masks, var_notify_classes); + VSTRING *boundary = vstring_alloc(100); + + /* + * Unique string for multi-part message boundaries. + */ + vstring_sprintf(boundary, "%s.%ld/%s", + queue_id, event_time(), var_myhostname); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_CLEANUP_FLAGS 0 @@ -354,9 +391,12 @@ int bounce_notify_service(char *service, char *queue_name, * reason for the bounce, and the headers of the original * message. Don't bother sending the boiler-plate text. */ - if (!bounce_header(bounce, buf, mail_addr_postmaster(), flush) - && bounce_diagnostics(service, bounce, buf, queue_id) == 0) + if (!bounce_header(bounce, buf, mail_addr_postmaster(), + STR(boundary), flush) + && bounce_diagnostics(service, bounce, buf, queue_id, + STR(boundary)) == 0) bounce_original(service, bounce, buf, queue_name, queue_id, + STR(boundary), flush ? BOUNCE_ALL : BOUNCE_HEADERS); bounce_status = post_mail_fclose(bounce); } @@ -376,10 +416,12 @@ int bounce_notify_service(char *service, char *queue_name, * pretends that we are a polite mail system, the text with * reason for the bounce, and a copy of the original message. */ - if (bounce_header(bounce, buf, recipient, flush) == 0 - && bounce_boilerplate(bounce, buf, flush) == 0 - && bounce_diagnostics(service, bounce, buf, queue_id) == 0) + if (bounce_header(bounce, buf, recipient, STR(boundary), flush) == 0 + && bounce_boilerplate(bounce, buf, STR(boundary), flush) == 0 + && bounce_diagnostics(service, bounce, buf, queue_id, + STR(boundary)) == 0) bounce_original(service, bounce, buf, queue_name, queue_id, + STR(boundary), flush ? BOUNCE_ALL : BOUNCE_HEADERS); bounce_status = post_mail_fclose(bounce); } @@ -407,10 +449,12 @@ int bounce_notify_service(char *service, char *queue_name, mail_addr_postmaster(), NULL_CLEANUP_FLAGS, "BOUNCE")) != 0) { - if (!bounce_header(bounce, buf, mail_addr_postmaster(), flush) - && bounce_diagnostics(service, bounce, buf, queue_id) == 0) + if (!bounce_header(bounce, buf, mail_addr_postmaster(), + STR(boundary), flush) + && bounce_diagnostics(service, bounce, buf, + queue_id, STR(boundary)) == 0) bounce_original(service, bounce, buf, queue_name, queue_id, - BOUNCE_HEADERS); + STR(boundary), BOUNCE_HEADERS); postmaster_status = post_mail_fclose(bounce); } if (postmaster_status) @@ -432,6 +476,7 @@ int bounce_notify_service(char *service, char *queue_name, * Cleanup. */ vstring_free(buf); + vstring_free(boundary); return (bounce_status); } diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index 5f5e5a96a..851ec4eb3 100644 --- a/postfix/global/mail_version.h +++ b/postfix/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-19990402" +#define DEF_MAIL_VERSION "Snapshot-19990405" extern char *var_mail_version; /* LICENSE diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index e3689662d..0f2ff5435 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -497,6 +497,7 @@ static void mail_reset(SMTPD_STATE *state) mail_stream_cleanup(state->dest); state->dest = 0; state->cleanup = 0; + state->err = 0; } if (state->queue_id != 0) { myfree(state->queue_id); diff --git a/postfix/util/mac_parse.c b/postfix/util/mac_parse.c index 54fc6be5a..e863a2328 100644 --- a/postfix/util/mac_parse.c +++ b/postfix/util/mac_parse.c @@ -72,6 +72,7 @@ void mac_parse(const char *value, MAC_PARSE_FN action, char *context) const char *ep; /* string end pointer */ static char open_paren[] = "({"; static char close_paren[] = ")}"; + int level; #define SKIP(start, var, cond) \ for (var = start; *var && (cond); var++); @@ -92,12 +93,18 @@ void mac_parse(const char *value, MAC_PARSE_FN action, char *context) vp += 1; pp = open_paren; if (*vp == *pp || *vp == *++pp) { /* ${x} or $(x) */ + level = 1; vp += 1; - SKIP(vp, ep, *ep != close_paren[pp - open_paren]); - if (*ep == 0) - msg_fatal("incomplete macro: %s", value); - vstring_strncat(buf, vp, ep - vp); - vp = ep + 1; + for (ep = vp; level > 0; ep++) { + if (*ep == 0) + msg_fatal("incomplete macro: %s", value); + if (*ep == *pp) + level++; + if (*ep == close_paren[pp - open_paren]) + level--; + } + vstring_strncat(buf, vp, ep - vp - 1); + vp = ep; } else { /* plain $x */ SKIP(vp, ep, ISALNUM(*ep) || *ep == '_'); vstring_strncat(buf, vp, ep - vp); diff --git a/postfix/util/vbuf.c b/postfix/util/vbuf.c index 00a35c35e..66d706389 100644 --- a/postfix/util/vbuf.c +++ b/postfix/util/vbuf.c @@ -134,7 +134,7 @@ int vbuf_unget(VBUF *bp, int ch) return (VBUF_EOF); } else { bp->cnt--; - bp->flags &= ~VBUF_FLAG_ERR; + bp->flags &= ~VBUF_FLAG_EOF; return (*--bp->ptr = ch); } } diff --git a/postfix/util/vstream.c b/postfix/util/vstream.c index f6da5dbe7..f83b9ede3 100644 --- a/postfix/util/vstream.c +++ b/postfix/util/vstream.c @@ -594,6 +594,12 @@ static int vstream_buf_get_ready(VBUF *bp) if (vstream_fflush_delayed(stream)) return (VSTREAM_EOF); + /* + * Did we receive an EOF indication? + */ + if (bp->flags & VSTREAM_FLAG_EOF) + return (VSTREAM_EOF); + /* * Fill the buffer with as much data as we can handle, or with as much * data as is available right now, whichever is less. Update the cached @@ -766,6 +772,7 @@ long vstream_fseek(VSTREAM *stream, long offset, int whence) } else { bp->flags |= VSTREAM_FLAG_SEEK; } + bp->flags &= ~VSTREAM_FLAG_EOF; return (stream->offset); }