[Exim] [PATCH] MIME encapsulated bounce and autoreply messag…

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Eli Chen
Ημερομηνία:  
Προς: exim-users
Αντικείμενο: [Exim] [PATCH] MIME encapsulated bounce and autoreply messages
This is a multi-part message in MIME format.
--
I know this is on the wishlist, but I can't wait any longer. ;)

This encloses the original message in exim-generated bounce and
autoreply messages in MIME encapsulated format. The original message is
also attached to warning messages. This allows the original message to
be viewed correctly in its original language. Sendmail and Microsoft
Exchange already does this.

I didn't allow this to be a configurable option, so there might be some
work involved there. I know the MIME boundary generation code is a
little silly; any suggestions/improvements are welcome!

The attached diff is done on v. 3.32
--
diff -u -r1.3 deliver.c
--- deliver.c    2002/02/20 18:24:58    1.3
+++ deliver.c    2002/04/24 22:25:30
@@ -5224,9 +5224,12 @@
       BOOL to_sender = strcmpic(sender_address, errmsg_recipient) == 0;
       int max = (return_size_limit/DELIVER_IN_BUFFER_SIZE + 1) *
         DELIVER_IN_BUFFER_SIZE;
-
+      char mimeboundary[256];
+
       DEBUG(9) debug_printf("sending error message to: %s\n", errmsg_recipient);


+      generateMimeBoundary(mimeboundary);
+
       /* Scan the addresses for all that have the same errors_address, removing
       them from the addr_failed chain, and putting them on msgchain. */


@@ -5291,6 +5294,9 @@
       bcc = moan_check_errorcopy(errmsg_recipient);
       if (bcc != NULL) fprintf(f, "Bcc: %s\n", bcc);


+      /* Add MIME-encapsulated message headers */
+      fprintf(f, "MIME-Version: 1.0\nContent-Type: multipart/mixed;\n\tboundary=\"%s\"\n", mimeboundary);
+
       /* The texts for the message can be read from a template file; if there
       isn't one, or if it is too short, built-in texts are used. The first
       emf text is a Subject: and any other headers. */
@@ -5302,6 +5308,12 @@
           to_sender? ": returning message to sender" : "");
         }


+      /* Print MIME warning */
+      fprintf(f, "This is a MIME-encapsulated message\n\n");
+
+      /* MIME-encapsulate text */
+      fprintf(f, "--%s\n\n", mimeboundary);
+
       emf_text = next_emf(emf, "intro");
       if (emf_text != NULL) fprintf(f, "%s", emf_text); else
         {
@@ -5442,7 +5454,7 @@
       if (emf_text != NULL) fprintf(f, "%s", emf_text); else
         {
         fprintf(f,
-"------ This is a copy of the message, including all the headers. ------\n");
+"------ Attached is a copy of the message. ------\n");
         }


       /* While reading the "truncated" message, set return_size_limit to
@@ -5472,6 +5484,10 @@
         }


       fprintf(f, "\n");
+
+      /* MIME-encapsulate original message */
+      fprintf(f, "--%s\nContent-Type: message/rfc822\n\n", mimeboundary);
+
       fflush(f);
       transport_filter_argv = NULL;   /* Just in case */
       return_path = sender_address;   /* In case not previously set */
@@ -5487,6 +5503,9 @@
         fclose(emf);
         }


+      /* end MIME-encapsulation */
+      fprintf(f, "--%s--\n", mimeboundary);
+
       /* Close the file, which should send an EOF to the child process
       that is receiving the message. Wait for it to finish. */


@@ -5735,6 +5754,11 @@
       header_line *h;
       int fd;
       pid_t pid = child_open_exim(&fd);
+      int max = (return_size_limit/DELIVER_IN_BUFFER_SIZE + 1) *
+        DELIVER_IN_BUFFER_SIZE;
+      char mimeboundary[256];
+
+      generateMimeBoundary(mimeboundary);


       if (pid > 0)
         {
@@ -5761,6 +5785,9 @@
           qualify_domain_sender);
         fprintf(f, "To: %s\n", recipients);


+        /* Add MIME-encapsulated message headers */
+        fprintf(f, "MIME-Version: 1.0\nContent-Type: multipart/mixed;\n\tboundary=\"%s\"\n", mimeboundary);
+
         wmf_text = next_emf(wmf, "header");
         if (wmf_text != NULL)
           fprintf(f, "%s\n", wmf_text);
@@ -5768,6 +5795,12 @@
           fprintf(f, "Subject: Warning: message %s delayed %s\n\n",
             message_id, warnmsg_delay);


+        /* Print MIME warning */
+        fprintf(f, "This is a MIME-encapsulated message\n\n");
+
+        /* MIME-encapsulate text */
+        fprintf(f, "--%s\n\n", mimeboundary);
+
         wmf_text = next_emf(wmf, "intro");
         if (wmf_text != NULL) fprintf(f, "%s", wmf_text); else
           {
@@ -5839,6 +5872,68 @@
 "and when that happens, the message will be returned to you.\n");
           }


