Reputation: 1540
I'm trying to implement a mail client using the IMAP protocol and MailKit library.
Regardless of how I configure the IMapClinet, the filed IMessageSummary.Envelope.InReplyTo
is always null.
I'm using the Fetch method like the following:
client.Inbox.Fetch(startIndex, -1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId | MessageSummaryItems.References | MessageSummaryItems.All | MessageSummaryItems.Headers);
And the interesting part is that the header for In-Reply-To
is present and contains the value which is also present on the References
header (they have the same value), but still, the mentioned field is always empty.
Am I missing something or do I need to evaluate the Envelop
property somehow before accessing its fields?
EDIT
Here is the protocol log to be examined which was suggested by @jstedfast:
Connected to imap://127.0.0.1:143/
S: * OK IMAP4rev1 SmarterMail
C: A00000000 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=CRAM-MD5 AUTH=PLAIN UIDPLUS QUOTA XLIST CHILDREN ENABLE IDLE
S: A00000000 OK CAPABILITY completed
C: A00000001 AUTHENTICATE CRAM-MD5
S: + PDE5MTIwMTU2NjMugwNDIzQFJvamFuUEM+
C: cm9qYW5Acm9qYW5wYy5sb2NhbCAyNGRiYMTNjNzk5YTkyYjBhZjkxYTU3ZQ==
S: A00000001 OK CRAM authentication successful
C: A00000002 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=CRAM-MD5 AUTH=PLAIN UIDPLUS QUOTA XLIST CHILDREN ENABLE IDLE
S: A00000002 OK CAPABILITY completed
C: A00000003 LIST "" ""
S: * LIST (\Noselect) "/" ""
S: A00000003 OK LIST completed
C: A00000004 LIST "" "INBOX"
S: * LIST (\HasNoChildren \Inbox) "/" "Inbox"
S: A00000004 OK LIST completed
C: A00000005 XLIST "" "*"
S: * XLIST (\HasNoChildren \Trash) "/" "Deleted Items"
S: * XLIST (\HasNoChildren) "/" "Drafts"
S: * XLIST (\HasNoChildren \Inbox) "/" "Inbox"
S: * XLIST (\HasNoChildren \Spam) "/" "Junk E-Mail"
S: * XLIST (\HasNoChildren \Sent) "/" "Sent Items"
S: A00000005 OK XLIST completed
C: A00000006 SELECT Inbox
S: * 1 EXISTS
S: * 0 RECENT
S: * OK [UNSEEN 1] Message 1 is first unseen
S: * OK [UIDVALIDITY 1] UIDs valid
S: * OK [UIDNEXT 35] Predicted next UID
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft \Recent)
S: * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \Recent)] Folder flags
S: A00000006 OK [READ-WRITE] SELECT completed
C: A00000007 FETCH 1:* (UID FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY BODY.PEEK[HEADER])
S: * 1 FETCH (UID 34 FLAGS () INTERNALDATE "7-Apr-2020 18:36:29 +0200" RFC822.SIZE 1536 ENVELOPE ("Tue, 07 Apr 2020 16:36:22 GMT" "Re: Hi dear friend" (({15}
S: [email protected] NIL "test" "mypc.local")) (({15}
S: [email protected] NIL "test" "mypc.local")) ((NIL NIL "test" "mypc.local")) ((NIL NIL "someone" "mypc.local")) NIL NIL NIL "<[email protected]>") BODY (("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 242 11) ("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 482 8) "alternative") BODY[HEADER] {468}
S: From: "[email protected]" <[email protected]>
S: To: <[email protected]>
S: Subject: Re: Hi dear friend
S: Date: Tue, 07 Apr 2020 16:36:22 GMT
S: Reply-To: [email protected]
S: Message-ID: <[email protected]>
S: MIME-Version: 1.0
S: Content-Type: multipart/alternative;
S: boundary=de8794cbb22d4f6ea5a415917f9287ee
S: In-Reply-To: <specified-message-id>
S: References: <specified-message-id>
S: Disposition-Notification-To: [email protected]
S: X-SmarterMail-TotalSpamWeight: 0 (Authenticated)
S:
S: )
S: A00000007 OK FETCH completed
Seems like the In-Reply-To
is only present on the message's headers together with References
.
New question: In the case where the In-Reply-To
is not present on the ENVELOPE
, is it a correct approach to manually examine the headers to find the value, or is it safer to use the References
field which is provided by the IMessageSummary
object?
Upvotes: 1
Views: 560
Reputation: 38528
MailKit parses the ENVELOPE
value returned by the IMAP server. If you look at the Protocol Log, do the IMAP server responses provide a non-null In-Reply-To value in the ENVELOPE
response?
The ENVELOPE
value has the following syntax:
envelope = "(" env-date SP env-subject SP env-from SP
env-sender SP env-reply-to SP env-to SP env-cc SP
env-bcc SP env-in-reply-to SP env-message-id ")"
env-bcc = "(" 1*address ")" / nil
env-cc = "(" 1*address ")" / nil
env-date = nstring
env-from = "(" 1*address ")" / nil
env-in-reply-to = nstring
env-message-id = nstring
env-reply-to = "(" 1*address ")" / nil
env-sender = "(" 1*address ")" / nil
env-subject = nstring
env-to = "(" 1*address ")" / nil
TL;DR, you'll be looking for the second-to-last string in the ENVELOPE
parenthesized list value.
Edit:
Okay, now that you've pasted the log, we can take a look at what we got back from the server. Here's the relevant bit:
... ENVELOPE ("Tue, 07 Apr 2020 16:36:22 GMT" "Re: Hi dear friend" (({15}
S: [email protected] NIL "test" "mypc.local")) (({15}
S: [email protected] NIL "test" "mypc.local")) ((NIL NIL "test" "mypc.local")) ((NIL NIL "someone" "mypc.local")) NIL NIL NIL "<[email protected]>")
env-date
= "Tue, 07 Apr 2020 16:36:22 GMT"
env-subject
= "Re: Hi dear friend"
env-from
= (("[email protected]" NIL "test" "mypc.local"))
env-sender
= (("[email protected]" NIL "test" "mypc.local"))
env-reply-to
= ((NIL NIL "test" "mypc.local"))
env-to
= ((NIL NIL "someone" "mypc.local"))
env-cc
= NIL
env-bcc
= NIL
env-in-reply-to
= NIL
env-message-id
= ""
So the problem is that the IMAP server is telling MailKit that the In-Reply-To value is NIL
(aka null
).
Based on the raw headers that you are getting back for this message, it's clear that SmarterMail IMAP server is buggy in at least 2 ways:
env-in-reply-to
value is being sent as NIL
when it should clearly be "<specified-message-id>"
env-sender
is being sent as a duplicate of env-from
, but it should be NIL
in your case based on the headers because it maps to the Sender:
header which doesn't exist for your sample message.Question for you: is "<specified-message-id>"
literally what is in the headers? I wonder if maybe SmarterMail is sending NIL
because that is technically invalid syntax and maybe SmarterMail is failing to parse that?
Just a thought.
Regarding the "New Question" in your post:
Yea, you can request the In-Reply-To
header and manually parse it - that's perfectly fine. In fact, the way MessageSummaryItems.References
works is that it asks for HEADER.FIELDS (REFERENCES)
and then parses the raw header. Since you are also sending MessageSummaryItems.Headers
, MailKit knows that it's pointless to ask for References
again, since it'll be part of the Headers
response.
I probably would recommend against requesting the full set of MessageSummaryItems.Headers
(unless you have a specific need to fetch them all) since it's a lot of extra data that you don't need. Then again, when dealing with a broken IMAP server, maybe it's better to ask for Headers
than Envelope
.
The idea of Envelope
is that it's more-or-less everything you need the client to know about in order to display a message-list to the user.
The reason that MailKit has MessageSummaryItems.References
(and not any other individual header) is because the References
header is needed in order to do proper threading using the MailKit.MessageThreader.Thread()
methods. It will make use of the Envelope.InReplyTo
value as well, but it isn't required, I don't think, because technically, References
is supposed to have the same msg-id
token as one of its values.
The References
header is the chain of Message-Id
header values back to the root of the "conversation" (it's a little more complex than that since clients are allowed to trim some msg-id
values once the list gets too long, but that's the general idea).
Upvotes: 1