This project is read-only.

Together better

Jan 9, 2014 at 10:27 PM
Edited Jan 11, 2014 at 9:41 AM
Suggestions for working together with:

https://higlabo.codeplex.com/documentation

https://mailsystem.codeplex.com/

https://imapx.codeplex.com/

https://github.com/andyedinborough/aenetmail

https://github.com/jstedfast/MailKit

Lumisoft Mail

References:

http://stackoverflow.com/questions/545724/using-c-sharp-net-librarires-to-check-for-imap-messages-from-gmail-servers

http://stackoverflow.com/questions/670183/accessing-imap-in-c-sharp

I'm newbie, but I have seen several open source components-libraries about IMAP. I'm considerer better for community that gurus and experts work together, IMHO. Greetings.

Jeffrey Stedfast says:

higlab: Seems like a pretty awful implementation, so it'd be a complete waste of my time even trying to integrate with their product. I'd be more productive for me to rewrite their library from scratch... so not gonna bother.

mailsystem: Wow, this is pure crap. It uses String.IndexOf('}') to parse literal strings returned by the IMAP server? Really??? Not worth my time.

imapx: Extremely sloppy parsing code, so again, not worth my time.

aenetmail: Another pretty sloppy MIME, POP3, IMAP, and SMTP implementation.

If they want to use MimeKit to replace their shitty MIME parsers, that's great, but I'm not going to get involved in these projects. It'd be time better spent if I just write a mail library on my own... which is what MailKit is all about.

The only piece that MailKit is missing is an ImapClient at this point, and since all of the other libraries you listed have horrendous implementations of everything, it'd be easier to just write an ImapClient for MailKit than it would be to fix any of those other libraries.

I'd like to implement IMAP support in MailKit... just not sure how high/low-level to make it. IMAP is pretty complex and any mail client dealing with IMAP is going to want to cache information for offline use. Should MailKit do that? Or should that be left to the application using MailKit? The IMAP protocol also supports partial downloads of messages (you can download individual parts or specify the number of bytes and a byte offset into the message to download... Should ImapClient expose this functionality? If so, how? These are just a few examples of the type of questions I need to think about. POP3 is dead simple because the purpose is simply to copy the mail to the local machine. IMAP on the other hand is meant to keep the mail on the server.


http://jeffreystedfast.blogspot.com.es/2013/10/optimization-tips-tricks-used-by.html#gpluscomments


Christtian Nilsson say

Why I started to use and still use S22.Imap instead of any other lib:
S22.Imap is a IMAP Client, nothing else just a IMAP client.
When I was trying to find a IMAP Client I found and looked on AENetMail however that is not a IMAP Client, it is a full email client library.

Any other library that is not only a IMAP Client is bloated for my purposes (sorry for the choice of word)

Something that might be interesting however is https://github.com/jstedfast/MimeKit
If I can find the time I would like to check it out and see if it could be reused.
But MailKit is of no use to me since (as with many of the others) it contains a POP3 client as well.
And then we have Comments like "Wow, this is pure crap" who wants to work with someone with a attitude like that?

One of the biggest issues with the .Net implementation of mail is the standard Net.Mail namespace, but most of what is needed for other client libraries are Internal in the base framework, and thus must be recreated with extra code.

Jeffrey Stedfast says:

MimeKit can be reused (that was the goal of the project). In fact, I wasn't really planning to write MailKit since I have no real interest in writing a mail client. The plan was for other people to write POP3, SMTP, and IMAP libraries built on top of MimeKit.

After getting a bunch of emails asking me how to send MimeKit messages via SMTP and/or asking me to plug MimeKit into this or that POP3 library, I gave up and implemented my own SmtpClient and Pop3Client. Since these clients are vastly more robust than any of the other Smtp and Pop3 clients I've seen, I can just point people at using those. I'm not super enthusiastic about writing an ImapClient because the last C implementation I wrote was ~10,000 lines of code to support all of the features and be usable while the network is offline, handling reconnecting when the server sends back untagged BYE responses that weren't the result of a LOGOUT command, etc. and that didn't even include IDLE support (which these days is a pretty MUST HAVE feature).

You'll notice that unlike every other POP3 .NET library, MailKit's Pop3Client does not use a lame line-reader approach (see Pop3Stream), nor does it duplicate the retrieved messages into a memory stream before parsing, it parses directly from the socket doing on-the-fly dot-decoding and is completely cancelable (another advantage of MimeKit).

I called that other IMAP client implementation crap because, well, it's crap. I mean, you can't just read a hunk of data from the socket, convert it into unicode (without first knowing what charset the mime message is in) and then use IndexOf(')') to figure out where the end of the message is with the assumption that that character does not appear in the message itself (haha, good luck with that).

