I attach a patch which implements a first pass at this work. I stripped out
all the makefile, etc diff stuff to make it readable.

What this does:

- issue BODYSTRUCTURE IMAP command instead of BODY.PEEK[]
- parses the BODYSTRUCTURE response into a MIME structure associated with
  the message
- issue FETCH (RFC822.HEADER BODY[n...]) to fetch only the text part of
  the message, parse the resulting literals into msg->fp

What it doesn't yet do:

- integrate with the rest of the MIME handling in mutt.
- free the MIME structure associated with the message

This means that when we go into the MIME structure page (default key 'v',
don't know what the screen is called) it will just parse the fetched part
of the message from msg->fp, it doesn't know anything about the new MIME
structure which we can use to fetch the missing parts on demand. I need
a bit of help with this as I'm not really familiar enough with the
internal details. Also when should the message be freed so I can free the
MIME structure?

Please let me know what you think and how best to proceed.

Cheers
-- 
Chris Burdess
diff -urN mutt-1.5.21/imap/bodystructure.c mutt.work/imap/bodystructure.c
--- mutt-1.5.21/imap/bodystructure.c	1970-01-01 01:00:00.000000000 +0100
+++ mutt.work/imap/bodystructure.c	2012-03-28 10:04:51.064372212 +0100
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2012 Chris Burdess <[email protected]>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "bodystructure.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "mutt.h"
+#include "imap_private.h"
+#include "message.h"
+#include "mx.h"
+
+#ifdef HAVE_PGP
+#include "pgp.h"
+#endif
+
+#if USE_HCACHE
+#include "hcache.h"
+#endif
+
+#include "bcache.h"
+
+MIME_PART *imap_parse_part (char *pc);
+MIME_PART *imap_parse_part_list (char *pc);
+MIME_MULTIPART *imap_parse_multipart (char *pc);
+MIME_BODYPART *imap_parse_bodypart (char *pc);
+char *imap_parse_string (char *pc);
+int imap_parse_int (char *pc);
+char *imap_parse_param_list (char *pc);
+
+void imap_parse_bodystructure (MESSAGE *msg, char *pc)
+{
+    pc++; /* initial BODYSTRUCTURE lparen */
+    SKIPWS (pc);
+    msg->part = imap_parse_part (pc);
+}
+
+MIME_PART *imap_parse_part (char *pc)
+{
+    MIME_PART *part = NULL;
+
+    if (pc) {
+        part = (MIME_PART *) malloc (sizeof (MIME_PART));
+        part->number = 0;
+        if (*pc == '(')
+        {
+            part->type = MIME_PART_TYPE_MULTIPART;
+            part->part.multipart = imap_parse_multipart (pc);
+        }
+        else
+        {
+            part->type = MIME_PART_TYPE_BODYPART;
+            part->part.bodypart = imap_parse_bodypart (pc);
+        }
+    }
+    return part;
+}
+
+MIME_PART *imap_parse_part_list (char *pc)
+{
+    int number = 1;
+    MIME_PART *first = NULL;
+    MIME_PART *prev = NULL;
+    MIME_PART *cur; 
+
+    while (pc && *pc == '(') {
+        pc++;
+        SKIPWS (pc);
+        cur = imap_parse_part (pc);
+        pc = imap_skip_to_rparen (pc);
+        SKIPWS (pc);
+        if (!first)
+            first = cur;
+        else
+            prev->next = cur;
+        cur->number = number++;
+        prev = cur;
+    }
+    return first;
+}
+
+MIME_MULTIPART *imap_parse_multipart (char *pc)
+{
+    MIME_MULTIPART *multipart;
+
+    multipart = (MIME_MULTIPART *) malloc (sizeof (MIME_MULTIPART));
+    multipart->parts = imap_parse_part_list (pc);
+    while (*pc == '(')
+        pc = imap_skip_to_rparen (pc);
+    multipart->multipart_subtype = imap_parse_string (pc);
+    pc = imap_next_word (pc);
+    multipart->multipart_params = imap_parse_param_list (pc);
+    return multipart;
+}
+
+MIME_BODYPART *imap_parse_bodypart (char *pc)
+{
+    MIME_BODYPART *bodypart;
+
+    bodypart = (MIME_BODYPART *) malloc (sizeof (MIME_BODYPART));
+    bodypart->body_type = imap_parse_string (pc);
+    pc = imap_next_word (pc);
+    bodypart->body_subtype = imap_parse_string (pc);
+    pc = imap_next_word (pc);
+    bodypart->body_params = imap_parse_param_list (pc);
+    if (*pc == '(')
+        pc = imap_skip_to_rparen (pc);
+    else
+        pc = imap_next_word (pc);
+    bodypart->body_id = imap_parse_string (pc);
+    pc = imap_next_word (pc);
+    bodypart->body_description = imap_parse_string (pc);
+    pc = imap_next_word (pc);
+    bodypart->body_encoding = imap_parse_string (pc);
+    pc = imap_next_word (pc);
+    bodypart->body_size = imap_parse_int (pc);
+    pc = imap_next_word (pc);
+    if (!ascii_strncasecmp (bodypart->body_type, "message", 7))
+        bodypart->message_part = imap_parse_part_list (pc);
+    else
+        bodypart->message_part = NULL;
+    /*printf("bodypart type=%s subtype=%s size=%d\r\n",
+            bodypart->body_type,
+            bodypart->body_subtype,
+            bodypart->body_size);*/
+    return bodypart;
+}
+
+char *imap_parse_string (char *pc)
+{
+    char *start;
+    size_t len = 0;
+    char *ret;
+
+    if (!pc)
+        return NULL;
+    if (!ascii_strncasecmp ("NIL", pc, 3)) {
+        SKIPWS (pc);
+        return NULL;
+    }
+    if (*pc == '"')
+    {
+        start = ++pc;
+        while (pc && *pc != '"') {
+            pc++;
+            len++;
+        }
+        pc++;
+        SKIPWS (pc);
+        ret = (char *) malloc (len + 1);
+        strncpy ((char *) ret, start, len);
+        ret[len] = '\0';
+        return ret;
+    }
+    else
+    {
+        pc = imap_next_word (pc);
+        return NULL;
+    }
+}
+
+int imap_parse_int (char *pc)
+{
+    char *start;
+    size_t len = 0;
+    char *buf;
+    int ret;
+
+    if (!pc)
+        return 0;
+    if (!ascii_strncasecmp ("NIL", pc, 3)) {
+        SKIPWS (pc);
+        return 0;
+    }
+    start = pc++;
+    while (*pc && !ISSPACE (*pc))
+    {
+        pc++;
+        len++;
+    }
+    SKIPWS (pc);
+    buf = (char *) malloc (len + 1);
+    strncpy ((char *) buf, start, len);
+    buf[len] = '\0';
+    ret = atoi (buf);
+    free ((void *) buf);
+    return ret;
+}
+
+char *imap_parse_param_list (char *pc)
+{
+    if (!pc)
+        return NULL;
+    if (!ascii_strncasecmp ("NIL", pc, 3)) {
+        SKIPWS (pc);
+        return NULL;
+    }
+    /* TODO */
+    return NULL;
+}
+
+char *first_text_part_number (MESSAGE *msg)
+{
+    char *buf;
+    char *acc;
+    MIME_PART *part = msg->part;
+
+    buf = (char *) malloc (8);
+    acc = (char *) malloc (32);
+    sprintf (acc, "");
+    while (part)
+    {
+        if (part->type == MIME_PART_TYPE_MULTIPART)
+        {
+            if (part->number > 0)
+            {
+                sprintf (buf, "%d.", part->number);
+                strcat (acc, buf);
+            }
+            part = part->part.multipart->parts;
+        }
+        if (part->type == MIME_PART_TYPE_BODYPART)
+        {
+            if (!ascii_strncasecmp (part->part.bodypart->body_type, "text", 4))
+            {
+                sprintf (buf, "%d", part->number);
+                strcat (acc, buf);
+                free (buf);
+                return acc;
+            }
+            else
+                part = part->next;
+        }
+    }
+    return "1"; /* default to whole MIME-IMB structure */
+}
+
diff -urN mutt-1.5.21/imap/bodystructure.h mutt.work/imap/bodystructure.h
--- mutt-1.5.21/imap/bodystructure.h	1970-01-01 01:00:00.000000000 +0100
+++ mutt.work/imap/bodystructure.h	2012-03-27 18:10:04.373234694 +0100
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 Chris Burdess <[email protected]>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef BODYSTRUCTURE_H
+#define BODYSTRUCTURE_H 1
+
+#endif /* BODYSTRUCTURE_H */
diff -urN mutt-1.5.21/imap/.deps/bodystructure.Po mutt.work/imap/.deps/bodystructure.Po
--- mutt-1.5.21/imap/.deps/bodystructure.Po	1970-01-01 01:00:00.000000000 +0100
+++ mutt.work/imap/.deps/bodystructure.Po	2012-03-28 10:04:52.960372269 +0100
@@ -0,0 +1,285 @@
+bodystructure.o: bodystructure.c ../config.h bodystructure.h \
+ /usr/include/errno.h /usr/include/features.h \
+ /usr/include/x86_64-linux-gnu/bits/predefs.h \
+ /usr/include/x86_64-linux-gnu/sys/cdefs.h \
+ /usr/include/x86_64-linux-gnu/bits/wordsize.h \
+ /usr/include/x86_64-linux-gnu/gnu/stubs.h \
+ /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
+ /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/x86_64-linux-gnu/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
+ /usr/include/stdlib.h /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stddef.h \
+ /usr/include/x86_64-linux-gnu/bits/waitflags.h \
+ /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/x86_64-linux-gnu/bits/endian.h \
+ /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \
+ /usr/include/x86_64-linux-gnu/sys/types.h \
+ /usr/include/x86_64-linux-gnu/bits/types.h \
+ /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \
+ /usr/include/x86_64-linux-gnu/sys/select.h \
+ /usr/include/x86_64-linux-gnu/bits/select.h \
+ /usr/include/x86_64-linux-gnu/bits/sigset.h \
+ /usr/include/x86_64-linux-gnu/bits/time.h \
+ /usr/include/x86_64-linux-gnu/sys/sysmacros.h \
+ /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/ctype.h /usr/include/string.h \
+ /usr/include/x86_64-linux-gnu/bits/string.h \
+ /usr/include/x86_64-linux-gnu/bits/string2.h ../mutt.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdarg.h \
+ /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
+ /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \
+ /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/unistd.h \
+ /usr/include/x86_64-linux-gnu/bits/posix_opt.h \
+ /usr/include/x86_64-linux-gnu/bits/environments.h \
+ /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \
+ /usr/include/x86_64-linux-gnu/sys/stat.h \
+ /usr/include/x86_64-linux-gnu/bits/stat.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed/limits.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed/syslimits.h \
+ /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \
+ /usr/include/x86_64-linux-gnu/bits/local_lim.h \
+ /usr/include/linux/limits.h \
+ /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \
+ /usr/include/x86_64-linux-gnu/bits/xopen_lim.h /usr/include/signal.h \
+ /usr/include/x86_64-linux-gnu/bits/signum.h \
+ /usr/include/x86_64-linux-gnu/bits/siginfo.h \
+ /usr/include/x86_64-linux-gnu/bits/sigaction.h \
+ /usr/include/x86_64-linux-gnu/bits/sigcontext.h \
+ /usr/include/x86_64-linux-gnu/bits/sigstack.h \
+ /usr/include/x86_64-linux-gnu/sys/ucontext.h \
+ /usr/include/x86_64-linux-gnu/bits/sigthread.h \
+ /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/wctype.h \
+ /usr/include/pwd.h /usr/include/grp.h ../rfc822.h ../lib.h \
+ /usr/include/libintl.h /usr/include/locale.h \
+ /usr/include/x86_64-linux-gnu/bits/locale.h ../hash.h ../charset.h \
+ /usr/include/iconv.h ../mutt_regex.h /usr/include/regex.h \
+ /usr/include/x86_64-linux-gnu/gnu/option-groups.h ../ascii.h ../protos.h \
+ /usr/include/inttypes.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdint.h /usr/include/stdint.h \
+ ../mbyte.h ../globals.h imap_private.h imap.h ../account.h ../url.h \
+ ../browser.h ../mailbox.h ../mutt_curses.h /usr/include/ncurses.h \
+ /usr/include/ncurses_dll.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdbool.h \
+ /usr/include/unctrl.h /usr/include/curses.h ../mutt_socket.h \
+ ../account.h ../bcache.h ../hcache.h message.h ../mx.h ../mailbox.h
+
+../config.h:
+
+bodystructure.h:
+
+/usr/include/errno.h:
+
+/usr/include/features.h:
+
+/usr/include/x86_64-linux-gnu/bits/predefs.h:
+
+/usr/include/x86_64-linux-gnu/sys/cdefs.h:
+
+/usr/include/x86_64-linux-gnu/bits/wordsize.h:
+
+/usr/include/x86_64-linux-gnu/gnu/stubs.h:
+
+/usr/include/x86_64-linux-gnu/gnu/stubs-64.h:
+
+/usr/include/x86_64-linux-gnu/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/x86_64-linux-gnu/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.6/include/stddef.h:
+
+/usr/include/x86_64-linux-gnu/bits/waitflags.h:
+
+/usr/include/x86_64-linux-gnu/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/x86_64-linux-gnu/bits/endian.h:
+
+/usr/include/x86_64-linux-gnu/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/x86_64-linux-gnu/sys/types.h:
+
+/usr/include/x86_64-linux-gnu/bits/types.h:
+
+/usr/include/x86_64-linux-gnu/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/x86_64-linux-gnu/sys/select.h:
+
+/usr/include/x86_64-linux-gnu/bits/select.h:
+
+/usr/include/x86_64-linux-gnu/bits/sigset.h:
+
+/usr/include/x86_64-linux-gnu/bits/time.h:
+
+/usr/include/x86_64-linux-gnu/sys/sysmacros.h:
+
+/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/ctype.h:
+
+/usr/include/string.h:
+
+/usr/include/x86_64-linux-gnu/bits/string.h:
+
+/usr/include/x86_64-linux-gnu/bits/string2.h:
+
+../mutt.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdarg.h:
+
+/usr/include/x86_64-linux-gnu/bits/stdio_lim.h:
+
+/usr/include/x86_64-linux-gnu/bits/sys_errlist.h:
+
+/usr/include/x86_64-linux-gnu/bits/stdio.h:
+
+/usr/include/unistd.h:
+
+/usr/include/x86_64-linux-gnu/bits/posix_opt.h:
+
+/usr/include/x86_64-linux-gnu/bits/environments.h:
+
+/usr/include/x86_64-linux-gnu/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/x86_64-linux-gnu/sys/stat.h:
+
+/usr/include/x86_64-linux-gnu/bits/stat.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed/limits.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed/syslimits.h:
+
+/usr/include/limits.h:
+
+/usr/include/x86_64-linux-gnu/bits/posix1_lim.h:
+
+/usr/include/x86_64-linux-gnu/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/x86_64-linux-gnu/bits/posix2_lim.h:
+
+/usr/include/x86_64-linux-gnu/bits/xopen_lim.h:
+
+/usr/include/signal.h:
+
+/usr/include/x86_64-linux-gnu/bits/signum.h:
+
+/usr/include/x86_64-linux-gnu/bits/siginfo.h:
+
+/usr/include/x86_64-linux-gnu/bits/sigaction.h:
+
+/usr/include/x86_64-linux-gnu/bits/sigcontext.h:
+
+/usr/include/x86_64-linux-gnu/bits/sigstack.h:
+
+/usr/include/x86_64-linux-gnu/sys/ucontext.h:
+
+/usr/include/x86_64-linux-gnu/bits/sigthread.h:
+
+/usr/include/x86_64-linux-gnu/bits/wchar.h:
+
+/usr/include/wctype.h:
+
+/usr/include/pwd.h:
+
+/usr/include/grp.h:
+
+../rfc822.h:
+
+../lib.h:
+
+/usr/include/libintl.h:
+
+/usr/include/locale.h:
+
+/usr/include/x86_64-linux-gnu/bits/locale.h:
+
+../hash.h:
+
+../charset.h:
+
+/usr/include/iconv.h:
+
+../mutt_regex.h:
+
+/usr/include/regex.h:
+
+/usr/include/x86_64-linux-gnu/gnu/option-groups.h:
+
+../ascii.h:
+
+../protos.h:
+
+/usr/include/inttypes.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdint.h:
+
+/usr/include/stdint.h:
+
+../mbyte.h:
+
+../globals.h:
+
+imap_private.h:
+
+imap.h:
+
+../account.h:
+
+../url.h:
+
+../browser.h:
+
+../mailbox.h:
+
+../mutt_curses.h:
+
+/usr/include/ncurses.h:
+
+/usr/include/ncurses_dll.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdbool.h:
+
+/usr/include/unctrl.h:
+
+/usr/include/curses.h:
+
+../mutt_socket.h:
+
+../account.h:
+
+../bcache.h:
+
+../hcache.h:
+
+message.h:
+
+../mx.h:
+
+../mailbox.h:
diff -urN mutt-1.5.21/imap/imap_private.h mutt.work/imap/imap_private.h
--- mutt-1.5.21/imap/imap_private.h	2009-08-25 20:08:52.000000000 +0100
+++ mutt.work/imap/imap_private.h	2012-03-28 09:38:00.112322856 +0100
@@ -283,6 +283,7 @@
 char* imap_get_qualifier (char* buf);
 int imap_mxcmp (const char* mx1, const char* mx2);
 char* imap_next_word (char* s);
+char* imap_skip_to_rparen (char* s);
 time_t imap_parse_date (char* s);
 void imap_make_date (char* buf, time_t timestamp);
 void imap_qualify_path (char *dest, size_t len, IMAP_MBOX *mx, char* path);
@@ -296,6 +297,10 @@
 void imap_utf7_encode (char **s);
 void imap_utf7_decode (char **s);
 
+/* bodystructure.c */
+void imap_parse_bodystructure (MESSAGE *msg, char *pc);
+char *first_text_part_number (MESSAGE *msg);
+
 #if USE_HCACHE
 /* typedef size_t (*hcache_keylen_t)(const char* fn); */
 #define imap_hcache_keylen mutt_strlen
diff -urN mutt-1.5.21/imap/Makefile.am mutt.work/imap/Makefile.am
--- mutt-1.5.21/imap/Makefile.am	2008-12-16 18:46:06.000000000 +0000
+++ mutt.work/imap/Makefile.am	2012-03-27 17:58:11.933212869 +0100
@@ -19,7 +19,7 @@
 AM_CPPFLAGS = -I$(top_srcdir) -I../intl
 
 noinst_LIBRARIES = libimap.a
-noinst_HEADERS = auth.h imap_private.h message.h
+noinst_HEADERS = auth.h imap_private.h message.h bodystructure.h
 
 libimap_a_SOURCES = auth.c auth_login.c browse.c command.c imap.c imap.h \
-	message.c utf7.c util.c $(AUTHENTICATORS) $(GSSSOURCES)
+	message.c utf7.c util.c bodystructure.c $(AUTHENTICATORS) $(GSSSOURCES)
diff -urN mutt-1.5.21/imap/Makefile.in mutt.work/imap/Makefile.in
--- mutt-1.5.21/imap/Makefile.in	2010-08-25 17:31:48.000000000 +0100
+++ mutt.work/imap/Makefile.in	2012-03-27 17:58:56.085214220 +0100
@@ -1,9 +1,9 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -57,8 +57,8 @@
 libimap_a_AR = $(AR) $(ARFLAGS)
 libimap_a_LIBADD =
 am__libimap_a_SOURCES_DIST = auth.c auth_login.c browse.c command.c \
-	imap.c imap.h message.c utf7.c util.c auth_anon.c auth_cram.c \
-	auth_sasl.c auth_gss.c
+	imap.c imap.h message.c utf7.c util.c bodystructure.c \
+	auth_anon.c auth_cram.c auth_sasl.c auth_gss.c
 @USE_SASL_FALSE@am__objects_1 = auth_anon.$(OBJEXT) \
 @USE_SASL_FALSE@	auth_cram.$(OBJEXT)
 @USE_SASL_TRUE@am__objects_1 = auth_sasl.$(OBJEXT)
@@ -66,7 +66,7 @@
 am_libimap_a_OBJECTS = auth.$(OBJEXT) auth_login.$(OBJEXT) \
 	browse.$(OBJEXT) command.$(OBJEXT) imap.$(OBJEXT) \
 	message.$(OBJEXT) utf7.$(OBJEXT) util.$(OBJEXT) \
-	$(am__objects_1) $(am__objects_2)
+	bodystructure.$(OBJEXT) $(am__objects_1) $(am__objects_2)
 libimap_a_OBJECTS = $(am_libimap_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -232,9 +232,9 @@
 EXTRA_DIST = README TODO auth_anon.c auth_cram.c auth_gss.c auth_sasl.c
 AM_CPPFLAGS = -I$(top_srcdir) -I../intl
 noinst_LIBRARIES = libimap.a
-noinst_HEADERS = auth.h imap_private.h message.h
+noinst_HEADERS = auth.h imap_private.h message.h bodystructure.h
 libimap_a_SOURCES = auth.c auth_login.c browse.c command.c imap.c imap.h \
-	message.c utf7.c util.c $(AUTHENTICATORS) $(GSSSOURCES)
+	message.c utf7.c util.c bodystructure.c $(AUTHENTICATORS) $(GSSSOURCES)
 
 all: all-am
 
@@ -273,7 +273,7 @@
 
 clean-noinstLIBRARIES:
 	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
-libimap.a: $(libimap_a_OBJECTS) $(libimap_a_DEPENDENCIES) 
+libimap.a: $(libimap_a_OBJECTS) $(libimap_a_DEPENDENCIES) $(EXTRA_libimap_a_DEPENDENCIES) 
 	-rm -f libimap.a
 	$(libimap_a_AR) libimap.a $(libimap_a_OBJECTS) $(libimap_a_LIBADD)
 	$(RANLIB) libimap.a
@@ -290,6 +290,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_gss.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_login.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_sasl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bodystructure.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/browse.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap.Po@am__quote@
@@ -407,10 +408,15 @@
 
 installcheck: installcheck-am
 install-strip:
-	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	  `test -z '$(STRIP)' || \
-	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
 mostlyclean-generic:
 
 clean-generic:
diff -urN mutt-1.5.21/imap/message.c mutt.work/imap/message.c
--- mutt-1.5.21/imap/message.c	2010-08-24 17:34:21.000000000 +0100
+++ mutt.work/imap/message.c	2012-03-28 10:37:20.392431927 +0100
@@ -404,9 +404,11 @@
   IMAP_CACHE *cache;
   int read;
   int rc;
+  int depth;
   /* Sam's weird courier server returns an OK response even when FETCH
    * fails. Thanks Sam. */
   short fetched = 0;
+  char *tmpbuf;
 
   idata = (IMAP_DATA*) ctx->data;
   h = ctx->hdrs[msgno];
@@ -457,10 +459,12 @@
    * command handler */
   h->active = 0;
 
+  msg->part = NULL;
   snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA(h)->uid,
-	    (mutt_bit_isset (idata->capabilities, IMAP4REV1) ?
-	     (option (OPTIMAPPEEK) ? "BODY.PEEK[]" : "BODY[]") :
-	     "RFC822"));
+          (mutt_bit_isset (idata->capabilities, IMAP4REV1) ?
+           (/*option (OPTIMAPBODYSTRUCTURE)*/1 ? "BODYSTRUCTURE" : 
+            (option (OPTIMAPPEEK) ? "BODY.PEEK[]" : "BODY[]")) :
+           "RFC822"));
 
   imap_cmd_start (idata, buf);
   do
@@ -476,50 +480,149 @@
     {
       while (*pc)
       {
-	pc = imap_next_word (pc);
-	if (pc[0] == '(')
-	  pc++;
-	if (ascii_strncasecmp ("UID", pc, 3) == 0)
-	{
-	  pc = imap_next_word (pc);
-	  uid = atoi (pc);
-	  if (uid != HEADER_DATA(h)->uid)
-	    mutt_error (_("The message index is incorrect. Try reopening the mailbox."));
-	}
-	else if ((ascii_strncasecmp ("RFC822", pc, 6) == 0) ||
-		 (ascii_strncasecmp ("BODY[]", pc, 6) == 0))
-	{
-	  pc = imap_next_word (pc);
-	  if (imap_get_literal_count(pc, &bytes) < 0)
-	  {
-	    imap_error ("imap_fetch_message()", buf);
-	    goto bail;
-	  }
-	  mutt_progress_init (&progressbar, _("Fetching message..."),
-			      M_PROGRESS_SIZE, NetInc, bytes);
-	  if (imap_read_literal (msg->fp, idata, bytes, &progressbar) < 0)
-	    goto bail;
-	  /* pick up trailing line */
-	  if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
-	    goto bail;
-	  pc = idata->buf;
-
-	  fetched = 1;
-	}
-	/* UW-IMAP will provide a FLAGS update here if the FETCH causes a
-	 * change (eg from \Unseen to \Seen).
-	 * Uncommitted changes in mutt take precedence. If we decide to
-	 * incrementally update flags later, this won't stop us syncing */
-	else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed)
-	{
-	  if ((pc = imap_set_flags (idata, h, pc)) == NULL)
-	    goto bail;
-	}
+        pc = imap_next_word (pc);
+        if (pc[0] == '(')
+          pc++;
+        if (ascii_strncasecmp ("UID", pc, 3) == 0)
+        {
+          pc = imap_next_word (pc);
+          uid = atoi (pc);
+          if (uid != HEADER_DATA(h)->uid)
+            mutt_error (_("The message index is incorrect. Try reopening the mailbox."));
+        }
+        else if ((ascii_strncasecmp ("RFC822", pc, 6) == 0) ||
+                (ascii_strncasecmp ("BODY[]", pc, 6) == 0))
+        {
+          pc = imap_next_word (pc);
+          if (imap_get_literal_count(pc, &bytes) < 0)
+          {
+            imap_error ("imap_fetch_message()", buf);
+            goto bail;
+          }
+          mutt_progress_init (&progressbar, _("Fetching message..."),
+                  M_PROGRESS_SIZE, NetInc, bytes);
+          if (imap_read_literal (msg->fp, idata, bytes, &progressbar) < 0)
+            goto bail;
+          /* pick up trailing line */
+          if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
+            goto bail;
+          pc = idata->buf;
+
+          fetched = 1;
+        }
+        /* UW-IMAP will provide a FLAGS update here if the FETCH causes a
+         * change (eg from \Unseen to \Seen).
+         * Uncommitted changes in mutt take precedence. If we decide to
+         * incrementally update flags later, this won't stop us syncing */
+        else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed)
+        {
+          if ((pc = imap_set_flags (idata, h, pc)) == NULL)
+            goto bail;
+        }
+        else if (ascii_strncasecmp ("BODYSTRUCTURE", pc, 13) == 0)
+        {
+          pc = imap_next_word (pc);
+          imap_parse_bodystructure (msg, pc);
+          pc = imap_skip_to_rparen (pc);
+        }
       }
     }
   }
   while (rc == IMAP_CMD_CONTINUE);
 
+  if (msg->part)
+  {
+    /* Load the first text part of the message */
+    char cmdbuf[32];
+    snprintf (cmdbuf, sizeof (cmdbuf), option (OPTIMAPPEEK) ? "BODY.PEEK[%s]" : "BODY[%s]", first_text_part_number (msg));
+    snprintf (buf, sizeof (buf), "UID FETCH %u (RFC822.HEADER %s)", HEADER_DATA(h)->uid, cmdbuf);
+    imap_cmd_start (idata, buf);
+    do
+    {
+      if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
+        break;
+
+      pc = idata->buf;
+      pc = imap_next_word (pc);
+      pc = imap_next_word (pc);
+      sprintf (msg->fp, "");
+
+      if (!ascii_strncasecmp ("FETCH", pc, 5))
+      {
+        while (*pc)
+        {
+          pc = imap_next_word (pc);
+          if (pc[0] == '(')
+            pc++;
+          if (ascii_strncasecmp ("UID", pc, 3) == 0)
+          {
+            pc = imap_next_word (pc);
+            uid = atoi (pc);
+            if (uid != HEADER_DATA(h)->uid)
+              mutt_error (_("The message index is incorrect. Try reopening the mailbox."));
+          }
+          else if (ascii_strncasecmp ("RFC822.HEADER", pc, 13) == 0)
+          {
+            pc = imap_next_word (pc);
+            if (imap_get_literal_count(pc, &bytes) < 0)
+            {
+              imap_error ("imap_fetch_message()", buf);
+              goto bail;
+            }
+            mutt_progress_init (&progressbar, _("Fetching message header..."),
+                    M_PROGRESS_SIZE, NetInc, bytes);
+            /*tmpbuf = (char *) malloc (bytes + 1);*/
+            rc = imap_read_literal (msg->fp, idata, bytes, &progressbar);
+            /*if (rc >= 0)
+              strcat (msg->fp, tmpbuf);
+            free (tmpbuf);*/
+            if (rc < 0)
+              goto bail;
+            /* pick up trailing line */
+            if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
+              goto bail;
+            pc = idata->buf;
+          }
+          else if (ascii_strncasecmp ("BODY[", pc, 5) == 0)
+          {
+            pc = imap_next_word (pc);
+            if (imap_get_literal_count(pc, &bytes) < 0)
+            {
+              imap_error ("imap_fetch_message()", buf);
+              goto bail;
+            }
+            mutt_progress_init (&progressbar, _("Fetching message..."),
+                    M_PROGRESS_SIZE, NetInc, bytes);
+            /*tmpbuf = (char *) malloc (bytes + 1);*/
+            rc = imap_read_literal (msg->fp, idata, bytes, &progressbar);
+            /*if (rc >= 0)
+              strcat (msg->fp, tmpbuf);
+            free (tmpbuf);*/
+            if (rc < 0)
+              goto bail;
+            /* pick up trailing line */
+            if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
+              goto bail;
+            pc = idata->buf;
+
+            fetched = 1;
+          }
+          /* UW-IMAP will provide a FLAGS update here if the FETCH causes a
+           * change (eg from \Unseen to \Seen).
+           * Uncommitted changes in mutt take precedence. If we decide to
+           * incrementally update flags later, this won't stop us syncing */
+          else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed)
+          {
+            if ((pc = imap_set_flags (idata, h, pc)) == NULL)
+              goto bail;
+          }
+        }
+      }
+    }
+    while (rc == IMAP_CMD_CONTINUE);
+  }
+
+
   /* see comment before command start. */
   h->active = 1;
 
diff -urN mutt-1.5.21/imap/util.c mutt.work/imap/util.c
--- mutt-1.5.21/imap/util.c	2010-08-24 17:34:21.000000000 +0100
+++ mutt.work/imap/util.c	2012-03-28 08:45:30.016226355 +0100
@@ -532,6 +532,33 @@
   return s;
 }
 
+char *imap_skip_to_rparen (char *s)
+{
+  int quoted = 0;
+  int depth = 0;
+
+  do
+  {
+    if (!quoted && *s == '(')
+      depth++;
+    else if (!quoted && *s == ')')
+      depth--;
+    else if (*s == '\\')
+    {
+      s++;
+      if (*s)
+        s++;
+      continue;
+    }
+    else if (*s == '\"')
+      quoted = quoted ? 0 : 1;
+    s++;
+  }
+  while (depth > 0 && s && *s);
+  SKIPWS (s);
+  return s;
+}
+
 /* imap_parse_date: date is of the form: DD-MMM-YYYY HH:MM:SS +ZZzz */
 time_t imap_parse_date (char *s)
 {
diff -urN mutt-1.5.21/init.h mutt.work/init.h
--- mutt-1.5.21/init.h	2010-09-15 16:39:31.000000000 +0100
+++ mutt.work/init.h	2012-03-27 18:00:06.745216386 +0100
@@ -1075,6 +1075,13 @@
   ** the previous methods are unavailable. If a method is available but
   ** authentication fails, mutt will not connect to the IMAP server.
   */
+  { "imap_bodystructure", DT_BOOL, R_NONE, OPTIMAPBODYSTRUCTURE, 0 },
+  /*
+  ** .pp
+  ** This contains the list of characters which you would like to treat
+  ** as folder separators for displaying IMAP paths. In particular it
+  ** helps in using the ``='' shortcut for your \fIfolder\fP variable.
+  */
   { "imap_check_subscribed",  DT_BOOL, R_NONE, OPTIMAPCHECKSUBSCRIBED, 0 },
   /*
    ** .pp
diff -urN mutt-1.5.21/mailbox.h mutt.work/mailbox.h
--- mutt-1.5.21/mailbox.h	2009-04-30 18:33:48.000000000 +0100
+++ mutt.work/mailbox.h	2012-03-27 17:58:05.717212676 +0100
@@ -40,6 +40,43 @@
   M_FLAGS               /* nondestructive flags change (IMAP) */
 };
 
+#define MIME_PART_TYPE_BODYPART 1
+#define MIME_PART_TYPE_MULTIPART 2
+
+typedef struct MIME_PART MIME_PART;
+typedef struct MIME_BODYPART MIME_BODYPART;
+typedef struct MIME_MULTIPART MIME_MULTIPART;
+
+struct MIME_BODYPART
+{
+  const char *body_type;    /* text, image, application, etc */
+  const char *body_subtype; /* plain, html, png etc */
+  const char *body_params;  /* list of parameter pairs */
+  const char *body_id;      /* content id */
+  const char *body_description;
+  const char *body_encoding;/* transfer encoding */
+  int body_size;            /* encoded size (may be an estimate) */
+  MIME_PART *message_part;  /* if body_type is message */
+};
+
+struct MIME_MULTIPART
+{
+  MIME_PART *parts;              /* list of parts in this multipart */
+  const char *multipart_subtype; /* mixed, digest, alternative, etc */
+  const char *multipart_params;  /* list of parameter pairs */
+};
+
+struct MIME_PART
+{
+  short number; /* number of this part within its container */
+  short type;   /* MIME_PART_TYPE_BODYPART | MIME_PART_TYPE_MULTIPART */
+  MIME_PART *next;
+  union {
+    MIME_BODYPART *bodypart;
+    MIME_MULTIPART *multipart;
+  } part;
+};
+
 typedef struct
 {
   FILE *fp;	/* pointer to the message data */
@@ -52,6 +89,7 @@
     unsigned replied : 1;
   } flags;
   time_t received;	/* the time at which this message was received */
+  MIME_PART *part;     /* MIME part of this message */
 } MESSAGE;
 
 CONTEXT *mx_open_mailbox (const char *, int, CONTEXT *);
diff -urN mutt-1.5.21/mutt.h mutt.work/mutt.h
--- mutt-1.5.21/mutt.h	2010-09-13 18:19:55.000000000 +0100
+++ mutt.work/mutt.h	2012-03-27 18:00:02.233216247 +0100
@@ -368,6 +368,7 @@
   OPTIMAPPASSIVE,
   OPTIMAPPEEK,
   OPTIMAPSERVERNOISE,
+  OPTIMAPBODYSTRUCTURE,
 #endif
 #if defined(USE_SSL)
 # ifndef USE_SSL_GNUTLS

Reply via email to