Parser Messages

Jan 2 at 12:30 AM
Jan 2 at 10:49 PM
Edited Jan 2 at 10:53 PM
Jeffrey Stedfast says

"I have no interest in working together with HigLabo, that library looks awful. I've been working on a mail client library https://github.com/jstedfast/MailKit and so development on MimeKit has slowed a bit as I work on MailKit in order to figure out what else may be needed in MimeKit (which at this point I almost consider done except for writing some sample apps and flushing out the docs a bit more)."



Then, I want use C# programatically for connect to my gmail account, read messages, download messages with attachments and inline images (embedded), filter messages-attachment . etc, and parser MIME messages. Maybe download EML or MSG from Outlook account, and parser MIME again.
Coordinator
Jan 7 at 1:17 AM
Thank you for your proposal.
I'll see MimeKit and improve performance of my library and feature which HigLabo missing compare with MimeKit.
If you have some request about missing feature, please let me know.

regards.
Jan 9 at 10:27 PM
Edited Jan 11 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
Coordinator
Jan 14 at 3:21 AM
Thank you for your imformation.
Jeffrey Stedfast says my library awfull.
I'm very sad, but I'll try to make my library from awful to awesome.

regards.
Jan 14 at 10:07 AM
Excellent library !
The main thing is that it develops, unlike the rest - the authors have forgotten due to lack of interest.
About two ( maybe more ) years ago and when I first saw HigLabo library, it was not have implementation of IMAP protocol. Only pop3. But it was the best of the library existed at that time .
I have implemented support for Imap (https://higlabo.codeplex.com/discussions/348161), taking as a basis the implementation of pop3. Of course, then the implementation of that little remains , and it is wonderful ! This project is not "copy-paste" other!
Thank you that you are supporting and develope HigLabo library!
  • Translated from Russian google translate :)
Coordinator
Jan 16 at 1:42 AM
Hi Kool_ru!

I remember that you gave me a gift as Imap patch just like yesterday.
It greatly help me to implement Imap feature and other people who use HigLabo may appreciate for your contribution.
I continue my developement of HigLabo library and I'm very happ that you help me by some patch like imap or support me by comment like this.

regards.
Jan 16 at 7:44 AM
Not sad, for me it is very good library and very useful. Sure, the implementation can be improvement.

View https://imapx.codeplex.com/discussions/484235

Thank you for supporting and develope HigLabo, maybe news updates in future.
Coordinator
Jan 22 at 9:07 AM
Hi kiquenet.

I implemented HigLabo.Mime library and finished it with about a week hard work from scratch.
It become massive performance improvement.It is simply incredible!!
Newer version is 12% faster than MimeKit with my roughly performance test.
It may be awesome.

I'll integrate it to HigLabo.Mail dll within a week.
And show performance test code of it.

regards.
Jan 29 at 10:57 PM
Edited Jan 29 at 11:58 PM
@higty:

Try using the MimeKit.MimeParser..ctor (Stream, bool) constructor and passing in 'true' as the 'persistent' argument. Your parser "cheats" (in quotes because it's not really cheating, it's a nice feature) by not loading the content, but MimeKit's parser has the same feature that you likely overlooked. Telling MimeKit's parser that it can rely on the source stream being persistent improves parser performance by a good 20%.

That said, looking over your parser, I can see that your MimeParser may be the only .NET parser to give mine a run for its money performance-wise, so I have to give you props for that.

Once I finish writing my own ImapClient (that I started writing as a result of this discussion), I'll likely be going back to my MimeParser and optimizing it more. It is theoretically possible to nearly double its performance (my C parser is roughly 1.5x faster than MimeKit).

Even so, MimeKit is 25x faster than OpenPOP.NET's even after disabling OpenPOP.NET's base64 decoder, 75x faster than SharpMimeTools, 65x faster than MIMER and 70x faster than Mail.dll (a proprietary mail library by LimiLabs). I haven't compared against yours, but if you are working on some optimizations, I'll wait until you've committed them.

