[PATCH] [RFC] Allow mutt to render an e-mail from the command-line
Background: In trying to write yet another biff app, I wanted to
create a brief summary of an e-mail. After fighting some Perl and
MIME packages, and seeing what others had done before, it soon
became clear that I was reinventing a rather large wheel. Mutt does
a wonderful job of rendering e-mail as text already, handling
multi-part messages, HTML, character set conversion, etc. The only
thing it is missing is the ability to call it from the command-line
and render an e-mail to stdout.
The attached patch adds the -r (render) flag, which accepts the
filename of a raw e-mail message. It renders the message to stdout
as you would view it in mutt, but leaves the headers intact. e.g.:
$ mutt -r <file containing raw e-mail>
I think it'd be a small, but useful addition to mutt.
I'm not familiar with the internals of mutt however, so if there's
something grossly wrong, please let me know. It works for me(tm). :)
Kind regards,
Bernard.
Index: mutt-1.5.13/copy.c
===================================================================
--- mutt-1.5.13.orig/copy.c 2007-02-02 17:45:20.000000000 +1100
+++ mutt-1.5.13/copy.c 2007-02-02 18:15:33.000000000 +1100
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
+#include <errno.h>
#include <unistd.h> /* needed for SEEK_SET under SunOS 4.1.4 */
static int address_header_decode (char **str);
@@ -748,6 +749,35 @@
return r;
}
+int mutt_render_file(FILE *fpout, char *filename)
+{
+ FILE *fpin;
+ HEADER *hdr;
+ int chflags = CH_DECODE;
+ int cmflags = M_CM_DECODE | M_CM_CHARCONV;
+ int r = -1;
+
+ if ((fpin = safe_fopen(filename, "r")) != NULL)
+ {
+ if ((hdr = maildir_parse_message (M_MH, filename, 0, NULL)) != NULL)
+ {
+ mutt_parse_part (fpin, hdr->content);
+
+ fseek(fpin, 0, SEEK_SET);
+ if (_mutt_copy_message (fpout, fpin, hdr, hdr->content, cmflags,
chflags) == 0
+ && (ferror (fpout) || feof (fpout)))
+ dprint (1, (debugfile, "_mutt_copy_message failed to detect EOF!\n"));
+ else
+ r = 0;
+ mutt_free_header(&hdr);
+ }
+ safe_fclose(&fpin);
+ }
+ else
+ mutt_error ( _("Unable to open %s: %s"), filename, strerror(errno));
+ return r;
+}
+
/* appends a copy of the given message to a mailbox
*
* dest destination mailbox
Index: mutt-1.5.13/main.c
===================================================================
--- mutt-1.5.13.orig/main.c 2007-02-02 17:45:20.000000000 +1100
+++ mutt-1.5.13/main.c 2007-02-02 18:22:06.000000000 +1100
@@ -111,6 +111,7 @@
mutt [ -nR ] [ -e <cmd> ] [ -F <file> ] -D\n\
mutt [ -nx ] [ -e <cmd> ] [ -a <file> ] [ -F <file> ] [ -H <file> ] [
-i <file> ] [ -s <subj> ] [ -b <addr> ] [ -c <addr> ] <addr> [ ... ]\n\
mutt [ -n ] [ -e <cmd> ] [ -F <file> ] -p\n\
+ mutt [ -n ] [ -e <cmd> ] [ -F <file> ] -r <file>\n\
mutt -v[v]\n");
puts _("\
@@ -136,6 +137,7 @@
puts _("\
-Q <variable>\tquery a configuration variable\n\
-R\t\topen mailbox in read-only mode\n\
+ -r <file>\trender an e-mail from the given file to stdout and exit\n\
-s <subj>\tspecify a subject (must be in quotes if it has spaces)\n\
-v\t\tshow version and compile-time definitions\n\
-x\t\tsimulate the mailx send mode\n\
@@ -531,6 +533,7 @@
LIST *commands = NULL;
LIST *queries = NULL;
LIST *alias_queries = NULL;
+ LIST *render_files = NULL;
int sendflags = 0;
int flags = 0;
int version = 0;
@@ -566,7 +569,7 @@
memset (Options, 0, sizeof (Options));
memset (QuadOptions, 0, sizeof (QuadOptions));
- while ((i = getopt (argc, argv, "A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:RvxyzZ")) !=
EOF)
+ while ((i = getopt (argc, argv, "A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:Rr:vxyzZ"))
!= EOF)
switch (i)
{
case 'A':
@@ -643,6 +646,10 @@
flags |= M_RO; /* read-only mode */
break;
+ case 'r':
+ render_files = mutt_add_list (render_files, optarg);
+ break;
+
case 's':
subject = optarg;
break;
@@ -688,7 +695,7 @@
}
/* Check for a batch send. */
- if (!isatty (0) || queries || alias_queries || dump_variables)
+ if (!isatty (0) || queries || alias_queries || dump_variables ||
render_files)
{
set_option (OPTNOCURSES);
sendflags = SENDBATCH;
@@ -731,6 +738,17 @@
}
return rv;
}
+
+ if (render_files)
+ {
+ int rv = 0;
+ for (; render_files; render_files = render_files->next)
+ {
+ if (mutt_render_file(stdout, render_files->data) != 0)
+ rv = 1;
+ }
+ return rv;
+ }
if (newMagic)
mx_set_magic (newMagic);
Index: mutt-1.5.13/mh.c
===================================================================
--- mutt-1.5.13.orig/mh.c 2007-02-02 17:45:20.000000000 +1100
+++ mutt-1.5.13/mh.c 2007-02-02 17:45:48.000000000 +1100
@@ -588,7 +588,7 @@
* Actually parse a maildir message. This may also be used to fill
* out a fake header structure generated by lazy maildir parsing.
*/
-static HEADER *maildir_parse_message (int magic, const char *fname,
+HEADER *maildir_parse_message (int magic, const char *fname,
int is_old, HEADER * _h)
{
FILE *f;
Index: mutt-1.5.13/PATCHES
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ mutt-1.5.13/PATCHES 2007-02-02 17:45:48.000000000 +1100
@@ -0,0 +1 @@
+patch-1.5.13.bb.render_flag.1
Index: mutt-1.5.13/protos.h
===================================================================
--- mutt-1.5.13.orig/protos.h 2007-02-02 17:45:20.000000000 +1100
+++ mutt-1.5.13/protos.h 2007-02-02 17:45:48.000000000 +1100
@@ -342,6 +342,7 @@
int mutt_print_attachment (FILE *, BODY *);
int mutt_query_complete (char *, size_t);
int mutt_query_variables (LIST *queries);
+int mutt_render_file(FILE *fpout, char *filename);
int mutt_save_attachment (FILE *, BODY *, char *, int, HEADER *);
int _mutt_save_message (HEADER *, CONTEXT *, int, int, int);
int mutt_save_message (HEADER *, int, int, int, int *);
@@ -364,6 +365,9 @@
int mh_valid_message (const char *);
+HEADER *maildir_parse_message (int magic, const char *fname,
+ int is_old, HEADER * _h);
+
pid_t mutt_create_filter (const char *, FILE **, FILE **, FILE **);
pid_t mutt_create_filter_fd (const char *, FILE **, FILE **, FILE **, int,
int, int);
Index: mutt-1.5.13/doc/mutt.man
===================================================================
--- mutt-1.5.13.orig/doc/mutt.man 2007-02-02 17:50:47.000000000 +1100
+++ mutt-1.5.13/doc/mutt.man 2007-02-02 17:51:37.000000000 +1100
@@ -46,6 +46,9 @@
.B mutt
[-n] [-e \fIcmd\fP] [-F \fIfile\fP] -A \fIalias\fP
.PP
+.B mutt
+[-n] [-e \fIcmd\fP] [-F \fIfile\fP] -r \fIfile\fP
+.PP
.B mutt
-v[v]
.PP
@@ -94,6 +97,8 @@
the command line have been executed.
.IP "-R"
Open a mailbox in \fIread-only\fP mode.
+.IP "-r \fIfile\fP"
+Render an e-mail from the given file to stdout and exit.
.IP "-s \fIsubject\fP"
Specify the subject of the message.
.IP "-v"