jstedfast / MailKit

A cross-platform .NET library for IMAP, POP3, and SMTP.
http://www.mimekit.net
MIT License
6.2k stars 822 forks source link

A Link for search Message Text would be nice #1787

Closed NilsHoyer closed 2 months ago

NilsHoyer commented 2 months ago

With MailFolder.Search, I can specify a Text, which will be used for UID SEARCH. A link inside your documentation with a detailed description would be nice, I think. Maybe to the related RFC diretely...

If I use a SearchQuery, with a "{" inside, i didn't find a mailnwith the related Subject. But until now, I didn't verify, if this was my mistake.

Additional, If I ready your API description with my Android Smartphone, it's very small. I believe, you did not offer mobile version.

... I don't need your assistance, I will find all I need Someehre, I believe. But I wanted to let you know my how you could improve you dicumantion Fürther more. Please excuse me, if you feel bithed with my posting.

jstedfast commented 2 months ago

The specification for the SEARCH command can be found in rfc3501, section 6.4.4 but it's probably not going to be super helpful (unfortunately).

Most IMAP servers seem to use some sort of "word index" that is used for body text searches, so it's not very accurate. This is likely done to make it "fast", otherwise it would be excruciatingly slow to do an exact text search over an entire folder of messages.

This likely is what causes searches with punctuation to fail for you, but you won't find any clue about this in the IMAP docs.

I haven't actually tried reading docs on my phone, but I would not be surprised if it wasn't very optimal - I use the Sandcastle Help File Builder to generate the web docs. Unfortunately, until that Visual Studio extension adds support for generating HTML for mobile devices, MimeKit/MailKit docs probably won't look very nice on mobile devices, either :(

NilsHoyer commented 2 months ago

I want to search in subjects only.

Now, I checked, If I use a "{" inside the SEARCH Text, I get a parser error from the Server.

I still believe, it would be nice If you would add a small hint in your documentation about the mentioned RFC, for me, IT was interrested.

Jeffrey Stedfast @.***> schrieb am Fr., 2. Aug. 2024, 20:13:

The specification for the SEARCH command can be found in rfc3501, section 6.4.4 https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4 but it's probably not going to be super helpful (unfortunately).

Most IMAP servers seem to use some sort of "word index" that is used for body text searches, so it's not very accurate. This is likely done to make it "fast", otherwise it would be excruciatingly slow to do an exact text search over an entire folder of messages.

This likely is what causes searches with punctuation to fail for you, but you won't find any clue about this in the IMAP docs.

I haven't actually tried reading docs on my phone, but I would not be surprised if it wasn't very optimal - I use the Sandcastle Help File Builder https://github.com/EWSoftware/SHFB to generate the web docs. Unfortunately, until that Visual Studio extension adds support for generating HTML for mobile devices, MimeKit/MailKit docs probably won't look very nice on mobile devices, either :(

— Reply to this email directly, view it on GitHub https://github.com/jstedfast/MailKit/issues/1787#issuecomment-2265905060, or unsubscribe https://github.com/notifications/unsubscribe-auth/BEUVHAG3Y5WFB3PAVMD7CGTZPPD5FAVCNFSM6AAAAABL4SKEQ2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRVHEYDKMBWGA . You are receiving this because you authored the thread.Message ID: @.***>

jstedfast commented 2 months ago

Can you get a protocol log with the parse error?

https://github.com/jstedfast/MailKit/blob/master/FAQ.md#q-how-can-i-get-a-protocol-log-for-imap-pop3-or-smtp-to-see-what-is-going-wrong

NilsHoyer commented 2 months ago

I've attached the log.

If I'm right, the problem based on the double quotes for the UID SEARCH command. If I search about "HelloTest", it works without the quotes. But with "Hello Test" it fails, since now MailKit adds the quotes. I believe, this is a server bug. Imap.log

jstedfast commented 2 months ago

Yea, I'm pretty sure that you are correct that this is a server bug.

jstedfast commented 2 months ago

I've updated the API Reference Manual to include a link to the appropriate specification that defines the search term.

NilsHoyer commented 2 months ago

Great! 😌

Jeffrey Stedfast @.***> schrieb am Mi., 7. Aug. 2024, 18:25:

I've updated the API Reference Manual to include a link to the appropriate specification that defines the search term.