Most people who implement POP3 and IMAP clients assume that the protocols are string-based, but they really aren't. At least not when you are using a programming language where strings are multi-byte (such as UTF-16). Sure, they are text-based, but when using Java or C#, you can't really use strings because you need to know the charset first and you can't know the charset before you parse the email message (or, in the case of IMAP, envelope data as well), and even then, each part might be in a different charset, so you can't use a single charset for conversion into unicode. The only parts of the response that you can read as strings are the actual protocol tokens (because they are ASCII tokens), which means you CANNOT use a TextReader. You have to read raw bytes (you can convert segments of the byte[] into strings as you go, of course, but you can't just gulp up the entire response as a string).

Then, of course, there's the fact that when reading a literal string response from the IMAP server, most IMAP implementations I've seen make the incorrect assumption that the octet count provided in the "{xxx}" is the same as the String.Length, which of course is wrong.

Now that I've pointed out these fundamental problems that plague every Pop3 and IMAP client I've seen for .NET, I'm sure you better understand why I call such clients crap.

Just an example of what I'm talking about: andyedinborough/aenetmail#150

AENetMail doesn't properly decode the dot-encoding that is used in the RETR command, nor does it even use the correct approach to figuring out the end of the response which is what causes any further commands to fail.

Some bugs are just bugs, but others are fundamental design problems.

Anyway, I don't care one way or another if S22.Imap decides to use MimeKit, although I'm more than willing to answer any questions the developers have about using it and fixing any bugs or adding any features they need (within reason, of course).

Most of the time, plugging in an alternative XYZ library is not trivial and requires a lot of rewriting of significant chunks of code, and generally developers of libraries such as this aren't going to bother rewriting their library if the itch they set out to scratch has already been solved well enough for their needs.

https://github.com/smiley22/S22.Imap/issues/72
Jan 12, 2014 at 9:45 AM
Wow. Just wow. Instead of calling something "pure crap" - why not actually contribute something to open-source? And fix things you don't like? This is OPEN-SOURCE, you know. If you don't like something - you fix it.

Who's this "Stedfast" anyway???
Jan 12, 2014 at 12:34 PM
You're right. I'm newbie, only considerations for good developers for join efforts to improvement open source community.
Jan 12, 2014 at 4:05 PM
Edited Jan 12, 2014 at 4:12 PM
Sigh. I am not happy that my comments have been posted to every single mail library project's forums without my permission to do so. (kiquenet has mirrored all of this to the ImapX forums, the AENetMail forums, the S22.Imap forums, etc).

So here I am, having to create a CodePlex account that I'll probably never ever use after this, but oh well.

jitbit: Who says I don't contribute to open source? Just because I've chosen not to contribute to your library does not mean I do not contribute to open source. Can I not choose to write my own (open source!) IMAP client library instead???

If you actually bothered to read my followup explaining why I thought ActiveUp's IMAP code was crap, you'd have seen that I actually bothered to look over your source code and discovered that you read the response into a System.String and then assume that the octet count provided in the {###} literal token will match the String.Length unicode character count (it won't for most charsets!) and that you have a gross hack that involves using response.IndexOf (')') to find the end.

Sorry, but this code made me face-palm and when I saw that I knew that I had no interest in contributing to this project because I felt that my time would be better spent writing my own (or finding another IMAP library to contribute to that wasn't broken in such a fundamental way).

You even have a bug report open about this: https://mailsystem.codeplex.com/workitem/24771

This is a fundamental design problem, and it isn't the only one you have.

An IMAP server can decide to respond using literals for pretty much anything that your code assumes will be a quoted string. Here's the BNF grammar from rfc3501 if you don't believe me:

string = quoted / literal

That means it can return LIST and LSUB responses using literals or any of the values in a BODYSTRUCTURE query. I'm guessing by the completely shocked expression on your face that you did not know this insanely important piece of trivia, did you?

Proof:

mailbox-list = "(" [mbx-list-flags] ")" SP (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
mailbox = "INBOX" / astring
astring = 1*ASTRING-CHAR / string
string = quoted / literal
literal = "{" number "}" CRLF *CHAR8 ; Number represents the number of CHAR8s

Huh. Whaddaya know? The mailbox name in a LIST response can be a literal and doesn't have to be a qstring like your code expects. Holy shit, it's like this "Stedfast" guy actually knows what the fuck he's talking about...

Some less severe problems include the following as I quickly scan through the Imap4Client.cs file:
    public string RenameMailbox(string oldMailboxName, string newMailboxName)
    {
        string response = this.Command("rename \"" + oldMailboxName + "\" \"" + newMailboxName + "\"");
        return response;
    }
What if oldMailboxName or newMailboxName contain a double-quote character? Did you know that you need to encode mailbox names using a modified UTF-7 encoding? Doesn't look like it based on this code...

Same can be said for your other methods that operate on mailboxes, such as the DeleteMailbox() method and the SubscribeMailbox() method.

I'm sure I'm coming off as a complete asshole right now, but remember: you attacked me rather than refute what I said. You decided to take offense at a word that was not directed at you or your character, but rather the library that you contribute to (probably not even your code to begin with, is it?). I do not even know if the code within MailSystem.NET is representative of your actual abilities or up to your normal coding standards, so when I say the code in MailSystem.NET's IMAP implementation is crap, it is not a reflection of you - it is just an evaluation of the design / code of MailSystem.NET and that is all.

Now, if you are interested (and I'd wager that you aren't because you probably want nothing to do with me or my projects), I've written a standalone MIME parser library (called MimeKit) under the MIT license that you are free to use in your MailSystem.NET library to replace whatever you're currently using as a MIME parser, assuming you find it to be an improvement over whatever library you are currently using (and I guarantee that you will).

You can find it here: https://github.com/jstedfast/MimeKit

If you have questions or if you just want to try your hand at getting "revenge" by tearing it to pieces with your knowledge of the MIME specifications, be my guest.


If you're interested, you can also check out https://github.com/jstedfast/MailKit to see how I've implemented my own SmtpClient and Pop3Client (and probably my own ImapClient at some point). You may learn a few tricks...

Oh, and just so you don't feel so bad... all of the other open source IMAP client libraries I've seen so far suffer from many of the same fundamental design problems, so MailSystem.NET has plenty of company.
Jan 13, 2014 at 2:41 PM
jitbit: I've spent a few minutes looking over your Pop3Client and SmtpClient code and I'm beginning to wonder if you guys even know that there are RFCs that define these protocols?

For example, Your Pop3Client code doesn't properly reverse the byte-stuffing that the RETR response contains.

Your SmtpClient code doesn't byte-stuff the DATA command at all and it's supposed to.

Let me help you guys out:

Here's the specification for the POP3 protocol: rfc1939
Here's the specification for the SMTP protocol: rfc2821
Here's the specification for the IMAP protocol: rfc3501

Next time you get offended that someone points out that your code was obviously written by developers who have never even LOOKED at, never mind bothered to read and comprehend, the specifications for the protocols the library is supposed to implement, make sure you don't attack a guy that actually has read them. You will get schooled just like you did here.
Jan 13, 2014 at 4:34 PM
@jstedfast sorry for attacking you, had a rough day yesterday. Thanks for the RFC stuff, and I'll review the imapclient code when I'll have more time.
Jan 13, 2014 at 4:45 PM
FWIW, I submitted a bug report for the Pop3Client byte-stuffing bug here: http://mailsystem.codeplex.com/workitem/25066 with further information that you may find helpful.

I didn't bother submitting one for the SmtpClient, but it's the same deal, except in reverse.
Jan 13, 2014 at 5:03 PM
Great collaboration both, thanks.
Jan 19, 2014 at 8:34 PM
I was curious what it would take to implement my own ImapClient (holy crap a lot of IMAP extensions have been published since I last worked on an IMAP client!), so the past 36 hours or so I've had a bit of a hacking marathon.

The IMAP protocol is really designed to use a tokenizer, so I wrote an ImapStream class that tokenizers server responses and, when it runs into a literal token, toggles itself into "literal mode", allowing you to read from it like a normal Stream, cutting you off when you've finished reading the literal data (IOW: it returns 0 once you've finished reading data).

On top of that, I have an ImapEngine and ImapCommand which is more-or-less a command pipeline engine for queueing and dispatching commands to the server and then reading the responses and dispaching untagged events to custom handlers (or to the engine itself for stuff that it needs to keep state).

Sitting on top of that, I have ImapClient and ImapFolder which drive the engine.

ImapFolder, at this point, is just a stub, but you can get a list of all of the personal, shared, and other namespaces from the ImapClient (along with all of the special folders if the server supports the SPECIAL-USE extension). You can also authenticate via a handful of SASL mechanisms.

This is all part of my MailKit project, if you are interested in taking a look. I promise you won't be disappointed.
Jan 21, 2014 at 12:05 PM
I've been on a roll and ImapFolder is now almost fully implemented as well. At this rate I should have a fully functional IMAP client by the end of the week.
Jan 25, 2014 at 4:23 PM
MailKit's IMAP support is now more-or-less complete. Only took me a week...
Jan 25, 2014 at 11:27 PM
It's great. Maybe MailKit's IMAP will be good documentation and samples.
Aug 21, 2014 at 10:36 PM
Actually I used ILSpy to check code of MailSystem.NET (even if it's open source)...and posted an issue for them.

They have static Send* methods, open a port, sends data and before exitting they dispose the created smtp client - but if exception occures, noone handles it and noone disposes the connection, so re-trying may not work until GC cleans the mess after them up.

I also googled MailKit vs. MailSystem and thanx to jstedfast comments, it's almost sure i will use his MailKit.