Anyway, I seem to have misjudged HigLabo somewhat (I'll list some of the obvious problems with it in a bit) and perhaps got it confused with MailSystem.NET who's author admitted he hadn't actually read the specs.

Your library is definitely better than the others, but your use of Regex in ImapClient makes me cringe. In my experience having worked on a mail client 10 years ago, some IMAP servers may send additional whitespace which would make your regexes fail. You could fix your regexes by using \s or whatever, but a better solution would be to use a tokenizer.


While I'm reviewing your ImapClient, let me point out some other flaws in your implementation:
String commandText = String.Format(this.Tag + " LOGIN {0} \"{1}\"", this.UserName, this.Password);
This is wrong. The username is defined as so:

userid = astring
astring = 1*ASTRING-CHAR / string
string = quoted / literal

You may need to either quote the user name or send it as a literal if it contains chars that are illegal within quotes (such as CR and LF, although possibly non-ascii chars as well - the spec is not clear on that point because it does not define CHAR, but some specs define CHAR is ascii char).

Same for the password.

Also, blindly putting "" around the password is wrong in cases where the password string contains \ or " (you need to escape them).

Same for mailbox names in places such as ImapClient.MailboxSelect().

Basically, it seems that your code does not handle the possibility of needing to send literal tokens for anything but appending messages and where you quote strings, none of them seem to escape the strings.

Hopefully this has been helpful.
Sat at 1:13 PM
On closer inspection, it appears that you've been stealing MimeKit code and removing my copyright notices. Your recent Base64Converter, QuotedPrintableConverter and CharTypeTable classes are direct rip-offs of code found in MimeKit. I haven't looked to see if you've stolen any further code, but the fact that you explicitly removed my copyright notices, I must say, makes me quite annoyed.

Please add back my copyright headers or remove my code from your project.

I've already emailed you about this matter and you've chosen to ignore it.

Hope to hear back soon,

Jeff
Sat at 2:16 PM
@highty you can use MImeKit, it's very helpful, it's right using copyright. J.Stedfast share his work for all community, it's right using copyright.
Coordinator
Mon at 2:24 AM
Edited Today at 6:40 AM
Jstedfast said: I've already emailed you about this matter and you've chosen to ignore it
Why can you conclude me to ignore your mail?
Is there any evidence?
I can show the evidence that I don't ignore your mail just now by this post.
You sent me a mail at 1/31 21:25:42 (0900 at Tokyo)
And post comment at 1/31 at 22:17 (0900 at Tokyo)
These 3 days I have a holiday, play golf and have a dinner with my friend, and play tennis in another day.
So I don't notice your mail and don't have a time to reply with such a long post.
And the mailbox you sent me a mail is one of my sub mail address.
So, I don't check this mailbox everyday.
You might check mailbox every 10 minute,365days, I don't.
You tends to label other people badly with your selfish assumption.

Jstedfast said: it appears that you've been stealing MimeKit code
I say once again, why can you conclude it?
Recent my check in, these are "TEMPORARY CHECK IN"
My work is in progress.
I plan to check all code and add copyright or remove temporary copied code when I upload zip file and link it to source code.
Like this.

https://higlabo.codeplex.com/releases/view/116994
I check all copyright at once, because of do a efficiency work.

You call me a robber with your selfish assumption.
You are really rudeness.
And you give other people an unpleasant feeling.
I'll show you evidences about it.

Your comment for other library
higlabo: 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.
There is a evidence that your comment make other an unpleasant experience.
I show one of the reaction about your comment.
Above comment by Kiquenet at Jan 10 at 7:27 AM
Christtian Nilsson say "And then we have Comments like "Wow, this is pure crap" who wants to work with someone with a attitude like that?"
You are absolutely insolent, a paranoiac.

Although it may be a private mail, it can not be a reasonable excuse.
I have never use these bad word even when I'm sending private mail.
I don't want to do such a shameful conduct.

If I were you, instead of using bad word, I would say about mailsystem like below.
"Wow, It looks nice! But String.IndexOf('}') may cause error. If author modify it, the library will improve and can be a more excellent. To join it looks good, but recent days I'm busy and could not have my time to it."
This is your comment.
"Wow, this is pure crap. It uses String.IndexOf('}') to parse literal strings returned by the IMAP server? Really??? Not worth my time."

From other post from https://higlabo.codeplex.com/discussions/528612
Jstedfast said: Base64Converter, QuotedPrintableConverter and CharTypeTable classes are direct rip-offs of code found in MimeKit. Perhaps other code as well
Third time, why can you conclude it?
I don't steal your code because I'll add copyright header or remove your code.
Can you produce "EVIDENCE" that I will not add copyright or remove your code in the future?

Okey, you misunderstood with finding rip-offs of code, this might not be inevitable.
But If I were you, I think like below
1.It may be a debug code and checked in by mistake.
2.He don't know detailed open source rule.
Or some other circumstances under the food that I couldn't notice.
So, I will ask by e-mail at first, and next I post it in public space after grasping the overall situation.
You e-mailed me and post here without my reply.
You sent me a mail at 1/31 21:25:42 (0900 at Tokyo)
And post comment at 1/31 at 22:17 (0900 at Tokyo)
Only 30 minutes progressed when you post comment.
You are narrow-minded.


Jstedfast said: Please add back my copyright headers or remove my code from your project
I'll remove all your code in my project.
Point out filename and line number that you think copy from your MimeKit within a week.
All code that you point out, I'll remove them completely.
Jstedfast said: ...direct rip-offs of code found in MimeKit. "Perhaps other code as well"
Because you are likely to fudge up one after another with your selfish assumption.
You are unreliable.
Your code is nothing special, I can easily create it by myself.
If I was to go all out you'd be as nothing to me.


Well, you might be the average skill about programing.
But not only learning how to program, you should learn the etiquette in the online community.
I will have nothing to do with you.
Mon at 3:30 AM
I sent you an email 24 hours before I posted to the forums about this, not 30 minutes. You must not be factoring in timezone offsets correctly.

My email was sent Friday morning, I didn't post to the forums until Saturday morning.
Point out filename and line number that you think copy from your MimeKit within a week.
All code that you point out, I'll remove them completely.
I already did: CharTypeTable.cs, Base64Converter.cs, and QuotedPrintableConverter.cs are copied from MimeKit.

You changed the class names but kept the variable names the same. You merged MimeKit's Base64Decoder.cs and Base64Encoder.cs into your Base64Converter.cs that you checked in earlier this week. You can check that my Base64Encoder/Decoder files in MimeKit have existed for a year.

Here's your CharTypeTable.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HigLabo.Mime.Internal
{
    [Flags]
    public enum CharType : ushort
    {
        None = 0,
        IsAscii = (1 << 0),
        IsAtom = (1 << 1),
        IsAttrChar = (1 << 2),
        IsBlank = (1 << 3),
        IsControl = (1 << 4),
        IsDomainSafe = (1 << 5),
        IsEncodedPhraseSafe = (1 << 6),
        IsEncodedWordSafe = (1 << 7),
        IsQuotedPrintableSafe = (1 << 8),
        IsSpace = (1 << 9),
        IsSpecial = (1 << 10),
        IsTokenSpecial = (1 << 11),
        IsWhitespace = (1 << 12),
        IsXDigit = (1 << 13),
    }
    public static class CharTypeExtensions
    {
        public static bool HasFlag(this CharType e, CharType other)
        {
            return ((e & other) == other);
        }
    }
    public class CharTypeTable
    {
        const string AtomSafeCharacters = "!#$%&'*+-/=?^_`{|}~";
        const string AttributeSpecials = "*'%";    // attribute specials from rfc2184
        const string CommentSpecials = "()\\\r";   // not allowed in comments
        const string DomainSpecials = "[]\\\r \t"; // not allowed in domains
        const string EncodedWordSpecials = "()<>@,;:\"/[]?.=_";  // rfc2047 5.1
        const string EncodedPhraseSpecials = "!*+-/=_";          // rfc2047 5.3
        const string Specials = "()<>@,;:\\\".[]";
        internal const string TokenSpecials = "()<>@,;:\\\"/[]?=";
        const string Whitespace = " \t\r\n";

        static readonly CharType[] table = new CharType[256];

        static void RemoveFlags (string values, CharType bit)
        {
            for (int i = 0; i < values.Length; i++)
                table[(byte) values[i]] &= ~bit;
        }

        static void SetFlags (string values, CharType bit, CharType bitcopy, bool remove)
        {
            int i;

            if (remove) {
                for (i = 0; i < 128; i++)
                    table[i] |= bit;

                for (i = 0; i < values.Length; i++)
                    table[values[i]] &= ~bit;

                if (bitcopy != CharType.None) {
                    for (i = 0; i < 256; i++) {
                        if (table[i].HasFlag (bitcopy))
                            table[i] &= ~bit;
                    }
                }
            } else {
                for (i = 0; i < values.Length; i++)
                    table[values[i]] |= bit;

                if (bitcopy != CharType.None) {
                    for (i = 0; i < 256; i++) {
                        if (table[i].HasFlag (bitcopy))
                            table[i] |= bit;
                    }
                }
            }
        }

        static CharTypeTable()
        {
            for (int i = 0; i < 256; i++) {
                if (i < 127) {
                    if (i < 32)
                        table[i] |= CharType.IsControl;
                    if (i > 32)
                        table[i] |= CharType.IsAttrChar;
                    if ((i >= 33 && i <= 60) || (i >= 62 && i <= 126) || i == 32)
                        table[i] |= (CharType.IsQuotedPrintableSafe | CharType.IsEncodedWordSafe);
                    if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z'))
                        table[i] |= CharType.IsEncodedPhraseSafe | CharType.IsAtom;
                    if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'f') || (i >= 'A' && i <= 'F'))
                        table[i] |= CharType.IsXDigit;

                    table[i] |= CharType.IsAscii;
                } else {
                    if (i == 127)
                        table[i] |= CharType.IsAscii;

                    table[i] |= CharType.IsControl;
                }
            }

            table['\t'] |= CharType.IsQuotedPrintableSafe | CharType.IsBlank;
            table[' '] |= CharType.IsSpace | CharType.IsBlank;

            SetFlags (Whitespace, CharType.IsWhitespace, CharType.None, false);
            SetFlags (AtomSafeCharacters, CharType.IsAtom, CharType.None, false);
            SetFlags (TokenSpecials, CharType.IsTokenSpecial, CharType.IsControl, false);
            SetFlags (Specials, CharType.IsSpecial, CharType.None, false);
            SetFlags (DomainSpecials, CharType.IsDomainSafe, CharType.None, true);
            RemoveFlags (Specials, CharType.IsAtom);
            RemoveFlags (EncodedWordSpecials, CharType.IsEncodedWordSafe);
            RemoveFlags (AttributeSpecials + TokenSpecials, CharType.IsAttrChar);
            SetFlags (EncodedPhraseSpecials, CharType.IsEncodedPhraseSafe, CharType.None, false);
        }

        public static bool IsAscii (byte c)
        {
            return table[c].HasFlag (CharType.IsAscii);
        }

        public static bool IsAtom (byte c)
        {
            return table[c].HasFlag (CharType.IsAtom);
        }

        public static bool IsAttr (byte c)
        {
            return table[c].HasFlag (CharType.IsAttrChar);
        }

        public static bool IsBlank (byte c)
        {
            return table[c].HasFlag (CharType.IsBlank);
        }

        public static bool IsCtrl (byte c)
        {
            return table[c].HasFlag (CharType.IsControl);
        }

        public static bool IsDomain (byte c)
        {
            return table[c].HasFlag (CharType.IsDomainSafe);
        }

        public static bool IsQpSafe (byte c)
        {
            return table[c].HasFlag (CharType.IsQuotedPrintableSafe);
        }

        public static bool IsToken(byte c)
        {
            return !IsTokenSpecial(c) && !IsWhitespace(c) && !IsCtrl(c);
        }

        public static bool IsTokenSpecial (byte c)
        {
            return table[c].HasFlag (CharType.IsTokenSpecial);
        }

        public static bool IsType (byte c, CharType type)
        {
            return (table[c] & type) != 0;
        }

        public static bool IsWhitespace (byte c)
        {
            return table[c].HasFlag (CharType.IsWhitespace);
        }

        public static bool IsXDigit (byte c)
        {
            return table[c].HasFlag (CharType.IsXDigit);
        }

        public static byte ToLower (byte c)
        {
            if (c >= 0x41 && c <= 0x5A)
                return (byte) (c + 0x20);

            return c;
        }

        public static byte ToUpper (byte c)
        {
            if (c >= 0x61 && c <= 0x7A)
                return (byte) (c - 0x20);

            return c;
        }

        public static byte ToXDigit (byte c)
        {
            if (c >= 0x41) {
                if (c >= 0x61)
                    return (byte) (c - (0x61 - 0x0a));

                return (byte) (c - (0x41 - 0x0A));
            }

            return (byte) (c - 0x30);
        }
    }
}
You copied that from here: MimeKit.ByteExtensions

