summaryrefslogtreecommitdiff
path: root/mail/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/decode.c')
-rw-r--r--mail/decode.c182
1 files changed, 153 insertions, 29 deletions
diff --git a/mail/decode.c b/mail/decode.c
index 6f20ae2cd..76d9f4e00 100644
--- a/mail/decode.c
+++ b/mail/decode.c
@@ -1,5 +1,5 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999-2019 Free Software Foundation, Inc.
+ Copyright (C) 1999-2024 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
/*
FIXME:
decode, this is temporary, until the API on how to present
- mime/attachements etc is less confusing.
+ mime/attachments etc is less confusing.
*/
struct decode_closure
@@ -41,7 +41,8 @@ mail_decode (int argc, char **argv)
msgset_t *msgset;
struct decode_closure decode_closure;
- if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT, &msgset))
+ if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT|MSG_ALLOWPART,
+ &msgset))
return 1;
decode_closure.select_hdr = mu_islower (argv[0][0]);
@@ -73,7 +74,7 @@ display_message (mu_message_t mesg, msgset_t *msgset, void *arg)
mime_descend (&mclos, display_submessage, NULL);
/* Mark enclosing message as read */
- if (mu_mailbox_get_message (mbox, msgset->msg_part[0], &mesg) == 0)
+ if (mu_mailbox_get_message (mbox, msgset_msgno (msgset), &mesg) == 0)
util_mark_read (mesg);
return 0;
@@ -121,41 +122,22 @@ display_headers (mu_stream_t out, mu_message_t mesg,
}
}
-void
-format_msgset (mu_stream_t str, const msgset_t *msgset, size_t *count)
-{
- int i;
- mu_stream_stat_buffer stat;
-
- if (count)
- mu_stream_set_stat (str, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT),
- stat);
- mu_stream_printf (str, "%lu", (unsigned long) msgset->msg_part[0]);
- for (i = 1; i < msgset->npart; i++)
- mu_stream_printf (str, "[%lu", (unsigned long) msgset->msg_part[i]);
- for (i = 1; i < msgset->npart; i++)
- mu_stream_printf (str, "]");
- if (count)
- {
- *count = stat[MU_STREAM_STAT_OUT];
- mu_stream_set_stat (str, 0, NULL);
- }
-}
-
static void
display_part_header (mu_stream_t str, const msgset_t *msgset,
const char *type, const char *encoding)
{
int size = util_screen_columns () - 3;
unsigned int i;
-
+ char *msp;
+
mu_stream_printf (str, "+");
for (i = 0; (int)i <= size; i++)
mu_stream_printf (str, "-");
mu_stream_printf (str, "+");
mu_stream_printf (str, "\n");
- mu_stream_printf (str, "%s", _("| Message="));
- format_msgset (str, msgset, NULL);
+ msp = msgset_str (msgset);
+ mu_stream_printf (str, _("| Message=%s"), msp);
+ free (msp);
mu_stream_printf (str, "\n");
mu_stream_printf (str, _("| Type=%s\n"), type);
@@ -226,12 +208,69 @@ mime_descend (struct mime_descend_closure *closure,
{
mu_message_t submsg = NULL;
- if (mu_message_unencapsulate (closure->message, &submsg, NULL) == 0)
+ switch (mu_message_unencapsulate (closure->message, &submsg, NULL))
{
+ case 0:
subclosure.hints = MDHINT_SELECTED_HEADERS;
subclosure.msgset = closure->msgset;
subclosure.message = submsg;
status = mime_descend (&subclosure, fun, data);
+ break;
+
+ case MU_ERR_INVALID_EMAIL:
+ /*
+ * The mu_message_unencapsulate function returns this code
+ * if it was unable to parse the message body as a RFC822
+ * message (this code is propagated from mu_stream_to_message,
+ * which does the actual work).
+ *
+ * If the enclosing message(part) is of message/digest type, it
+ * is possible that messages are packed into it without MIME
+ * headers. That violates RFC 1341, but such digests are
+ * reported to exist (re. email conversation with Karl on
+ * 2020-08-07, <202008070138.0771cfHn003390@freefriends.org>).
+ *
+ * Try to see whether the part has one of the normal RFC822 headers
+ * and if so treat it as the message. Otherwise, treat it as
+ * text/plain.
+ *
+ * FIXME: Do all this only if the upper-level message is of
+ * message/digest type.
+ */
+ {
+ char *names[] = { "From", "To", "Subject" };
+ mu_header_t hdr;
+
+ if (mu_message_get_header (closure->message, &hdr) == 0 &&
+ mu_header_sget_firstof (hdr, names, NULL, NULL) == 0)
+ {
+ mu_stream_t str;
+ if (mu_message_get_streamref (closure->message, &str) == 0)
+ {
+ status = mu_stream_to_message (str, &submsg);
+ mu_stream_unref (str);
+ if (status == 0)
+ {
+ mu_header_t subhdr;
+ if (mu_message_get_header (submsg, &subhdr) == 0)
+ {
+ mu_header_remove (subhdr,
+ MU_HEADER_CONTENT_TYPE, 1);
+ subclosure.hints = MDHINT_SELECTED_HEADERS;
+ subclosure.msgset = closure->msgset;
+ subclosure.message = submsg;
+ status = mime_descend (&subclosure, fun, data);
+ break;
+ }
+ }
+ }
+ }
+ }
+ /* FALLTHROUGH */
+
+ default:
+ /* Treat as text/plain */
+ status = fun (closure, data);
}
}
else
@@ -449,3 +488,88 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg)
sigaction (SIGQUIT, &savequit, NULL);
sigprocmask (SIG_SETMASK, &savemask, NULL);
}
+
+/* print_message_body(msg, out, stat)
+ *
+ * Prints the body of the message MSG to the output stream OUT. If
+ * the Content-Transfer-Encoding header is set, the body is decoded.
+ * If stat is not NULL, it must point to an array of two size_t.
+ * Upon return stat[0] will contain the number of bytes and stat[1]
+ * the number of newline characters written to the output.
+ */
+int
+print_message_body (mu_message_t msg, mu_stream_t out, size_t *stat)
+{
+ int rc;
+ mu_header_t hdr;
+ mu_body_t body;
+ mu_stream_t d_stream;
+ mu_stream_t stream;
+ char *encoding = NULL;
+ mu_stream_stat_buffer sb;
+
+ rc = mu_message_get_header (msg, &hdr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header",
+ NULL, rc);
+ return rc;
+ }
+
+ rc = mu_message_get_body (msg, &body);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_body",
+ NULL, rc);
+ return rc;
+ }
+
+ rc = mu_body_get_streamref (body, &stream);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_body_get_streamref",
+ NULL, rc);
+ return rc;
+ }
+
+ util_get_hdr_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING, &encoding);
+ if (encoding == NULL || *encoding == '\0')
+ /* No need to filter */;
+ else if ((rc = mu_filter_create (&d_stream, stream, encoding,
+ MU_FILTER_DECODE, MU_STREAM_READ)) == 0)
+ {
+ mu_stream_unref (stream);
+ stream = d_stream;
+ }
+ else
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_body",
+ encoding, rc);
+ /* FIXME: continue anyway? */
+ }
+
+ if (stat)
+ {
+ mu_stream_set_stat (stream,
+ MU_STREAM_STAT_MASK (MU_STREAM_STAT_IN) |
+ MU_STREAM_STAT_MASK (MU_STREAM_STAT_INLN),
+ sb);
+ }
+ rc = mu_stream_copy (out, stream, 0, NULL);
+
+ mu_stream_destroy (&stream);
+ free (encoding);
+
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_copy",
+ encoding, rc);
+ }
+ else if (stat)
+ {
+ stat[0] = sb[MU_STREAM_STAT_IN];
+ stat[1] = sb[MU_STREAM_STAT_INLN];
+ }
+
+ return rc;
+}

Return to:

Send suggestions and report system problems to the System administrator.