]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-19990405
authorWietse Venema <wietse@porcupine.org>
Mon, 5 Apr 1999 05:00:00 +0000 (00:00 -0500)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 03:34:04 +0000 (22:34 -0500)
postfix/HISTORY
postfix/bounce/bounce_notify_service.c
postfix/global/mail_version.h
postfix/smtpd/smtpd.c
postfix/util/mac_parse.c
postfix/util/vbuf.c
postfix/util/vstream.c

index cfdaaa5065f4f2ab4d5845d70b74629bfeb6a470..5515cf17439994a830ccd87f1676bf08502aa19f 100644 (file)
@@ -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
index ae8889bc8362ed9cb98a678d6b7a4013f2f757fb..a7f5d25673fef44ca12b3cdd4c7fc520ef6a3ec7 100644 (file)
@@ -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);
 }
index 5f5e5a96a0a560ea42e1ce4025046b0dd10eae2d..851ec4eb31bbf60d09de70a4560cb54d0e89a015 100644 (file)
@@ -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
index e3689662d426f2732bbcd2901347f11e68bce564..0f2ff5435322bed4e0f58dcecbf60339c97e8d24 100644 (file)
@@ -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);
index 54fc6be5abfc92caf7070ff1b4237d0d0066c684..e863a23284d2f718f8382a961478f39298bfed0f 100644 (file)
@@ -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);
index 00a35c35e34e61adbb35fe2665eb4bebf8561c86..66d706389067a82c4fee933f58eeb3e996155e85 100644 (file)
@@ -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);
     }
 }
index f6da5dbe749d0bd92f481a4c6c70bc6d653d6a22..f83b9ede3afa6ef22206b68c889c5fc39a434954 100644 (file)
@@ -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);
 }