+        fprintf(f, "\n");
+
+        /* Now copy the message, trying to give an intelligible comment if
+           it is too long for it all to be copied. The limit isn't strictly
+           applied because of the buffering. */
+
+        wmf_text = next_emf(wmf, "copy");
+        if (wmf_text != NULL) fprintf(f, "%s", wmf_text); else
+        {
+            fprintf(f,
+                    "------ Attached is a copy of the message. ------\n");
+        }
+
+        /* While reading the "truncated" message, set return_size_limit to
+           the actual max testing value, rounded. We need to read the message
+           whether we are going to use it or not. */
+
+        {
+            int temp = return_size_limit;
+            return_size_limit = (max/1000)*1000;
+            wmf_text = next_emf(wmf, "truncated");
+            return_size_limit = temp;
+        }
+
+        if (return_size_limit > 0)
+        {
+            struct stat statbuf;
+            if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max)
+            {
+                if (wmf_text != NULL) fprintf(f, "%s", wmf_text); else
+                {
+                    fprintf(f,
+                            "------ The body of the message is %d characters long; only the first\n"
+                            "------ %d or so are included here.\n", (int)statbuf.st_size,
+                            return_size_limit);
+                }
+            }
+        }
+
+        fprintf(f, "\n");
+
+        /* MIME-encapsulate original message */
+        fprintf(f, "--%s\nContent-Type: message/rfc822\n\n", mimeboundary);
+
+        fflush(f);
+        transport_filter_argv = NULL;   /* Just in case */
+        return_path = sender_address;   /* In case not previously set */
+        transport_write_message(NULL, fileno(f), topt_add_return_path,
+                                return_size_limit, NULL, NULL, NULL, NULL, NULL, 0);
+
+        /* Write final text and close the template file if one is open */
+
+        if (wmf != NULL)
+        {
+            wmf_text = next_emf(wmf, "final");
+            if (wmf_text != NULL) fprintf(f, "%s", wmf_text);
+            fclose(wmf);
+        }
+
+        /* end MIME-encapsulation */
+        fprintf(f, "--%s--\n", mimeboundary);
+
         /* Close and wait for child process to complete, without a timeout.
         If there's an error, don't update the count. */


diff -u -r1.2 macros.h
--- macros.h    2001/11/27 05:43:44    1.2
+++ macros.h    2002/04/24 22:25:30
@@ -6,6 +6,9 @@
 /* See the file NOTICE for conditions of use and distribution. */



+/* Generate a pseudo-random MIME boundary string */
+#define generateMimeBoundary(buf)    snprintf(buf,sizeof(buf),"mimeboundary.%d.%d",time(NULL),time(NULL)*2);
+
 /* These aren't macros, but they're the sort of general definition that fits in
 this file and we need to have them defined early. Some operating systems
 (naughtily, imo) include a definition for "uchar" in the standard header files,
diff -u -r1.1.1.1 autoreply.c
--- transports/autoreply.c    2001/09/11 18:36:06    1.1.1.1
+++ transports/autoreply.c    2002/04/24 22:25:30
@@ -204,12 +204,15 @@
 time_t once_repeat;
 FILE *f;
 FILE *ff = NULL;
+char mimeboundary[256];


autoreply_transport_options_block *ob =
(autoreply_transport_options_block *)(tblock->options_block);

DEBUG(2) debug_printf("%s transport entered\n", tblock->name);

+generateMimeBoundary(mimeboundary);
+
/* Set up for the good case */

addr->transport_return = OK;
@@ -482,8 +485,18 @@
/* Add any specially requested headers */

if (headers != NULL) fprintf(f, "%s\n", headers);
+
+/* Add MIME-encapsulated message headers */
+fprintf(f, "MIME-Version: 1.0\nContent-Type: multipart/mixed;\n\tboundary=\"%s\"\n", mimeboundary);
+
fprintf(f, "\n");

+/* Print MIME warning */
+fprintf(f, "This is a MIME-encapsulated message\n\n");
+
+/* MIME-encapsulate text */
+fprintf(f, "--%s\n\n", mimeboundary);
+
 if (text != NULL)
   {
   fprintf(f, "%s", text);
@@ -522,17 +535,20 @@
     if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max)
       {
       int size = statbuf.st_size;  /* Because might be a long */
-      fprintf(f, "\n"
-"------ This is a copy of the message, including all the headers.\n"
+      fprintf(f, "\n\n"
+"------ Attached is a copy of the message.\n"
 "------ The body of the message is %d characters long; only the first\n"
 "------ %d or so are included here.\n\n", size, (max/1000)*1000);
       }
-    else fprintf(f, "\n"
-"------ This is a copy of the message, including all the headers. ------\n\n");
+    else fprintf(f, "\n\n"
+"------ Attached is a copy of the message. ------\n\n");
     }
-  else fprintf(f, "\n"
-"------ This is a copy of the message, including all the headers. ------\n\n");
+  else fprintf(f, "\n\n"
+"------ Attached is a copy of the message. ------\n\n");


+  /* MIME-encapsulate original message */
+  fprintf(f, "--%s\nContent-Type: message/rfc822\n\n", mimeboundary);
+
   fflush(f);
   transport_write_message(addr, fileno(f),
     (tblock->body_only? topt_no_headers : 0) |
@@ -543,6 +559,9 @@
     return_size_limit, tblock->add_headers, tblock->remove_headers,
     NULL, NULL, tblock->rewrite_rules, tblock->rewrite_existflags);
   }
+
+/* end MIME-encapsulation */
+fprintf(f, "--%s--\n", mimeboundary);


/* End the message and wait for the child process to end; no timeout. */



--