Hi, I already found a problem with my boundary generation code. This one's
much better because it adds the message id to the time stamp, similar to
Sendmail's method:
/* Generate a pseudo-random MIME boundary string */
-#define generateMimeBoundary(buf)
snprintf(buf,sizeof(buf),"mimeboundary.%d.%d",time(NULL),time(NULL)*2);
+#define generateMimeBoundary(buf)
snprintf(buf,sizeof(buf),"mimeboundary.%s.%d",message_id,time(NULL));
Eli
----- Original Message -----
From: "Eli Chen" <eli@???>
To: <exim-users@???>
Sent: Wednesday, April 24, 2002 4:05 PM
Subject: [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. */
>
>
>
> --
>
>
> --
>
> ## List details at http://www.exim.org/mailman/listinfo/exim-users Exim
details at
http://www.exim.org/ ##
>