public Article GetArticle(string messageId)
        {
            if (this.connectedServer == null)
            {
                throw new NntpException("No connecting newsserver.");
            }
            if (this.connectedGroup == null)
            {
                throw new NntpException("No connecting newsgroup.");
            }
            Article  article = new Article();
            Response res     = MakeRequest("Article " + messageId);

            if (res.Code != 220)
            {
                throw new NntpException(res.Code);
            }
            int i = res.Message.IndexOf(' ');

            article.ArticleId = int.Parse(res.Message.Substring(0, i));
            article.MessageId = res.Message.Substring(i + 1, res.Message.IndexOf(' ', i + 1));
            MIMEPart part = null;

            article.Header = this.GetHeader(messageId, out part);
            if (part == null)
            {
                article.Body = this.GetNormalBody(messageId);
            }
            else
            {
                article.Body = this.GetMIMEBody(messageId, part);
            }
            return(article);
        }
        private ArticleBody GetMIMEBody(string messageId, MIMEPart part)
        {
            string        line           = null;
            ArticleBody   body           = null;
            StringBuilder sb             = null;
            ArrayList     attachmentList = new ArrayList();

            try
            {
                NntpUtil.DispatchMIMEContent(sr, part, ".");
                sb             = new StringBuilder();
                attachmentList = new ArrayList();
                body           = new ArticleBody();
                body.IsHtml    = true;
                this.ConvertMIMEContent(messageId, part, sb, attachmentList);
                body.Text        = sb.ToString();
                body.Attachments = (Attachment[])attachmentList.ToArray(typeof(Attachment));
            }
            finally
            {
                if (((NetworkStream)sr.BaseStream).DataAvailable)
                {
                    while ((line = sr.ReadLine()) != null && line != ".")
                    {
                        ;
                    }
                }
            }
            return(body);
        }
        private void ConvertMIMEContent(string messageId, MIMEPart part, StringBuilder sb, ArrayList attachmentList)
        {
            Match m = null;

            m = Regex.Match(part.ContentType, @"MULTIPART", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                foreach (MIMEPart subPart in part.EmbeddedPartList)
                {
                    this.ConvertMIMEContent(messageId, subPart, sb, attachmentList);
                }
                return;
            }
            m = Regex.Match(part.ContentType, @"TEXT", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                sb.Append(part.Text);
                sb.Append("<hr>");
                return;
            }
            Attachment attachment = new Attachment(messageId + " - " + part.Filename, part.Filename, part.BinaryData);

            attachmentList.Add(attachment);
        }
        private ArticleHeader GetHeader(string messageId, out MIMEPart part)
        {
            string        response = null;
            ArticleHeader header   = new ArticleHeader();
            string        name     = null;
            string        value    = null;

            header.ReferenceIds = new string[0];
            string[] values  = null;
            string[] values2 = null;
            Match    m       = null;

            part = null;
            int i = -1;

            while ((response = sr.ReadLine()) != null && response != "")
            {
                m = Regex.Match(response, @"^\s+(\S+)$");
                if (m.Success)
                {
                    value = m.Groups[1].ToString();
                }
                else
                {
                    i = response.IndexOf(':');
                    if (i == -1)
                    {
                        continue;
                    }
                    name  = response.Substring(0, i).ToUpper();
                    value = response.Substring(i + 1);
                }
                switch (name)
                {
                case "REFERENCES":
                    values              = value.Split(' ');
                    values2             = header.ReferenceIds;
                    header.ReferenceIds = new string[values.Length + values2.Length];
                    values.CopyTo(header.ReferenceIds, 0);
                    values2.CopyTo(header.ReferenceIds, values.Length);
                    break;

                case "SUBJECT":
                    header.Subject += NntpUtil.Base64HeaderDecode(value);
                    break;

                case "DATE":
                    i           = value.IndexOf(',');
                    header.Date = DateTime.Parse(value.Substring(i + 1, value.Length - 7 - i));
                    break;

                case "FROM":
                    header.From += NntpUtil.Base64HeaderDecode(value);
                    break;

                case "NNTP-POSTING-HOST":
                    header.PostingHost += value;
                    break;

                case "LINES":
                    header.LineCount = int.Parse(value);
                    break;

                case "MIME-VERSION":
                    part                         = new MIMEPart();
                    part.ContentType             = "TEXT/PLAIN";
                    part.Charset                 = "US-ASCII";
                    part.ContentTransferEncoding = "7BIT";
                    part.Filename                = null;
                    part.Boundary                = null;
                    break;

                case "CONTENT-TYPE":
                    if (part != null)
                    {
                        m = Regex.Match(response, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            part.ContentType = m.Groups[1].ToString();
                        }
                        m = Regex.Match(response, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            part.Boundary         = m.Groups[1].ToString();
                            part.EmbeddedPartList = new ArrayList();
                        }
                        m = Regex.Match(response, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            part.Charset = m.Groups[1].ToString();
                        }
                        m = Regex.Match(response, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            part.Filename = m.Groups[1].ToString();
                        }
                    }
                    break;

                case "CONTENT-TRANSFER-ENCODING":
                    if (part != null)
                    {
                        m = Regex.Match(response, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            part.ContentTransferEncoding = m.Groups[1].ToString();
                        }
                    }
                    break;
                }
            }
            return(header);
        }
        public static MIMEPart DispatchMIMEContent( StreamReader sr, MIMEPart part, string seperator )
        {
            string line = null;
            Match m = null;
            MemoryStream ms;
            byte[] bytes;
            switch ( part.ContentType.Substring(0, part.ContentType.IndexOf('/')).ToUpper() )
            {
                case "MULTIPART":
                    MIMEPart newPart = null;
                    while ( (line = sr.ReadLine()) != null && line != seperator && line != seperator + "--" )
                    {
                        m = Regex.Match(line, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if ( !m.Success )
                        {
                            continue;
                        }
                        newPart = new MIMEPart();
                        newPart.ContentType = m.Groups[1].ToString();
                        newPart.Charset = "US-ASCII";
                        newPart.ContentTransferEncoding = "7BIT";
                        while ( line != "" )
                        {
                            m = Regex.Match(line, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                            if ( m.Success )
                            {
                                newPart.Boundary = m.Groups[1].ToString();
                                newPart.EmbeddedPartList = new ArrayList();
                            }
                            m = Regex.Match(line, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                            if ( m.Success )
                            {
                                newPart.Charset = m.Groups[1].ToString();
                            }
                            m = Regex.Match(line, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase);
                            if ( m.Success )
                            {
                                newPart.ContentTransferEncoding = m.Groups[1].ToString();
                            }
                            m = Regex.Match(line, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                            if ( m.Success )
                            {
                                newPart.Filename = Base64HeaderDecode(m.Groups[1].ToString());
                                newPart.Filename = newPart.Filename.Substring( newPart.Filename.LastIndexOfAny(new char[]{'\\', '/'}) + 1 );
                            }
                            line = sr.ReadLine();
                        }
                        part.EmbeddedPartList.Add(DispatchMIMEContent(sr, newPart, "--" + part.Boundary));
                    }
                    break;
                case "TEXT":
                    ms = new MemoryStream();
                    bytes = null;
                    long pos;
                    StreamReader msr = new StreamReader(ms, Encoding.GetEncoding(part.Charset));
                    StringBuilder sb = new StringBuilder();
                    while ( (line = sr.ReadLine()) != null && line != seperator && line != seperator + "--" )
                    {
                        pos = ms.Position;
                        if ( line != "" )
                        {
                            switch ( part.ContentTransferEncoding.ToUpper() )
                            {
                                case "QUOTED-PRINTABLE":
                                    NntpUtil.QuotedPrintableDecode(line, ms);
                                    break;
                                case "BASE64":
                                    if ( line != null && line != "" )
                                        NntpUtil.Base64Decode(line, ms);
                                    break;
                                case "UU":
                                    if ( line != null && line != "" )
                                        NntpUtil.UUDecode(line, ms);
                                    break;
                                case "7BIT":
                                    bytes = Encoding.ASCII.GetBytes(line);
                                    ms.Write(bytes, 0, bytes.Length);
                                    ms.WriteByte((byte)'\n');
                                    break;
                                default:
                                    bytes = Encoding.ASCII.GetBytes(line);
                                    ms.Write(bytes, 0, bytes.Length);
                                    ms.WriteByte((byte)'\n');
                                    break;
                            }
                        }
                        ms.Position = pos;
                        if ( part.ContentType.ToUpper() == "TEXT/HTML" )
                        {
                            sb.Append( msr.ReadToEnd() );
                        }
                        else
                        {
                            sb.Append( HttpUtility.HtmlEncode( msr.ReadToEnd() ).Replace("\n", "<br>\n") );
                        }
                    }
                    part.Text = sb.ToString();
                    break;
                default:
                    ms = new MemoryStream();
                    bytes = null;
                    while ( (line = sr.ReadLine()) != null && line != seperator && line != seperator + "--" )
                    {
                        if ( line != "" )
                        {
                            switch ( part.ContentTransferEncoding.ToUpper() )
                            {
                                case "QUOTED-PRINTABLE":
                                    NntpUtil.QuotedPrintableDecode(line, ms);
                                    break;
                                case "BASE64":
                                    if ( line != null && line != "" )
                                        NntpUtil.Base64Decode(line, ms);
                                    break;
                                case "UU":
                                    if ( line != null && line != "" )
                                        NntpUtil.UUDecode(line, ms);
                                    break;
                                default:
                                    bytes = Encoding.ASCII.GetBytes(line);
                                    ms.Write(bytes, 0, bytes.Length);
                                    break;
                            }
                        }
                    }
                    ms.Seek( 0, SeekOrigin.Begin );
                    part.BinaryData = new byte[ms.Length];
                    ms.Read(part.BinaryData, 0, (int)ms.Length);
                    break;
            }

            return part;
        }
        public static MIMEPart DispatchMIMEContent(StreamReader sr, MIMEPart part, string seperator)
        {
            string       line = null;
            Match        m    = null;
            MemoryStream ms;

            byte[] bytes;
            switch (part.ContentType.Substring(0, part.ContentType.IndexOf('/')).ToUpper())
            {
            case "MULTIPART":
                MIMEPart newPart = null;
                while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--")
                {
                    m = Regex.Match(line, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase);
                    if (!m.Success)
                    {
                        continue;
                    }
                    newPart                         = new MIMEPart();
                    newPart.ContentType             = m.Groups[1].ToString();
                    newPart.Charset                 = "US-ASCII";
                    newPart.ContentTransferEncoding = "7BIT";
                    while (line != "")
                    {
                        m = Regex.Match(line, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            newPart.Boundary         = m.Groups[1].ToString();
                            newPart.EmbeddedPartList = new ArrayList();
                        }
                        m = Regex.Match(line, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            newPart.Charset = m.Groups[1].ToString();
                        }
                        m = Regex.Match(line, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            newPart.ContentTransferEncoding = m.Groups[1].ToString();
                        }
                        m = Regex.Match(line, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            newPart.Filename = Base64HeaderDecode(m.Groups[1].ToString());
                            newPart.Filename = newPart.Filename.Substring(newPart.Filename.LastIndexOfAny(new char[] { '\\', '/' }) + 1);
                        }
                        line = sr.ReadLine();
                    }
                    part.EmbeddedPartList.Add(DispatchMIMEContent(sr, newPart, "--" + part.Boundary));
                }
                break;

            case "TEXT":
                ms    = new MemoryStream();
                bytes = null;
                long          pos;
                StreamReader  msr = new StreamReader(ms, Encoding.GetEncoding(part.Charset));
                StringBuilder sb  = new StringBuilder();
                while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--")
                {
                    pos = ms.Position;
                    if (line != "")
                    {
                        switch (part.ContentTransferEncoding.ToUpper())
                        {
                        case "QUOTED-PRINTABLE":
                            NntpUtil.QuotedPrintableDecode(line, ms);
                            break;

                        case "BASE64":
                            if (line != null && line != "")
                            {
                                NntpUtil.Base64Decode(line, ms);
                            }
                            break;

                        case "UU":
                            if (line != null && line != "")
                            {
                                NntpUtil.UUDecode(line, ms);
                            }
                            break;

                        case "7BIT":
                            bytes = Encoding.ASCII.GetBytes(line);
                            ms.Write(bytes, 0, bytes.Length);
                            ms.WriteByte((byte)'\n');
                            break;

                        default:
                            bytes = Encoding.ASCII.GetBytes(line);
                            ms.Write(bytes, 0, bytes.Length);
                            ms.WriteByte((byte)'\n');
                            break;
                        }
                    }
                    ms.Position = pos;
                    if (part.ContentType.ToUpper() == "TEXT/HTML")
                    {
                        sb.Append(msr.ReadToEnd());
                    }
                    else
                    {
                        sb.Append(HttpUtility.HtmlEncode(msr.ReadToEnd()).Replace("\n", "<br>\n"));
                    }
                }
                part.Text = sb.ToString();
                break;

            default:
                ms    = new MemoryStream();
                bytes = null;
                while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--")
                {
                    if (line != "")
                    {
                        switch (part.ContentTransferEncoding.ToUpper())
                        {
                        case "QUOTED-PRINTABLE":
                            NntpUtil.QuotedPrintableDecode(line, ms);
                            break;

                        case "BASE64":
                            if (line != null && line != "")
                            {
                                NntpUtil.Base64Decode(line, ms);
                            }
                            break;

                        case "UU":
                            if (line != null && line != "")
                            {
                                NntpUtil.UUDecode(line, ms);
                            }
                            break;

                        default:
                            bytes = Encoding.ASCII.GetBytes(line);
                            ms.Write(bytes, 0, bytes.Length);
                            break;
                        }
                    }
                }
                ms.Seek(0, SeekOrigin.Begin);
                part.BinaryData = new byte[ms.Length];
                ms.Read(part.BinaryData, 0, (int)ms.Length);
                break;
            }

            return(part);
        }