MAIL_SPOOL_GRP=$nmh_cv_ls_mail_grp
AC_SUBST(MAIL_SPOOL_GRP)dnl
+dnl ---------------------------------------------
+dnl CHECK FOR PROGRAM TO PROVIDE MIME TYPE STRING
+dnl ---------------------------------------------
+AS_IF([file --mime "${srcdir}"/configure >/dev/null 2>&1],
+ [nmh_mimetypeproc='"file --mime"'])
+if test x"$nmh_mimetypeproc" = x; then
+ AS_IF([file -i "${srcdir}"/configure >/dev/null 2>&1],
+ [nmh_mimetypeproc='"file -i"'])
+fi
+AS_CASE([$nmh_mimetypeproc], [?*],
+ [AC_DEFINE_UNQUOTED([MIMETYPEPROC], [$nmh_mimetypeproc],
+ [Program, with arguments, that provides MIME type string.])])
+
dnl ------------------
dnl CHECK HEADER FILES
dnl ------------------
.\"
.\" %nmhwarning%
.\"
-.TH SEND %manext1% "April 14, 2013" "%nmhversion%"
+.TH SEND %manext1% "December 22, 2013" "%nmhversion%"
.SH NAME
send \- send a message
.SH SYNOPSIS
is interpreted as a file name, and each file named is included as a separate
part in the MIME message.
.PP
-For file names with dot suffixes, the profile is scanned for a
+Determination of the content MIME type inserted into the Content-Type
+header for each part depends on how the
+.B nmh
+installation was configured. If a program, such as
+.B file
+with a
+.B --mime
+or
+.B -i
+option, was found that can specify the type of a file as a MIME type
+string, then that will be used. To determine if your
+.B nmh
+was so configured, run
+.B mhparam mimetypeproc
+and see if a non-empty string is displayed.
+.PP
+If your
+.B nmh
+was not configured with a program to specify a file type as a MIME
+string, then a different method is used to determine the content-type
+string. For file names with dot suffixes, the profile is scanned for a
.I mhshow-suffix-
entry for that suffix.
The content-type for the part is taken from that profile entry if a match is
.SH "SEE ALSO"
.IR comp (1),
.IR dist (1),
+.IR file (1),
.IR forw (1),
+.IR mhparam (1),
.IR repl (1),
.IR whatnow (1),
.IR mh\-alias (5),
. "${srcdir}/test/post/test-post-common.sh"
+# Find MIME type string, using mimetypeproc if configured with it.
+MIMETYPEPROC=`mhparam mimetypeproc`
+content_type_string() {
+ if test -z "$MIMETYPEPROC"; then
+ echo "text/plain; name=\"`basename $1`\"; charset=\"us-ascii\""
+ else
+ # 1) Excise leading filename followed by : and any whitespace.
+ # 2) Wrap charset value in double quotes. Assume that it isn't already.
+ printf "%s %s%s" \
+ `$MIMETYPEPROC $1 | sed -e 's/.*: *//' -e 's/\(charset=\)\(.*\)/\1"\2"/'`\
+ "; name=\"`basename $1`\""
+ fi
+}
+
# Customize test_post () for use with mhmail.
# $1 is expected output file, provided by caller
# $2 is mhmail switches, except for -body
See how easy it is to add an attachment!
------- =_aaaaaaaaaa0
-Content-Type: text/plain; name="attachment.txt"; charset="us-ascii"
+Content-Type: `content_type_string ${srcdir}/test/mhmail/attachment.txt`
Content-Description: attachment.txt
Content-Disposition: attachment; filename="attachment.txt"
static void clean_up_temporary_files(void);
static int get_line(void);
static void make_mime_composition_file_entry(char *, int, char *);
+static char *mime_type (const char *);
/*
char *p; /* miscellaneous string pointer */
struct stat st; /* file status buffer */
- content_type = default_content_type;
-
- /*
- * Check the file name for a suffix. Scan the context for that suffix on a
- * mhshow-suffix- entry. We use these entries to be compatible with mhnshow,
- * and there's no reason to make the user specify each suffix twice. Context
- * entries of the form "mhshow-suffix-contenttype" in the name have the suffix
- * in the field, including the dot.
- */
+ if ((content_type = mime_type (file_name)) == NULL) {
+ /*
+ * Check the file name for a suffix. Scan the context for
+ * that suffix on a mhshow-suffix- entry. We use these
+ * entries to be compatible with mhnshow, and there's no
+ * reason to make the user specify each suffix twice. Context
+ * entries of the form "mhshow-suffix-contenttype" in the name
+ * have the suffix in the field, including the dot.
+ */
+ if ((p = strrchr(file_name, '.')) != (char *)0) {
+ for (np = m_defs; np; np = np->n_next) {
+ if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0 &&
+ strcasecmp(p, np->n_field ? np->n_field : "") == 0) {
+ content_type = strdup (np->n_name + 14);
+ break;
+ }
+ }
+ }
- if ((p = strrchr(file_name, '.')) != (char *)0) {
- for (np = m_defs; np; np = np->n_next) {
- if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0 &&
- strcasecmp(p, np->n_field ? np->n_field : "") == 0) {
- content_type = np->n_name + 14;
- break;
- }
- }
+ if (content_type == NULL && default_content_type != NULL) {
+ content_type = strdup (default_content_type);
+ }
}
/*
(void)fclose(fp);
- content_type = binary ? "application/octet-stream" : "text/plain";
+ content_type =
+ strdup (binary ? "application/octet-stream" : "text/plain");
}
/*
adios ((char *)0, "unsupported attachformat %d", attachformat);
}
+ free (content_type);
+
/*
* Finish up with the file name.
*/
return;
}
+/*
+ * Try to use external command to determine mime type, and possibly
+ * encoding. Caller is responsible for free'ing returned memory.
+ */
+static char *
+mime_type (const char *file_name) {
+ char *content_type = NULL; /* mime content type */
+
+#ifdef MIMETYPEPROC
+ char cmd[2 * PATH_MAX + 2]; /* file command buffer */
+ char buf[BUFSIZ >= 2048 ? BUFSIZ : 2048];
+ FILE *fp; /* content and pipe file pointer */
+ char mimetypeproc[] = MIMETYPEPROC " '%s'";
+
+ if ((int) snprintf (cmd, sizeof cmd, mimetypeproc, file_name) <
+ (int) sizeof cmd) {
+ if ((fp = popen (cmd, "r")) != NULL) {
+ if (fgets (buf, sizeof cmd, fp)) {
+ char *cp;
+
+ /* Skip leading <filename>:<whitespace>, if present. */
+ if ((content_type = strchr (buf, ':')) != NULL) {
+ ++content_type;
+ while (*content_type && isblank (*content_type)) {
+ ++content_type;
+ }
+ } else {
+ content_type = buf;
+ }
+
+ /* Truncate at newline (LF or CR), if present. */
+ if ((cp = strpbrk (content_type, "\n\n")) != NULL) {
+ *cp = '\0';
+ }
+ } else {
+ advise (NULL, "unable to read mime type");
+ }
+ } else {
+ advise (NULL, "unable to run %s", buf);
+ }
+ } else {
+ advise (NULL, "filename to large to deduce mime type");
+ }
+#else
+ NMH_UNUSED (file_name);
+#endif
+
+ return content_type ? strdup (content_type) : NULL;
+}
+
/*
* Split large message into several messages of
* type "message/partial" and send them.