From: Marcin Niestroj <macius19...@gmail.com>

It turns out that some IMAP servers do not return messages in
ascending UID order to a UID FETCH request. Below is a log fragment
that shows `mbsync -D -a` on poczta.o2.pl mail server:

  M: * 502 FETCH (UID 1221 FLAGS (\Seen))
  M: * 164 FETCH (UID 164 FLAGS (\Seen))
  M: * 1035 FETCH (UID 4377 FLAGS (\Seen))
  M: * 715 FETCH (UID 2275 FLAGS (\Seen))
  M: * 668 FETCH (UID 2005 FLAGS (\Seen))
  M: * 15 FETCH (UID 15 FLAGS (\Seen))
  M: * 393 FETCH (UID 427 FLAGS (\Seen))
  M: * 801 FETCH (UID 2854 FLAGS (\Seen))
  M: * 764 FETCH (UID 2620 FLAGS (\Seen))
  M: * 583 FETCH (UID 1593 FLAGS (\Seen))
  M: * 572 FETCH (UID 1564 FLAGS (\Seen))
  M: * 457 FETCH (UID 934 FLAGS (\Seen))
  M: * 67 FETCH (UID 67 FLAGS (\Seen \Answered))
  ...
  uid= 1221, flags=   S, size=     0, tuid=?
  uid=  164, flags=   S, size=     0, tuid=?
  uid= 4377, flags=   S, size=     0, tuid=?
  uid= 2275, flags=   S, size=     0, tuid=?
  uid= 2005, flags=   S, size=     0, tuid=?
  uid=   15, flags=   S, size=     0, tuid=?
  uid=  427, flags=   S, size=     0, tuid=?
  uid= 2854, flags=   S, size=     0, tuid=?
  uid= 2620, flags=   S, size=     0, tuid=?
  uid= 1593, flags=   S, size=     0, tuid=?
  uid= 1564, flags=   S, size=     0, tuid=?
  uid=  934, flags=   S, size=     0, tuid=?
  uid=   67, flags=  RS, size=     0, tuid=?
  ...
  master: 1335 messages, 0 recent
  matching messages on master against sync records
  Synchronizing...
  synchronizing old entries
  synchronizing new entries
  new message 1221 on master
    -> pair(1221,0) created
    -> updated flags to 16
  new message 4377 on master
    -> pair(4377,0) created
    -> updated flags to 16
  new message 4500 on master
    -> pair(4500,0) created
    -> updated flags to 16
  new message 5960 on master
    -> pair(5960,0) created
    -> updated flags to 16
  new message 6030 on master
    -> pair(6030,0) created
    -> updated flags to 16
  new message 6048 on master
    -> pair(6048,0) created
  synchronizing flags

As a result only 6 messages are downloaded out of 1335 in INBOX.

This patch adds a new step after all messages from IMAP server are
fetched. It sorts fetched messages in ascending UID order, so any code
executed in later stages can rely on that. It solves issue described
above with poczta.o2.pl server, so all 1335 (in that case) messages
are downloaded.
---
 src/drv_imap.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 03eaf30..d964ddf 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -2593,6 +2593,64 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, 
uint newuid, uint seenui
        }
 }
 
+static int
+imap_sort_msgs_comp( const void *a_, const void *b_ )
+{
+       const message_t *a = *(const message_t * const *) a_;
+       const message_t *b = *(const message_t * const *) b_;
+
+       if (a->uid < b->uid)
+               return -1;
+       else if (a->uid == b->uid)
+               return 0;
+       else
+               return 1;
+}
+
+static size_t
+imap_msgs_count( imap_store_t *ctx )
+{
+       message_t *msg = ctx->msgs;
+       size_t count = 0;
+
+       while (msg) {
+               count++;
+               msg = msg->next;
+       }
+
+       return count;
+}
+
+static void
+imap_sort_msgs( imap_store_t *ctx )
+{
+       size_t count = imap_msgs_count( ctx );
+       message_t *m = ctx->msgs;
+       message_t **t;
+       size_t i;
+
+       if (count <= 1)
+               return;
+
+       t = nfmalloc( sizeof(*t) * count );
+
+       for (i = 0; i < count; i++) {
+               t[i] = m;
+               m = m->next;
+       }
+
+       qsort( t, count, sizeof(*t), imap_sort_msgs_comp );
+
+       for (i = 0; i < count - 1; i++)
+               t[i]->next = t[i + 1];
+       t[count - 1]->next = NULL;
+
+       ctx->msgs = t[0];
+       ctx->msgapp = &t[count - 1]->next;
+
+       free(t);
+}
+
 static void imap_submit_load_p2( imap_store_t *, imap_cmd_t *, int );
 
 static void
@@ -2614,6 +2672,8 @@ imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, 
int response )
 {
        imap_load_box_state_t *sts = (imap_load_box_state_t 
*)((imap_cmd_refcounted_t *)cmd)->state;
 
+       imap_sort_msgs( ctx );
+
        transform_refcounted_box_response( &sts->gen, response );
        imap_submit_load_p3( ctx, sts );
 }
-- 
2.19.1



_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to