send: Always MIMEify and pass already MIMIfied drafts through
authormarkus schnalke <meillo@marmaro.de>
Fri, 5 Aug 2016 19:46:55 +0000 (21:46 +0200)
committermarkus schnalke <meillo@marmaro.de>
Fri, 5 Aug 2016 19:53:22 +0000 (21:53 +0200)
Even if technically not necessary, MIMEify the draft. This simplifies
the code at hardly any cost.

To still be able to create arbitrary complex MIME structures, make
send(1) pass already MIMEified drafts through, without automatically
invoking mhbuild(1) on them a second time (which would fail). This
way, you can manually invoke mhbuild(1) and afterward call send(1)
... and everything will work just as expected.

Also documented this in the man page, and additionally added a
paragraph about the signing and encrypting feature of send(1), which
wasn't documented yet.

man/send.man1
uip/send.c

index 02e64fe..7367610 100644 (file)
@@ -34,17 +34,18 @@ Most of the features attributed to
 are actually performed by
 .BR spost .
 .PP
-The draft is scanned for attachment header fields.
+Unless a
+.I MIME-Version
+header is already present, the message is converted to a MIME message.
+In this process, the draft is scanned for attachment header fields.
 Their name defaults to ``Attach'', but may be changed by the value of the
 .I Attachment-Header
 profile entry.
-If such header fields are found, or the body contains non-ASCII characters,
-the message is converted to a MIME message.
-This conversion occurs before all other processing.
+If such header fields are found, the body of each is interpreted as a
+file name (or a message specification), and each of these files or
+messages is included as a separate part in the MIME message.
+(The first part of the MIME message is the draft body.)
 .PP
-The first part of the MIME message is the draft body if the body is non-empty.
-The body of each attachment header field is interpreted as a file name,
-and each file named is included as a separate part in the MIME message.
 .PP
 The MIME type of each file is determined by the MIME type query program,
 as defined by the
@@ -58,11 +59,39 @@ The last component of the path name is taken as the name of the MIME parts.
 A message part header for an attachment might be:
 .PP
 .nf
-Content-Type: text/plain; name="VERSION"; charset="us-ascii"
-Content-Description: VERSION
-Content-Disposition: attachment; filename="VERSION"
+Content-Type: text/plain; name="README"; charset="us-ascii"
+Content-Description: README
+Content-Disposition: attachment; filename="README"
 .fi
 .PP
+This conversion occurs before all other processing.
+.PP
+If, however, a
+.I MIME-Version
+header field is already present in the draft, no such conversion
+will be done. This way, it is possible to access the full
+capabilities of
+.B mhbuild
+to create elaborate MIME structures, which reach way beyond the
+attachment system's capabilities.
+If
+.B mhbuild
+was invoked on the draft beforehand (e.g. at the Whatnow prompt),
+then
+.B send
+will use this already MIMEified draft as is.
+.PP
+As a second conversion step,
+.B send
+searches for
+.I Sign
+and
+.I Enc
+header fields, and if found, invokes
+.B mhsign
+to sign and encrypt the message. Signing and encrypting is done
+independently of the MIME conversion.
+.PP
 If
 .B \-verbose
 is specified,
@@ -160,12 +189,15 @@ for more information.
 ^Draft\-Folder:~^To set the default draft\-folder
 ^Aliasfile:~^For a default alias file
 ^Signature:~^To determine the user's mail signature
-^Attachment\-Header:~^To set the name of the attachment header field
+^Attachment\-Header:~^The name of the attachment header field
+^Sign\-Header:~^The name of the sign request header field
+^Enc\-Header:~^The name of the encryption request header field
 ^Mime\-Type\-Query:~^Program to determine the MIME types of files
 .fi
 
 .SH "SEE ALSO"
-comp(1), dist(1), forw(1), repl(1), mh\-alias(5), spost(8)
+comp(1), dist(1), forw(1), repl(1), mh\-alias(5), mhbuild(1),
+mhsign(1), spost(8)
 
 .SH DEFAULTS
 .nf
index c1665b2..9ad124f 100644 (file)
@@ -268,6 +268,7 @@ sendsbr(char **vec, int vecp, char *drft, struct stat *st)
        */
        switch (attach(drft)) {
        case OK:
+               /* successfully MIMEified: use generate draft */
                drft = composition_file_name;
                break;
 
@@ -275,6 +276,7 @@ sendsbr(char **vec, int vecp, char *drft, struct stat *st)
                return (NOTOK);
 
        case DONE:
+               /* already in MIME format: keep original draft */
                break;
        }
 