Your Base64Converter class's variables are named exactly the same as the ones in my Base64Encoder/Decoder classes - you even have a method named EstimateOutputLength() which is the same as in mine. Your look-up tables are copied exactly.

You added Base64Converter.cs to your project less than a week ago. Mine has existed since 2012. Are you saying you just magically happened to use the same variable and method names as if by coincidence?

The same for the QuotedPrintableConverter class you added last week.
Your code is nothing special, I can easily create it by myself.
If I was to go all out you'd be as nothing to me. 
If you can create it yourself, why didn't you?
Well, you might be the average skill about programing.
But not only learning how to program, you should learn the etiquette in the online community.
I will have nothing to do with you.
That suits me just fine. Remove those 3 files and any other files you copied from MimeKit.
Mon at 9:33 AM
I would like working together for community, my original idea was that. I not prefer kung fu fighting.

J.Stedfast has a marvellous work with MimeKit code. And golden helpful for

https://mailsystem.codeplex.com/
https://imapx.codeplex.com/
S22.Imap

His thorough knowledge of the subject is very grateful for community, IMHO.

@Higty, great job for me with Higlabo (social media connectors it's great and useful).

Now, with this matter using IMAP and MimeKit.Extensions, I think IMHO better is restarting system :-)

Maybe, you can adding copyright notices, and both can do apologizes itself, not will be Iran - USA issue :-)