— Reply to this email directly, view it on GitHub https://github.com/jstedfast/MailKit/issues/1787#issuecomment-2273856820, or unsubscribe https://github.com/notifications/unsubscribe-auth/BEUVHAE6PJUWV43FD64OYATZQJDAPAVCNFSM6AAAAABL4SKEQ2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZTHA2TMOBSGA . You are receiving this because you authored the thread.Message ID: @.***>

NilsHoyer commented 2 months ago

Die you know a good free IMAP server for local developing under Windows?

jstedfast commented 2 months ago

Unfortunately, I don';t know of a good one for Windows that is easy to setup. I usually use Dovecot on Mac/Linux if I need to set one up.

NilsHoyer commented 2 months ago

Last week, I tried the following IMailFolder.Search method: https://mimekit.net/docs/html/M_MailKit_Net_Imap_IImapFolder_Search.htm

Unfortunately, I was to stupid to find them inside VS 2022 after installing your NuGet Package 😢.

(Still, I have problems understanding the SeaechQuery class, using multiple AND and OR.)

jstedfast commented 2 months ago

The And and Or methods can be used in 2 ways:

// Both of these are identical:
var query1 = SearchQuery.SubjectContains ("subject").And (SearchQuery.FromContains ("Nils"));
var query2 = SearchQuery.And (SearchQuery.SubjectContains ("subject"), SearchQuery.FromContains ("Nils"));

The Or method can be used in exactly the same ways.

The SearchQuery APIs essentially build an expression tree if that concept is at all familiar to you.

Does that answer your question? Or what are you struggling with? Perhaps I can try to explain it.

NilsHoyer commented 2 months ago

Thank you for your offer to assist me, I'm happy about this, since I'm too stupid to find a solution by myself.

I have six expressions: Expr1, Expr2, ... Expr6.

In C# I would use this

if (Expr1 && Expr2 || Expr3 && Expr4 || Expr5 && Expr6)
    ...

I've tried to realize this with MailKit on this way:

var searchQuery =
    SearchQuery.SubjectContains(Expr1).And(SearchQuery.SubjectContains(Expr2))
        .Or(SearchQuery.SubjectContains(Expr3).And(SearchQuery.SubjectContains(Expr4))
        .Or(SearchQuery.SubjectContains(Expr5).And(SearchQuery.SubjectContains(Expr6))));

For me, it is important, that the AND (&&) will be handled before the OR (||).

Inside the log, I found this line:

C: A00000006 UID SEARCH OR (SUBJECT "Expr1" SUBJECT "Expr2") OR (SUBJECT "Expr3" SUBJECT "Expr4") (SUBJECT "Expr5" SUBJECT "Expr6")

I would expect this one (but I'm not a IMAP professional, so maybe I'm wrong):

C: A00000006 UID SEARCH (SUBJECT "Expr1" SUBJECT "Expr2") OR (SUBJECT "Expr3" SUBJECT "Expr4") OR (SUBJECT "Expr5" SUBJECT "Expr6")
jstedfast commented 2 months ago

MailKit's command is correct and matches you pseudo-code if-statement.

IMAP's SEARCH command uses "prefix" notation (as opposed to "infix"). In other words:

OR EXPR1 EXPR2 would map to if (EXPR1 || EXPR2) in C# syntax.

If we then expand this out a bit more to something a little closer to your query:

OR EXPR1 OR EXPR2 EXPR3 would map to if (EXPR1 || (EXPR2 || EXPR3))

So if we take then look at the SEARCH command that MailKit is sending:

C: A00000006 UID SEARCH OR (SUBJECT "Expr1" SUBJECT "Expr2") OR (SUBJECT "Expr3" SUBJECT "Expr4") (SUBJECT "Expr5" SUBJECT "Expr6")

This would map to:

if (
    (Subject.Contains ("Expr1") && Subject.Contains ("Expr2"))
    ||
    (
        (Subject.Contains ("Expr3") && Subject.Contains ("Expr4"))
        ||
        (Subject.Contains ("Expr5") && Subject.Contains ("Expr6"))
    ))
NilsHoyer commented 2 months ago

... so the problem is again the server, I'm using on my local Windows system.

Thank you for checking my code and your detailed description.