@@ -327,27 +329,11 @@ sendsbr(char **vec, int vecp, char *drft, struct stat *st)
 }
 
 static int
-contains_non_ascii(char *str)
-{
-       unsigned char *cp;
-
-       for (cp = str; *cp; cp++) {
-               if (*cp > 127) {
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-static int
 attach(char *draft_file_name)
 {
        char buf[MAXPATHLEN + 6];
        int c;
-       int has_attachment;
-       int has_body = 0;
-       int non_ascii = 0; /* msg body or hdr contains non-ASCII chars */
-       int length;  /* length of attachment header field name */
+       int length = strlen(attach_hdr);
        char *p;
 
        if (!(draft_file = fopen(draft_file_name, "r"))) {
@@ -358,47 +344,7 @@ attach(char *draft_file_name)
        field = mh_xcalloc(field_size = 256, sizeof(char));
 
        /*
-       ** Scan the draft file for an attachment header field name.
-       */
-       length = strlen(attach_hdr);
-       has_attachment = 0;
-       while (get_line() != EOF && *field != '\0' && *field != '-') {
-               if (strncasecmp(field, attach_hdr, length)==0 &&
-                               field[length] == ':') {
-                       has_attachment = 1;
-               }
-               if (contains_non_ascii(field)) {
-                       non_ascii = 1;
-               }
-       }
-
-       /*
-       ** Look for at least one non-blank line in the body of the
-       ** message which indicates content in the body.
-       ** Check if body contains at least one non-blank (= not empty)
-       ** and if it contains any non-ASCII chars (= need MIME).
-       */
-       while (get_line() != EOF) {
-               if (contains_non_ascii(field)) {
-                       non_ascii = 1;
-               }
-               for (p = field; *p; p++) {
-                       if (isgraph(*p)) {
-                               has_body = 1;
-                       }
-               }
-               if (has_body && non_ascii) {
-                       break;  /* that's been already enough information */
-               }
-       }
-
-       if (!has_attachment && non_ascii==0) {
-               /* We don't need to convert it to MIME. */
-               return DONE;
-       }
-
-       /*
-       ** Else: mimify
+       ** MIMEify
        */
 
        /* Make names for the temporary files.  */
@@ -409,12 +355,10 @@ attach(char *draft_file_name)
                        m_mktemp(toabsdir(invo_name), NULL, NULL),
                        sizeof (composition_file_name));
 
-       if (has_body) {
-               body_file = fopen(body_file_name, "w");
-       }
+       body_file = fopen(body_file_name, "w");
        composition_file = fopen(composition_file_name, "w");
 
-       if ((has_body && !body_file) || !composition_file) {
+       if (!body_file || !composition_file) {
                clean_up_temporary_files();
                adios(EX_IOERR, NULL, "unable to open all of the temporary files.");
        }
@@ -422,6 +366,16 @@ attach(char *draft_file_name)
        /* Copy non-attachment header fields to the temp composition file. */
        rewind(draft_file);
        while (get_line() != EOF && *field && *field != '-') {
+               if (strncasecmp(field, VRSN_FIELD, strlen(VRSN_FIELD))==0 &&
+                               field[strlen(VRSN_FIELD)] == ':') {
+                       /*
+                       ** The draft is already in MIME format, thus
+                       ** back out and use the original draft file.
+                       */
+                       clean_up_temporary_files();
+                       return DONE;
+               }
+
                if (strncasecmp(field, attach_hdr, length) != 0 ||
                                field[length] != ':') {
                        fprintf(composition_file, "%s\n", field);
@@ -429,17 +383,15 @@ attach(char *draft_file_name)
        }
        fputs("--------\n", composition_file);
 
-       if (has_body) {
-               /* Copy the message body to the temporary file. */
-               while ((c = getc(draft_file)) != EOF) {
-                       putc(c, body_file);
-               }
-               fclose(body_file);
-
-               /* Add a mhbuild MIME composition file line for the body */
-               /* charset will be discovered/guessed by mhbuild */
-               fprintf(composition_file, "#text/plain %s\n", body_file_name);
+       /* Copy the message body to the temporary file. */
+       while ((c = getc(draft_file)) != EOF) {
+               putc(c, body_file);
        }
+       fclose(body_file);
+
+       /* Add a mhbuild MIME composition file line for the body */
+       /* charset will be discovered/guessed by mhbuild */
+       fprintf(composition_file, "#text/plain %s\n", body_file_name);
 
        /*
        ** Now, go back to the beginning of the draft file and look for
@@ -681,7 +633,6 @@ sendaux(char **vec, int vecp, char *drft, struct stat *st)
                }
        }
 
-
        return status ? NOTOK : status;
 }