Do Peace, not war. Better happy programming, share for community, and using copyright notices if it required using MimeKit code or another share code.

Ask to other authors (MailSystem, Imapx, S22.Imap) , help's J.Stedfast is marvellous for create better componentes and libraries for Imap.

Anyway, IMHO, it would be good synergy and constructive knowledge to grow together in developer Community, because I don't know any collaborate forum about it. Always right copyright notices.

Sorry for any inconvenience this may have caused you, to both.
Mon at 12:36 PM
@kiquenet

Higty has not taken my IMAP code, only my Base64, QuotedPrintable and ByteExtensions code as far as I know.

All I ask is that Higty either add back my copyright notice -or- remove my code from his project.

Either action will satisfy me.
Coordinator
Tue at 6:05 AM
Edited Tue at 6:18 AM
JstedFast said: I sent you an email 24 hours before I posted to the forums about this, not 30 minutes. You must not be factoring in timezone offsets correctly.
You missed the point at issue.That is not so different from.I didn't check mailbox every day.

JstedFast said: You added Base64Converter.cs to your project less than a week ago. Mine has existed since 2012. Are you saying you just magically happened to use the same variable and method names as if by coincidence?
Is there any comment that I don't copy your code?
Let's calm down J.Stedfast.
Such a comment is not good.Especially "magically", "coincidence", and entire of these sentence are provocative.
Poeple who looked your comment might feel that You are strongly opinionated and you are rudeness.
Even though I can keep silence and say nothing, but I dare to advise for you and your future.
Try to be a gentleman and choice more polite word.

