This project is read-only.

Get body after first using MessageFetchMode.Minimal to populate folder

Jun 7, 2016 at 9:06 AM
This is what I have done that works

Client.Behavior.AutoDownloadBodyOnAccess = True
    For Each imapFolder In Client.Folders
        If (IsNothing(imapFolder) = False) Then
            If FetchLimit <> 0 Then

                imapFolder.Messages.Download(, MessageFetchMode.Basic, eAcc.FetchMore) 'Fetch messages up to limit
                imapFolder.Messages.Download(, MessageFetchMode.Basic) 'Fetch ALL messages 

            End If
        End If
However, it takes too long to download all the message bodies, so I want to change this code to:
imapFolder.Messages.Download(, MessageFetchMode.Minimal)

However, when I do this I get some messages where the body is blank and some where it says something like this "IMAPX261 OK UID FETCH completed"

I tried adding the below code when the message is accessed, yet I get the same result. Only when I use MessageFetchMode.Basic at the start, do things work correctly.

Dim mess As ImapX.Message
Jun 7, 2016 at 9:18 AM
Edited Jun 7, 2016 at 9:19 AM
I noticed that sometimes I am getting text like this ") IMAPX33 OK UID FETCH completed" at the end of messages bodies even when using MessageFetchMode.Basic
Jun 8, 2016 at 7:16 PM
It looks like MessageContent.cs is using regex to try and extract the message content, but it's not working properly.

Probably the IMAP server is putting the requested items in a different order than what the regex expects, e.g. the regex expects the UID to be the first item, but the server is probably responding with the BODY first or something.

This is something that is really hard to parse correctly with regex because it's a bit like a JSON response in the sense that key/value pairs can come in any order + the fact that values can be a NIL, quoted-string, or a literal string.

For example, the server can respond with any of the following:
* 1 FETCH (UID 27) (BODY {#}
<content>) IMAPX33 OK UID FETCH completed
* 1 FETCH (BODY {#}
<content>) UID 27
IMAPX33 OK UID FETCH completed
* 1 FETCH (UID 27) (BODY NIL) IMAPX33 OK UID FETCH completed
* 1 FETCH (UID 27) (BODY "hello") IMAPX33 OK UID FETCH completed
Generally IMAP servers will use the literal string format (e.g. {#} ...) for message bodies, but if the message is empty, they might use NIL or they might use "".

This is what makes using regex so complicated for this task :-\
Jun 9, 2016 at 12:14 PM
So it seems then from a practical standpoint, if you want to consistently fetch message bodies, you must use MessageFetchMode.Basic for the initial folder population. If you use MessageFetchMode.Minimal and then subsequently fetch message bodies, either by means of AutoDownloadBodyOnAccess or manually (Message.Download) then the IMAP server my put the requested items in an unexpected order.
Jun 14, 2016 at 10:09 PM
It can put any of the responses in any order it wants to. I guess you're just getting lucky with Basic but not lucky with Minimal.
Jun 15, 2016 at 9:11 AM
Hello everyone,

there's a new version of ImapX currently in work, which no longer uses regex to parse the server responses. There is an ANTLR based parser instead.
I hope I can release a stable beta soon.


Jun 16, 2016 at 7:44 PM
Awesome news, Pavel :)