这个类是关于MimeReader的帮助类
看下面代码吧
/// <summary> /// 类说明:Assistant /// 编 码 人:苏飞 /// 联系方式:361983679 /// 更新网站:[url=http://www.cckan.net/thread-655-1-1.html]http://www.cckan.net/thread-655-1-1.html[/url] /// </summary> using System; using System.Collections.Generic; using System.IO; using System.Net.Mime; namespace DotNet.Utilities { /// <summary> /// This class is responsible for parsing a string array of lines /// containing a MIME message. /// </summary> public class MimeReader { private static readonly char[] HeaderWhitespaceChars = new char[] { ' ', ' ' }; private Queue<string> _lines; /// <summary> /// Gets the lines. /// </summary> /// <value>The lines.</value> public Queue<string> Lines { get { return _lines; } } private MimeEntity _entity; /// <summary> /// Initializes a new instance of the <see cref="MimeReader"/> class. /// </summary> private MimeReader() { _entity = new MimeEntity(); } /// <summary> /// Initializes a new instance of the <see cref="MimeReader"/> class. /// </summary> /// <param name="entity">The entity.</param> /// <param name="lines">The lines.</param> private MimeReader(MimeEntity entity, Queue<string> lines) : this() { if (entity == null) { throw new ArgumentNullException("entity"); } if (lines == null) { throw new ArgumentNullException("lines"); } _lines = lines; _entity = new MimeEntity(entity); } /// <summary> /// Initializes a new instance of the <see cref="MimeReader"/> class. /// </summary> /// <param name="lines">The lines.</param> public MimeReader(string[] lines) : this() { if (lines == null) { throw new ArgumentNullException("lines"); } _lines = new Queue<string>(lines); } /// <summary> /// Parse headers into _entity.Headers NameValueCollection. /// </summary> private int ParseHeaders() { string lastHeader = string.Empty; string line = string.Empty; // the first empty line is the end of the headers. while (_lines.Count > 0 && !string.IsNullOrEmpty(_lines.Peek())) { line = _lines.Dequeue(); //if a header line starts with a space or tab then it is a continuation of the //previous line. if (line.StartsWith(" ") || line.StartsWith(Convert.ToString(' '))) { _entity.Headers[lastHeader] = string.Concat(_entity.Headers[lastHeader], line); continue; } int separatorIndex = line.IndexOf(':'); if (separatorIndex < 0) { System.Diagnostics.Debug.WriteLine("Invalid header:{0}", line); continue; } //This is an invalid header field. Ignore this line. string headerName = line.Substring(0, separatorIndex); string headerValue = line.Substring(separatorIndex + 1).Trim(HeaderWhitespaceChars); _entity.Headers.Add(headerName.ToLower(), headerValue); lastHeader = headerName; } if (_lines.Count > 0) { _lines.Dequeue(); } //remove closing header CRLF. return _entity.Headers.Count; } /// <summary> /// Processes mime specific headers. /// </summary> /// <returns>A mime entity with mime specific headers parsed.</returns> private void ProcessHeaders() { foreach (string key in _entity.Headers.AllKeys) { switch (key) { case "content-description": _entity.ContentDescription = _entity.Headers[key]; break; case "content-disposition": _entity.ContentDisposition = new ContentDisposition(_entity.Headers[key]); break; case "content-id": _entity.ContentId = _entity.Headers[key]; break; case "content-transfer-encoding": _entity.TransferEncoding = _entity.Headers[key]; _entity.ContentTransferEncoding = MimeReader.GetTransferEncoding(_entity.Headers[key]); break; case "content-type": _entity.SetContentType(MimeReader.GetContentType(_entity.Headers[key])); break; case "mime-version": _entity.MimeVersion = _entity.Headers[key]; break; } } } /// <summary> /// Creates the MIME entity. /// </summary> /// <returns>A mime entity containing 0 or more children representing the mime message.</returns> public MimeEntity CreateMimeEntity() { try { ParseHeaders(); ProcessHeaders(); ParseBody(); SetDecodedContentStream(); return _entity; } catch { return null; } } /// <summary> /// Sets the decoded content stream by decoding the EncodedMessage /// and writing it to the entity content stream. /// </summary> /// <param name="entity">The entity containing the encoded message.</param> private void SetDecodedContentStream() { switch (_entity.ContentTransferEncoding) { case System.Net.Mime.TransferEncoding.Base64: _entity.Content = new MemoryStream(Convert.FromBase64String(_entity.EncodedMessage.ToString()), false); break; case System.Net.Mime.TransferEncoding.QuotedPrintable: _entity.Content = new MemoryStream(GetBytes(QuotedPrintableEncoding.Decode(_entity.EncodedMessage.ToString())), false); break; case System.Net.Mime.TransferEncoding.SevenBit: default: _entity.Content = new MemoryStream(GetBytes(_entity.EncodedMessage.ToString()), false); break; } } /// <summary> /// Gets a byte[] of content for the provided string. /// </summary> /// <param name="decodedContent">Content.</param> /// <returns>A byte[] containing content.</returns> private byte[] GetBytes(string content) { using (MemoryStream stream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(stream)) { writer.Write(content); } return stream.ToArray(); } } /// <summary> /// Parses the body. /// </summary> private void ParseBody() { if (_entity.HasBoundary) { while (_lines.Count > 0 && !string.Equals(_lines.Peek(), _entity.EndBoundary)) { /*Check to verify the current line is not the same as the parent starting boundary. If it is the same as the parent starting boundary this indicates existence of a new child entity. Return and process the next child.*/ if (_entity.Parent != null && string.Equals(_entity.Parent.StartBoundary, _lines.Peek())) { return; } if (string.Equals(_lines.Peek(), _entity.StartBoundary)) { AddChildEntity(_entity, _lines); } //Parse a new child mime part. else if (string.Equals(_entity.ContentType.MediaType, MediaTypes.MessageRfc822, StringComparison.InvariantCultureIgnoreCase) && string.Equals(_entity.ContentDisposition.DispositionType, DispositionTypeNames.Attachment, StringComparison.InvariantCultureIgnoreCase)) { /*If the content type is message/rfc822 the stop condition to parse headers has already been encountered. But, a content type of message/rfc822 would have the message headers immediately following the mime headers so we need to parse the headers for the attached message now. This is done by creating a new child entity.*/ AddChildEntity(_entity, _lines); break; } else { _entity.EncodedMessage.Append(string.Concat(_lines.Dequeue(), Pop3Commands.Crlf)); } //Append the message content. } } //Parse a multipart message. else { while (_lines.Count > 0) { _entity.EncodedMessage.Append(string.Concat(_lines.Dequeue(), Pop3Commands.Crlf)); } } //Parse a single part message. } /// <summary> /// Adds the child entity. /// </summary> /// <param name="entity">The entity.</param> private void AddChildEntity(MimeEntity entity, Queue<string> lines) { /*if (entity == null) { return; } if (lines == null) { return; }*/ MimeReader reader = new MimeReader(entity, lines); entity.Children.Add(reader.CreateMimeEntity()); } /// <summary> /// Gets the type of the content. /// </summary> /// <param name="contentType">Type of the content.</param> /// <returns></returns> public static ContentType GetContentType(string contentType) { if (string.IsNullOrEmpty(contentType)) { contentType = "text/plain; charset=us-ascii"; } return new ContentType(contentType); } /// <summary> /// Gets the type of the media. /// </summary> /// <param name="mediaType">Type of the media.</param> /// <returns></returns> public static string GetMediaType(string mediaType) { if (string.IsNullOrEmpty(mediaType)) { return "text/plain"; } return mediaType.Trim(); } /// <summary> /// Gets the type of the media main. /// </summary> /// <param name="mediaType">Type of the media.</param> /// <returns></returns> public static string GetMediaMainType(string mediaType) { int separatorIndex = mediaType.IndexOf('/'); if (separatorIndex < 0) { return mediaType; } else { return mediaType.Substring(0, separatorIndex); } } /// <summary> /// Gets the type of the media sub. /// </summary> /// <param name="mediaType">Type of the media.</param> /// <returns></returns> public static string GetMediaSubType(string mediaType) { int separatorIndex = mediaType.IndexOf('/'); if (separatorIndex < 0) { if (mediaType.Equals("text")) { return "plain"; } return string.Empty; } else { if (mediaType.Length > separatorIndex) { return mediaType.Substring(separatorIndex + 1); } else { string mainType = GetMediaMainType(mediaType); if (mainType.Equals("text")) { return "plain"; } return string.Empty; } } } /// <summary> /// Gets the transfer encoding. /// </summary> /// <param name="transferEncoding">The transfer encoding.</param> /// <returns></returns> /// <remarks> /// The transfer encoding determination follows the same rules as /// Peter Huber's article w/ the exception of not throwing exceptions /// when binary is provided as a transferEncoding. Instead it is left /// to the calling code to check for binary. /// </remarks> public static TransferEncoding GetTransferEncoding(string transferEncoding) { switch (transferEncoding.Trim().ToLowerInvariant()) { case "7bit": case "8bit": return System.Net.Mime.TransferEncoding.SevenBit; case "quoted-printable": return System.Net.Mime.TransferEncoding.QuotedPrintable; case "base64": return System.Net.Mime.TransferEncoding.Base64; case "binary": default: return System.Net.Mime.TransferEncoding.Unknown; } } } }