JstedFast said: If you can create it yourself, why didn't you?
I say once again for you, this is a "TEMPORARY CHECK IN"
Mime parsing consist of some parts. So, I try to break my work.
A briefly list is here
Header
Key: Value
Rfc2047
Rfc2231
Body
Content-Type : Text
Content-Type : Attachment
Boundary, RecursiveContent
Converter
Base64
QuotedPrintable
...etc

So, I decided to tackle "Header,Body parsing" at first and postpone converter.
To focus on the performance about "Header,Body parsing", I copied your converter roughly.
Because of this, I can compare the performance and logic of my "Header,Body parsing" to yours.
And next step, I had planed to determine whether I use your library with copyright or implement converter by myself.
That's why I postpone to create converter.

JstedFast said: Remove those 3 files and any other files you copied from MimeKit.
I'll remove CharTypeTable.cs, Base64Converter.cs, QuotedPrintableConverter.cs.It's ok.
What are any other files?
Are they your assumption or any evidence?
Point out it with file name and line number.
If you mention nothing about it, I regard above 3 files is all from your next comment.
JstedFast said: Higty has not taken my IMAP code, only my Base64, QuotedPrintable and ByteExtensions code


regards
Coordinator
Tue at 6:10 AM
Edited Today at 5:59 AM
@kiquenet

