Hi Brendan and all,
I rebuilt the patch after issues with diff options. Here comes the patch
for imap partial fetch.
The patch introduces imap_partial_fetch into mutt. To try it out, add the line
set imap_partial_fetch=yes
to your .muttrc file.
The code introduced here will at least partly resolve the issue related
to imap partial fetch. I often get emails which a 3.6k text part and
with 22 M of images. The proposed change will as a minimum allow users
to check the text of a message before downloading 22M of images.
The patch has been tested at least once and it builds. What's next?
Cheers,
Tilman
diff -ru muttsrc/commands.c mycleanmutt/commands.c
--- muttsrc/commands.c 2014-02-01 21:48:14.425507687 +0100
+++ mycleanmutt/commands.c 2014-02-01 22:03:15.666597898 +0100
@@ -69,7 +69,7 @@
snprintf (buf, sizeof (buf), "%s/%s", TYPE (cur->content),
cur->content->subtype);
- mutt_parse_mime_message (Context, cur);
+ mutt_parse_mime_message (Context, cur, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
mutt_message_hook (Context, cur, M_MESSAGEHOOK);
/* see if crypto is needed for this message. if so, we should exit curses */
@@ -370,7 +370,7 @@
}
if (decode)
- mutt_parse_mime_message (Context, h);
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
mutt_copy_message (fp, Context, h, cmflags, chflags);
}
@@ -402,7 +402,7 @@
if (WithCrypto && decode)
{
- mutt_parse_mime_message (Context, h);
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 :
0);
if(h->security & ENCRYPT && !crypt_valid_passphrase(h->security))
return 1;
}
@@ -427,7 +427,7 @@
if(Context->hdrs[Context->v2r[i]]->tagged)
{
mutt_message_hook (Context, Context->hdrs[Context->v2r[i]],
M_MESSAGEHOOK);
- mutt_parse_mime_message(Context, Context->hdrs[Context->v2r[i]]);
+ mutt_parse_mime_message(Context, Context->hdrs[Context->v2r[i]],
option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (Context->hdrs[Context->v2r[i]]->security & ENCRYPT &&
!crypt_valid_passphrase(Context->hdrs[Context->v2r[i]]->security))
return 1;
@@ -709,7 +709,7 @@
set_copy_flags (h, decode, decrypt, &cmflags, &chflags);
if (decode || decrypt)
- mutt_parse_mime_message (Context, h);
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if ((rc = mutt_append_message (ctx, Context, h, cmflags, chflags)) != 0)
return rc;
@@ -979,11 +979,11 @@
{
MESSAGE *msg;
int rv = 0;
-
+
h->security |= PGP_TRADITIONAL_CHECKED;
- mutt_parse_mime_message (Context, h);
- if ((msg = mx_open_message (Context, h->msgno)) == NULL)
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
+ if ((msg = mx_open_message (Context, h->msgno, 0)) == NULL)
return 0;
if (crypt_pgp_check_traditional (msg->fp, h->content, 0))
{
Only in mycleanmutt/contrib: Makefile
Only in mycleanmutt/contrib: Makefile.in
diff -ru muttsrc/copy.c mycleanmutt/copy.c
--- muttsrc/copy.c 2014-02-01 21:48:14.461489868 +0100
+++ mycleanmutt/copy.c 2014-02-01 22:03:36.686702129 +0100
@@ -682,7 +682,7 @@
MESSAGE *msg;
int r;
- if ((msg = mx_open_message (src, hdr->msgno)) == NULL)
+ if ((msg = mx_open_message (src, hdr->msgno, 1)) == NULL)
return -1;
if ((r = _mutt_copy_message (fpout, msg->fp, hdr, hdr->content, flags,
chflags)) == 0
&& (ferror (fpout) || feof (fpout)))
@@ -737,7 +737,7 @@
MESSAGE *msg;
int r;
- if ((msg = mx_open_message (src, hdr->msgno)) == NULL)
+ if ((msg = mx_open_message (src, hdr->msgno, 0)) == NULL)
return -1;
r = _mutt_append_message (dest, msg->fp, src, hdr, hdr->content, cmflags,
chflags);
mx_close_message (&msg);
diff -ru muttsrc/crypt.c mycleanmutt/crypt.c
--- muttsrc/crypt.c 2014-02-01 21:48:14.469485908 +0100
+++ mycleanmutt/crypt.c 2014-02-01 21:38:02.092787775 +0100
@@ -609,7 +609,7 @@
{
if (Context->hdrs[Context->v2r[i]]->tagged)
{
- mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]);
+ mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]],
option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (Context->hdrs[Context->v2r[i]]->security & ENCRYPT &&
!crypt_valid_passphrase (Context->hdrs[Context->v2r[i]]->security))
{
@@ -660,7 +660,7 @@
}
else
{
- mutt_parse_mime_message (Context, h);
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (!(h->security & ENCRYPT && !crypt_valid_passphrase (h->security)))
{
if ((WithCrypto & APPLICATION_PGP)
diff -ru muttsrc/imap/imap.h mycleanmutt/imap/imap.h
--- muttsrc/imap/imap.h 2014-02-01 21:48:14.577432446 +0100
+++ mycleanmutt/imap/imap.h 2014-02-01 21:38:01.812926387 +0100
@@ -57,7 +57,7 @@
/* message.c */
int imap_append_message (CONTEXT* ctx, MESSAGE* msg);
int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete);
-int imap_fetch_message (MESSAGE* msg, CONTEXT* ctx, int msgno);
+int imap_fetch_message (MESSAGE* msg, CONTEXT* ctx, int msgno, int
partial_fetch);
/* socket.c */
void imap_logout_all (void);
diff -ru muttsrc/imap/message.c mycleanmutt/imap/message.c
--- muttsrc/imap/message.c 2014-02-01 21:48:14.585428486 +0100
+++ mycleanmutt/imap/message.c 2014-02-01 21:38:01.800932328 +0100
@@ -42,6 +42,8 @@
#include "bcache.h"
+#include "mime.h"
+
static FILE* msg_cache_get (IMAP_DATA* idata, HEADER* h);
static FILE* msg_cache_put (IMAP_DATA* idata, HEADER* h);
static int msg_cache_commit (IMAP_DATA* idata, HEADER* h);
@@ -389,7 +391,7 @@
return retval;
}
-int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
+int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno, int
partial_fetch)
{
IMAP_DATA* idata;
HEADER* h;
@@ -408,15 +410,37 @@
* fails. Thanks Sam. */
short fetched = 0;
+ /* TW change 2013-12-31 f** NYE */
+ LOFF_T first_part_size = 0;
+ LOFF_T first_part_offset = 0;
+
+ /* TW change on 2014-01-01 */
+ char bs[LONG_STRING];
+ char bps[LONG_STRING];
+
idata = (IMAP_DATA*) ctx->data;
h = ctx->hdrs[msgno];
+ if(h->content->type==TYPEMULTIPART)
+ {
+ if(h->content->parts)
+ {
+ first_part_size = h->content->parts->length;
+ first_part_offset = h->content->parts->offset;
+ }
+ }
+
if ((msg->fp = msg_cache_get (idata, h)))
{
- if (HEADER_DATA(h)->parsed)
- return 0;
- else
- goto parsemsg;
+ /* either the message has been fetched already or it should be fetched
only partially */
+ if(HEADER_DATA(h)->partial==0 ||
(HEADER_DATA(h)->partial==1&&partial_fetch==1&&first_part_size<16384))
+ {
+ if (HEADER_DATA(h)->parsed) {
+ return 0;
+ } else {
+ goto parsemsg;
+ }
+ }
}
/* we still do some caching even if imap_cachedir is unset */
@@ -457,10 +481,27 @@
* command handler */
h->active = 0;
- snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA(h)->uid,
+ if(partial_fetch==1)
+ {
+ /* Added by TW on 2014-01-01 to ensure the first part of a message is all
fetched */
+ if(first_part_size<16384)
+ {
+ first_part_size=16384;
+ }
+ snprintf (bps, sizeof(bps),"BODY.PEEK[]<0.%i>",(int) first_part_size);
+ snprintf (bs, sizeof(bs), "BODY[]<0.%i>",(int) first_part_size);
+ snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA(h)->uid,
+ (mutt_bit_isset (idata->capabilities, IMAP4REV1) ?
+ (option (OPTIMAPPEEK) ? bps : bs) :
+ "RFC822"));
+ HEADER_DATA(h)->partial = 1;
+ } else {
+ snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA(h)->uid,
(mutt_bit_isset (idata->capabilities, IMAP4REV1) ?
(option (OPTIMAPPEEK) ? "BODY.PEEK[]" : "BODY[]") :
"RFC822"));
+ HEADER_DATA(h)->partial = 0;
+ }
imap_cmd_start (idata, buf);
do
@@ -568,7 +609,10 @@
fgets (buf, sizeof (buf), msg->fp);
}
- h->content->length = ftell (msg->fp) - h->content->offset;
+/* Changed by TW on 2013-12-31 to resolve the issue with wrong message sizes */
+ if(partial_fetch==0) {
+ h->content->length = ftell (msg->fp) - h->content->offset;
+ }
/* This needs to be done in case this is a multipart message */
#if defined(HAVE_PGP) || defined(HAVE_SMIME)
diff -ru muttsrc/imap/message.h mycleanmutt/imap/message.h
--- muttsrc/imap/message.h 2014-02-01 21:48:14.585428486 +0100
+++ mycleanmutt/imap/message.h 2014-02-01 21:38:01.808928368 +0100
@@ -35,6 +35,7 @@
unsigned int changed : 1;
unsigned int parsed : 1;
+ unsigned int partial : 1;
unsigned int uid; /* 32-bit Message UID */
LIST *keywords;
diff -ru muttsrc/init.h mycleanmutt/init.h
--- muttsrc/init.h 2014-02-01 21:48:14.609416606 +0100
+++ mycleanmutt/init.h 2014-02-01 21:38:02.044811544 +0100
@@ -1149,6 +1149,12 @@
** .pp
** This variable defaults to the value of $$imap_user.
*/
+ { "imap_partial_fetch", DT_BOOL, R_NONE, OPTIMAPPARTIALFETCH, 0 },
+ /*
+ ** .pp
+ ** If enabled, mutt will download only the selected part of an IMAP message.
+ ** Useful in case of IMAP messages with large attachments.
+ */
{ "imap_pass", DT_STR, R_NONE, UL &ImapPass, UL 0 },
/*
** .pp
diff -ru muttsrc/mailbox.h mycleanmutt/mailbox.h
--- muttsrc/mailbox.h 2014-02-01 21:48:14.649396799 +0100
+++ mycleanmutt/mailbox.h 2014-02-01 21:38:01.732965995 +0100
@@ -56,7 +56,7 @@
CONTEXT *mx_open_mailbox (const char *, int, CONTEXT *);
-MESSAGE *mx_open_message (CONTEXT *, int);
+MESSAGE *mx_open_message (CONTEXT *, int, int);
MESSAGE *mx_open_new_message (CONTEXT *, HEADER *, int);
void mx_fastclose_mailbox (CONTEXT *);
diff -ru muttsrc/mutt.h mycleanmutt/mutt.h
--- muttsrc/mutt.h 2014-02-01 21:48:14.677382943 +0100
+++ mycleanmutt/mutt.h 2014-02-01 21:38:02.080793721 +0100
@@ -364,6 +364,7 @@
OPTIMAPCHECKSUBSCRIBED,
OPTIMAPIDLE,
OPTIMAPLSUB,
+ OPTIMAPPARTIALFETCH,
OPTIMAPPASSIVE,
OPTIMAPPEEK,
OPTIMAPSERVERNOISE,
diff -ru muttsrc/mx.c mycleanmutt/mx.c
--- muttsrc/mx.c 2014-02-01 21:48:14.701371058 +0100
+++ mycleanmutt/mx.c 2014-02-01 21:38:02.084791736 +0100
@@ -1349,7 +1349,7 @@
}
/* return a stream pointer for a message */
-MESSAGE *mx_open_message (CONTEXT *ctx, int msgno)
+MESSAGE *mx_open_message (CONTEXT *ctx, int msgno, int partial_fetch)
{
MESSAGE *msg;
@@ -1386,7 +1386,7 @@
#ifdef USE_IMAP
case M_IMAP:
{
- if (imap_fetch_message (msg, ctx, msgno) != 0)
+ if (imap_fetch_message (msg, ctx, msgno, partial_fetch) != 0)
FREE (&msg);
break;
}
diff -ru muttsrc/parse.c mycleanmutt/parse.c
--- muttsrc/parse.c 2014-02-01 21:48:14.713365122 +0100
+++ mycleanmutt/parse.c 2014-02-01 21:38:01.645009558 +0100
@@ -649,8 +649,13 @@
}
/* in case of missing end boundary, set the length to something reasonable */
- if (last && last->length == 0 && !final)
+ if (last && last->length == 0 && !final)
+ {
last->length = end_off - last->offset;
+#ifdef USE_IMAP
+
+#endif /* USE_IMAP */
+ }
/* parse recursive MIME parts */
for(last = head; last; last = last->next)
@@ -945,7 +950,7 @@
return NULL;
}
-void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur)
+void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur, int partial_fetch)
{
MESSAGE *msg;
@@ -954,11 +959,13 @@
cur->content->type != TYPEMULTIPART)
break; /* nothing to do */
- if (cur->content->parts)
+/* changed by TW on 2014-01-02: When partial_fetch==0, the presence of the
first part of a message is no good indicator of whether the message has been
parsed earlier */
+ if (partial_fetch==0 && cur->content->parts)
break; /* The message was parsed earlier. */
- if ((msg = mx_open_message (ctx, cur->msgno)))
+ if ((msg = mx_open_message (ctx, cur->msgno, partial_fetch)))
{
+
mutt_parse_part (msg->fp, cur->content);
if (WithCrypto)
@@ -1626,7 +1633,7 @@
if (hdr->content->parts)
keep_parts = 1;
else
- mutt_parse_mime_message (ctx, hdr);
+ mutt_parse_mime_message (ctx, hdr, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (AttachAllow || AttachExclude || InlineAllow || InlineExclude)
hdr->attach_total = count_body_parts(hdr->content, M_PARTS_TOPLEVEL);
diff -ru muttsrc/pattern.c mycleanmutt/pattern.c
--- muttsrc/pattern.c 2014-02-01 21:48:14.717363138 +0100
+++ mycleanmutt/pattern.c 2014-02-01 22:02:55.074495797 +0100
@@ -155,7 +155,7 @@
char *buf;
size_t blen;
- if ((msg = mx_open_message (ctx, msgno)) != NULL)
+ if ((msg = mx_open_message (ctx, msgno, 0)) != NULL)
{
if (option (OPTTHOROUGHSRC))
{
@@ -175,7 +175,7 @@
if (pat->op != M_HEADER)
{
- mutt_parse_mime_message (ctx, h);
+ mutt_parse_mime_message (ctx, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (WithCrypto && (h->security & ENCRYPT)
&& !crypt_valid_passphrase(h->security))
diff -ru muttsrc/pgp.c mycleanmutt/pgp.c
--- muttsrc/pgp.c 2014-02-01 21:48:14.721361157 +0100
+++ mycleanmutt/pgp.c 2014-02-01 21:38:01.856904605 +0100
@@ -675,7 +675,7 @@
if (h)
{
- mutt_parse_mime_message (Context, h);
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if(h->security & PGPENCRYPT && !pgp_valid_passphrase ())
return;
}
@@ -695,7 +695,7 @@
{
if (Context->hdrs[Context->v2r[i]]->tagged)
{
- mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]);
+ mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]],
option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (Context->hdrs[Context->v2r[i]]->security & PGPENCRYPT
&& !pgp_valid_passphrase())
{
@@ -709,7 +709,7 @@
}
else
{
- mutt_parse_mime_message (Context, h);
+ mutt_parse_mime_message (Context, h, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
if (h->security & PGPENCRYPT && !pgp_valid_passphrase())
{
safe_fclose (&fpout);
Only in mycleanmutt/po: bg.gmo
Only in mycleanmutt/po: ca.gmo
Only in mycleanmutt/po: cs.gmo
Only in mycleanmutt/po: da.gmo
Only in mycleanmutt/po: de.gmo
Only in mycleanmutt/po: el.gmo
Only in mycleanmutt/po: eo.gmo
Only in mycleanmutt/po: es.gmo
Only in mycleanmutt/po: et.gmo
Only in mycleanmutt/po: eu.gmo
Only in mycleanmutt/po: fr.gmo
Only in mycleanmutt/po: ga.gmo
Only in mycleanmutt/po: gl.gmo
Only in mycleanmutt/po: hu.gmo
Only in mycleanmutt/po: id.gmo
Only in mycleanmutt/po: it.gmo
Only in mycleanmutt/po: ja.gmo
Only in mycleanmutt/po: ko.gmo
Only in mycleanmutt/po: lt.gmo
Only in mycleanmutt/po: nl.gmo
Only in mycleanmutt/po: pl.gmo
Only in mycleanmutt/po: POTFILES
Only in mycleanmutt/po: pt_BR.gmo
Only in mycleanmutt/po: ru.gmo
Only in mycleanmutt/po: sk.gmo
Only in mycleanmutt/po: sv.gmo
Only in mycleanmutt/po: tr.gmo
Only in mycleanmutt/po: uk.gmo
Only in mycleanmutt/po: zh_CN.gmo
Only in mycleanmutt/po: zh_TW.gmo
diff -ru muttsrc/postpone.c mycleanmutt/postpone.c
--- muttsrc/postpone.c 2014-02-01 21:48:15.005220570 +0100
+++ mycleanmutt/postpone.c 2014-02-01 21:38:02.116775894 +0100
@@ -536,7 +536,7 @@
memset (&s, 0, sizeof (s));
- if (!fp && (msg = mx_open_message (ctx, hdr->msgno)) == NULL)
+ if (!fp && (msg = mx_open_message (ctx, hdr->msgno, 0)) == NULL)
return (-1);
if (!fp) fp = msg->fp;
diff -ru muttsrc/protos.h mycleanmutt/protos.h
--- muttsrc/protos.h 2014-02-01 21:48:15.009218584 +0100
+++ mycleanmutt/protos.h 2014-02-01 21:38:01.716973911 +0100
@@ -222,7 +222,7 @@
void _mutt_mktemp (char *, size_t, const char *, int);
void mutt_normalize_time (struct tm *);
void mutt_paddstr (int, const char *);
-void mutt_parse_mime_message (CONTEXT *ctx, HEADER *);
+void mutt_parse_mime_message (CONTEXT *ctx, HEADER *, int);
void mutt_parse_part (FILE *, BODY *);
void mutt_perror (const char *);
void mutt_prepare_envelope (ENVELOPE *, int);
diff -ru muttsrc/recvattach.c mycleanmutt/recvattach.c
--- muttsrc/recvattach.c 2014-02-01 21:48:15.017214630 +0100
+++ mycleanmutt/recvattach.c 2014-02-01 21:38:02.096785800 +0100
@@ -950,11 +950,13 @@
int op = OP_NULL;
/* make sure we have parsed this message */
- mutt_parse_mime_message (Context, hdr);
+ /* Adapted by TW on 2014-01-02: parse the full message */
+ hdr->content->parts=NULL;
+ mutt_parse_mime_message (Context, hdr, 0);
mutt_message_hook (Context, hdr, M_MESSAGEHOOK);
- if ((msg = mx_open_message (Context, hdr->msgno)) == NULL)
+ if ((msg = mx_open_message (Context, hdr->msgno, 0)) == NULL)
return;
diff -ru muttsrc/send.c mycleanmutt/send.c
--- muttsrc/send.c 2014-02-01 21:48:15.045200762 +0100
+++ mycleanmutt/send.c 2014-02-01 21:38:01.645009558 +0100
@@ -364,7 +364,7 @@
{
int chflags = CH_DECODE, cmflags = 0;
- mutt_parse_mime_message (ctx, cur);
+ mutt_parse_mime_message (ctx, cur, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
mutt_message_hook (ctx, cur, M_MESSAGEHOOK);
if (WithCrypto && (cur->security & ENCRYPT) && option (OPTFORWDECODE))
@@ -429,7 +429,7 @@
crypt_valid_passphrase (cur->security);
}
- mutt_parse_mime_message (ctx, cur);
+ mutt_parse_mime_message (ctx, cur, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
mutt_message_hook (ctx, cur, M_MESSAGEHOOK);
mutt_make_attribution (ctx, cur, out);
diff -ru muttsrc/sendlib.c mycleanmutt/sendlib.c
--- muttsrc/sendlib.c 2014-02-01 21:48:15.049198786 +0100
+++ mycleanmutt/sendlib.c 2014-02-01 21:38:02.144762036 +0100
@@ -1288,7 +1288,7 @@
body->disposition = DISPINLINE;
body->noconv = 1;
- mutt_parse_mime_message (ctx, hdr);
+ mutt_parse_mime_message (ctx, hdr, option (OPTIMAPPARTIALFETCH) ? 1 : 0);
chflags = CH_XMIT;
cmflags = 0;
@@ -2528,7 +2528,7 @@
}
/* If we failed to open a message, return with error */
- if (!fp && (msg = mx_open_message (Context, h->msgno)) == NULL)
+ if (!fp && (msg = mx_open_message (Context, h->msgno, 0)) == NULL)
return -1;
if (!fp) fp = msg->fp;
diff -ru muttsrc/VERSION mycleanmutt/VERSION
--- muttsrc/VERSION 2014-02-01 21:48:14.397521555 +0100
+++ mycleanmutt/VERSION 2014-02-01 21:38:01.353154112 +0100
@@ -1 +1 @@
-1.5.22
+1.5.23