My mind is always opened.
But without respect each other, things never progress to good direction even if they have great skill.

I am waitng for J.Stedfast to change himself be a gentleman.
It may be merely caused by me, but I have never had such a terrible situation in my 6 years online activity.
I (and you) know J.Stedfast had a trouble for others within a few month.
And Christtian Nilsson say "...And then we have Comments like "Wow, this is pure crap" who wants to work with someone with a attitude like that?"
it is likely to be cause by his attitude than me in statistical point of view, from comparing with my 6 years and his one month.
And more evidences exist.
Generally speaking, "pretty awful","pure crap","Extremely sloppy","pretty slopy" are bad word and not recommended.
I have never use such a word even if private mail.

As you say, better happy programing sounds good.I hope peace world too.
Whenever if I have something wrong, I can apologize.
But there is nothing to apologize.Isn't it?
Because I advised for his being gentleman and point out objective evidence and clear my project circumstance.

I don't deny to work together.
If he apologizes and change his atittude, I consider to work together.
Tue at 1:26 PM
@higty

First off, thanks for removing CharTypeTable.cs and rewriting Base64/QuotedPrintableConverter.
What are any other files?
Are they your assumption or any evidence?
Point out it with file name and line number.
I meant code like this:
// Hack:unroll-loops. Read 4byte per once
uint* dword = (uint*)this.Current;
do
{
    mask = *dword++ ^ 0x0A0A0A0A;
    mask = ((mask - 0x01010101) & (~mask & 0x80808080));
} while (mask == 0);
this.Current = (byte*)(dword - 1);
while (*this.Current != (byte)'\n') { this.Current++; }
You removed one occurrence in MimeStreamBuffer.cs... thank you, but you left in another (in ReadBody), presumably by accident. If you could remove that as well, I would appreciate it, thanks.
Coordinator
Today at 6:57 AM
I think it is a general logic who is familiar with pointer and bit operation like me.
Even though I'm a average programer, nothing special, but I can easily understand it.
For beginner, copyright is required even copying a simple for loop.
But for truly professional, I feel these bit operation are basic knowledge.

But you say so, I try to offer some option that you feel OK.
Tell me what level is acceptable for you.

For example, is it acceptable?
Change variable name.
//Option1
uint* bbbb = (uint*)this.Current;
do
{
    mask = *bbbb ^ 0x0A0A0A0A;
    mask = ((mask - 0x01010101) & (~mask & 0x80808080));
    bbbb++;
} while (mask == 0);
this.Current = (byte*)(bbbb - 1);
// 10 is \n
while (*this.Current != 10) { this.Current++; }
If not, is it acceptable?
Change value of you.
//Option2
mask = ((mask - 0x01010101) & (~mask & 0x40404040));
If both is not, is it acceptable?
I changed logic.
//Option3
uint* bbbb = (uint*)this.Current;
while (true)
{
    mask = *bbbb ^ 0x0A0A0A0A;
    mask = ((mask - 0x01010101) & (~mask & 0x80808080));
    bbbb++;
    if (mask == 0) break;
} 
this.Current = (byte*)(bbbb - 1);
// 10 is \n
while (*this.Current != 10) { this.Current++; }
If not, is performance improvement required?
Your code of assignment to mask is completely unnecessary.
And don't use if statement (like above) but prefer to use while (expression) is better for performance.
My code improve 10% faster than before in my roughly test.
//Option4
uint* bbbb = (uint*)this.Current;
do
{
    mask = *bbbb ^ 0x0A0A0A0A;
    bbbb++;
} while (((mask - 0x01010101) & (~mask & 0x80808080)) == 0);
this.Current = (byte*)(bbbb - 1);
// 10 is \n
while (*this.Current != 10) { this.Current++; }
If all is not, no developer can create product.
It is impossible without duplicating even one code existing in the world.


regards.
Today at 11:53 AM
But you admit you copied it from me. At least that's a start...

How about putting a comment in your code saying so? Isn't that the honest thing to do?

You claim that any programmer familiar with bit masking could have done this, and yet no code I've seen has done so - including yours. That makes it copyrightable.
If all is not, no developer can create product. 
Why can't you go back to using your normal loop?
while (*x != 10)
    x++;
That's an obvious snippet of code that is not copyrightable.

You want me to treat you with respect and yet you continue to treat me with disrespect. Perhaps I should remind you to act like a gentleman and do the honest thing by putting a comment in your code saying you got that loop from me & MimeKit (or you can just take it out if giving me any credit is not to your taste).

I'm only asking for common courtesy.
Today at 2:22 PM
I'll tell you what... since I'm such a nice guy, I'm going to give you some suggestions on replacing that loop with something even faster that I haven't had a chance to implement in MimeKit yet.

That loop is a brute-force approach of finding the end of the line so that I can compare boundary markers.

Are there not algorithms that are better than a brute-force linear search for finding strings in a larger string? (hint: yes)

There are even algorithms that allow you to search for multiple strings (which might be useful if you are nested several multiparts deep, right?).

Has it not occurred to you to try those approaches?

Instead of blindly copying my code, why not think for yourself and find even better ways of doing it? Not only will that get me off your back about copyrights, but it will also mean that your code will be significantly faster than mine because it'll use even more awe-inspiring performance tricks.

If you want to prove that you are a better programmer than me, the way to do it is not to copy my code, the way to do it is to come up with your own solution that is an even better approach than my "average programmer" brute-force approach.

Changing my variable names isn't going to impress anyone. Using an even better algorithm for scanning for the end of the content is the way to impress people... otherwise you'll only be known as "the guy that copied MimeKit".

If you come up with something far better, then I won't be able to claim credit.

Hopefully that has inspired you to be creative and come up with your own solution.