protected virtual void ParseBody() { string strFullConentType = _headers["Content-Type"]; if (strFullConentType == null) { strFullConentType = ""; } //string strContentTypeValue = null; Hashtable parametrs; MimeEntry.ParseHeader(strFullConentType, out _contentType, out parametrs); // Step 2. Parse Messagy Body [1/23/2004] if (!_contentType.StartsWith("multipart/")) { _charSet = (string)parametrs["charset"]; if (_charSet == null) { _charSet = Encoding.Default.HeaderName; } string ContentEncoding = _headers["Content-Transfer-Encoding"]; if (ContentEncoding == null) { ContentEncoding = "8bit"; } string strDisposition = _headers["Content-Disposition"]; if (strDisposition != null) { Hashtable DispositionParameters; string DispositionType; MimeEntry.ParseHeader(strDisposition, out DispositionType, out DispositionParameters); DispositionType = DispositionType.ToLower(); if (DispositionType == "attachment") { this._disposition = Disposition.Attachment; } else if (DispositionType == "inline") { this._disposition = Disposition.Inline; } _fileName = (string)DispositionParameters["filename"]; if (_fileName != null) { _fileName = Rfc822HeaderCollection.DeocodeHeaderValue(_fileName); } } //string BodyString = Encoding.Default.GetString(this._BinaryData.GetBuffer(),this._BodyOffset,(int)(this._BinaryData.Length - this._BodyOffset)); Encoding encoding = null; try { encoding = Encoding.GetEncoding(CharSet); } catch { encoding = Encoding.Default; } string BodyString = encoding.GetString(this._BinaryData.GetBuffer(), this._BodyOffset, (int)(this._BinaryData.Length - this._BodyOffset)); //string BodyString = Encoding.ASCII.GetString(this._BinaryData.GetBuffer(),this._BodyOffset,(int)(this._BinaryData.Length - this._BodyOffset)); //string BodyString2 = Encoding.UTF8.GetString(this._BinaryData.GetBuffer(),this._BodyOffset,(int)(this._BinaryData.Length - this._BodyOffset)); switch (ContentEncoding.ToLower()) { case "quoted-printable": _body = encoding.GetBytes(MimeEntry.QDecode(encoding, BodyString)); break; case "7bit": //_body = Encoding.ASCII.GetBytes(BodyString); _body = encoding.GetBytes(BodyString); break; default: case "8bit": _body = encoding.GetBytes(BodyString); break; case "base64": BodyString = BodyString.Trim(); if (BodyString.Length > 0) { int base64FixCount = 0; // Fix If Base 64 is broken while (true) { try { _body = Convert.FromBase64String(BodyString); break; } catch (System.FormatException) { // Remove not supported chars if (base64FixCount == 0) { BodyString = Regex.Replace(BodyString, "[^a-zA-Z0-9+/=]+", string.Empty); } else if (base64FixCount == 1) { BodyString += "="; } else { BodyString = BodyString.Substring(0, BodyString.Length - 1); } if (BodyString.Length == 0 || base64FixCount == 25) // Max 25 Attempts to fix chars { _body = new byte[] { }; break; } base64FixCount++; } } } else { _body = new byte[] {} }; break; case "binary": _body = encoding.GetBytes(BodyString); break; //default: // throw new Pop3ServerIncorectEMailFormatException("Not supported content-encoding " + ContentEncoding + " !"); } } else { DataParseStatus parseStatus = _mimeEntries.ParseMimeEntries(_BinaryData.GetBuffer(), (int)_BinaryData.Length, ref _BodyOffset, this.Headers); } }
public DataParseStatus ParseHeaders(byte[] buffer, int size, ref int unparsed) { int headerKeyBegin = -1; int hederKeyEnd = -1; int finalCLRNCount = -1; int currIndex = unparsed; Encoding defaultEncoding = Encoding.Default; do { string strHeader = String.Empty; bool flag1 = false; bool isHeaderKeyUTF8 = false; bool isHeaderValueUTF8 = false; string strHeaderValue = null; if (base.Count == 0) { while (currIndex < size && (buffer[currIndex] == 32 || /*[space]*/ buffer[currIndex] == 9)) { currIndex++; } if (currIndex == size) { return(DataParseStatus.NeedMoreData); } } headerKeyBegin = currIndex; for (; currIndex < size && buffer[currIndex] != 58 /*:*/ && buffer[currIndex] != 10; currIndex++) { if (buffer[currIndex] > 32 /*[space]*/) { hederKeyEnd = currIndex; //isHeaderKeyUTF8 = !isHeaderKeyUTF8 ? (buffer[currIndex] > 127) : true; } } if (currIndex == size) { return(DataParseStatus.NeedMoreData); } while (true) { string strHeaderValueTmp = String.Empty; int headerValueBegin = -1; int headerValueEnd = -1; for (finalCLRNCount = (base.Count != 0 || hederKeyEnd >= 0) ? 0 : 1; currIndex < size && finalCLRNCount < 2 && (buffer[currIndex] <= 32 /*[space]*/ || buffer[currIndex] == 58); currIndex++) { if (buffer[currIndex] == 10) { finalCLRNCount++; flag1 = (currIndex + 1 < size) ? ((buffer[currIndex + 1] != 32 /*[space]*/) ? (buffer[currIndex + 1] == 9) : true) : false; } } if (finalCLRNCount != 2 && (finalCLRNCount != 1 || flag1)) { if (currIndex == size) { return(DataParseStatus.NeedMoreData); } headerValueBegin = currIndex; for (; currIndex < size && buffer[currIndex] != 10; currIndex++) { if (buffer[currIndex] > 32 /*[space]*/) { headerValueEnd = currIndex; //isHeaderValueUTF8 = !isHeaderValueUTF8 ? (buffer[currIndex] > 127) : true; } } if (currIndex == size) { return(DataParseStatus.NeedMoreData); } for (finalCLRNCount = 0; currIndex < size && finalCLRNCount < 2 && (buffer[currIndex] == 13 || buffer[currIndex] == 10); currIndex++) { if (buffer[currIndex] == 10) { finalCLRNCount++; } } if (currIndex == size && finalCLRNCount < 2) { return(DataParseStatus.NeedMoreData); } } if (headerValueBegin >= 0 && headerValueBegin > hederKeyEnd && headerValueEnd >= headerValueBegin) { if (isHeaderValueUTF8) { strHeaderValueTmp = Encoding.UTF8.GetString(buffer, headerValueBegin, headerValueEnd - headerValueBegin + 1); } else { strHeaderValueTmp = defaultEncoding.GetString(buffer, headerValueBegin, headerValueEnd - headerValueBegin + 1); } } strHeaderValue = (strHeaderValue != null) ? String.Concat(strHeaderValue, " ", strHeaderValueTmp) : strHeaderValueTmp; if (currIndex >= size || finalCLRNCount != 1 || buffer[currIndex] != 32 /*[space]*/ && buffer[currIndex] != 9) { break; } currIndex++; } if (headerKeyBegin >= 0 && hederKeyEnd >= headerKeyBegin) { if (isHeaderKeyUTF8) { strHeader = Encoding.UTF8.GetString(buffer, headerKeyBegin, hederKeyEnd - headerKeyBegin + 1); } else { strHeader = Encoding.ASCII.GetString(buffer, headerKeyBegin, hederKeyEnd - headerKeyBegin + 1); } } if (strHeader.Length > 0) { string strValue = DeocodeHeaderValue(strHeaderValue); base.Add(strHeader, strValue); if (strHeader == "Content-Type") { string strContentType; Hashtable parametrs; MimeEntry.ParseHeader(strValue, out strContentType, out parametrs); string strCharset = (string)parametrs["charset"]; if (!string.IsNullOrEmpty(strCharset)) { try { defaultEncoding = Encoding.GetEncoding(strCharset); } catch { defaultEncoding = Encoding.Default; } } } } unparsed = currIndex; }while (finalCLRNCount != 2); //this.IsReadOnly = true; return(DataParseStatus.Done); }
public static string DeocodeHeaderValue(string headerValue) { // Cool Encoding [2/13/2004] MatchCollection matchList = Regex.Matches(headerValue, @"(?<encodedword>=\?(?<charset>[^?]+)\?(?<encoding>[^?]+)\?(?<encodedtext>[^?]+)\?=)"); if (matchList.Count > 0) { // Fix: White space between adjacent 'encoded-word's is not displayed // [2007-07-03] TODO (=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=) -> (ab) // [2007-07-03] TODO (=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=) -> (ab) // [2007-07-03] TODO (=?ISO-8859-1?Q?a?=\r\n =?ISO-8859-1?Q?b?=) -> (ab) headerValue = Regex.Replace(headerValue, @"\?=[ ]+=\?", @"?==?"); System.Text.StringBuilder strBilder = new System.Text.StringBuilder(headerValue); foreach (Match matchItem in matchList) { string strEncodedWord = matchItem.Groups["encodedword"].Value; string strCharset = matchItem.Groups["charset"].Value; string strEncoding = matchItem.Groups["encoding"].Value; string strEncodedText = matchItem.Groups["encodedtext"].Value; if (matchItem.Groups["spaceceprator"].Success) { strBilder.Replace(strEncodedWord + matchItem.Groups["spaceceprator"].Value, strEncodedWord); } System.Text.Encoding encoder = System.Text.Encoding.GetEncoding(strCharset); string DecodedString = null; if (strEncoding.ToUpper() == "Q") { // FIX: The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be // represented as "_" (underscore, ASCII 95.). (This character may // not pass through some internetwork mail gateways, but its use // will greatly enhance readability of "Q" encoded data with mail // readers that do not support this encoding.) DecodedString = MimeEntry.QDecode(encoder, strEncodedText.Replace('_', ' ')); } else if (strEncoding.ToUpper() == "B") { int base64FixCount = 0; while (true) { try { byte[] FromBase64String = Convert.FromBase64String(strEncodedText); DecodedString = encoder.GetString(FromBase64String); break; } catch (System.FormatException) { // Remove not supported chars if (base64FixCount == 0) { strEncodedText = Regex.Replace(strEncodedText, "[^a-zA-Z0-9+/=]+", string.Empty); } else if (base64FixCount == 1) { strEncodedText += "="; } else { strEncodedText = strEncodedText.Substring(0, strEncodedText.Length - 1); } if (strEncodedText.Length == 0 || base64FixCount == 25) // Max 25 Attempts to fix chars { DecodedString = null; break; } base64FixCount++; } } } if (DecodedString != null) { strBilder.Replace(strEncodedWord, DecodedString); } } return(strBilder.ToString()); } // if(headerValue.StartsWith("=?")) // { // string[] parts = headerValue.Substring(2).Split(new char[]{'?'}); // // string encoderName = parts[0]; // string type = parts[1]; // string datax = parts[2]; // // System.Text.Encoding encoder = System.Text.Encoding.GetEncoding(encoderName); // if(type.ToUpper() == "Q") // { // return MimeEntry.QDecode(encoder,datax); // } // else if(type.ToUpper() == "B") // { // return encoder.GetString(Convert.FromBase64String(datax)); // } // } return(headerValue); }
protected void SaveMimeEntry(System.IO.StreamWriter writer, MimeEntry entry) { if(entry.ContentDisposition==Disposition.Attachment) return; // Step 2. Process Mime Entry [5/11/2004] string ContentType = entry.Headers["Content-Type"]; Hashtable ContentTypeParametrs = ParseHeaderLine(ContentType); string ContentTypeBoundary = (string)ContentTypeParametrs["boundary"]; // if(ContentType==null) // ContentType = "Content-Type: text/html; charset=\"utf-8\""; if(entry.Body!=null &&ContentTypeBoundary==null) { writer.Write("\r\n------=_NextPart_000_0000_01C26874.EA4F5D40\r\n"); SaveHeaders(writer,entry.Headers); // if(ContentType.IndexOf("text/html")!=-1) // { // writer.Write(Convert.ToBase64String(Encoding.UTF8.GetBytes(entry.BodyText))); // } if(ContentType==null) { ContentType = "Content-Type: text/html; charset=\"utf-8\""; writer.Write(Convert.ToBase64String(Encoding.UTF8.GetBytes(entry.BodyText))); } else writer.Write(Convert.ToBase64String(entry.Body)); } foreach(MimeEntry childEntry in entry.MimeEntries) { SaveMimeEntry(writer,childEntry); } }
internal DataParseStatus ParseMimeEntries(byte[] buffer, int size, ref int unparsed, Rfc822HeaderCollection headers) { string strFullConentType = headers["Content-Type"]; if(strFullConentType==null) strFullConentType=""; string strContentTypeValue = null; Hashtable parametrs; MimeEntry.ParseHeader(strFullConentType, out strContentTypeValue, out parametrs); if(!strContentTypeValue.StartsWith("multipart/", true, CultureInfo.InvariantCulture)) { // Simple Email [1/27/2004] MemoryStream strmEntry = new MemoryStream(); strmEntry.Write(buffer, unparsed, size - unparsed); this.Add(new MimeEntry(strmEntry,headers)); } else { // Parse Multipart Value string boundaryID = (string)parametrs["boundary"]; // Step 1. Unpack multipart [2/10/2004] StreamLineReader lineReader = new StreamLineReader (buffer, unparsed, size); byte[] lineData = lineReader.ReadLine(); // Step 1.1 Search first entry while(lineData!=null) { string strLine = System.Text.Encoding.Default.GetString(lineData); if(strLine.StartsWith("--" + boundaryID)) { lineData = lineReader.ReadLine(); break; } lineData = lineReader.ReadLine(); } // Step 1.2 Start reading entries MemoryStream strmEntry = new MemoryStream(); while(lineData!=null) { string strLine = System.Text.Encoding.Default.GetString(lineData); if(strLine.StartsWith("--" + boundaryID) && strmEntry.Length > 0) { // Step 1.3 Add Entry try { MimeEntry newEntry = new MimeEntry(strmEntry); this.Add(newEntry); } catch (Pop3ServerIncorectEMailFormatException ex) { // Skeep Broken Entry if (ex.InnerException != null) throw; } strmEntry.SetLength(0); } else { strmEntry.Write(lineData,0,lineData.Length); strmEntry.Write(new byte[]{(byte)'\r',(byte)'\n'},0,2); } lineData = lineReader.ReadLine(); } } return DataParseStatus.Done; }
internal void Add(MimeEntry newItem) { this.List.Add(newItem); }
internal DataParseStatus ParseMimeEntries(byte[] buffer, int size, ref int unparsed, Rfc822HeaderCollection headers) { string strFullConentType = headers["Content-Type"]; if (strFullConentType == null) { strFullConentType = ""; } string strContentTypeValue = null; Hashtable parametrs; MimeEntry.ParseHeader(strFullConentType, out strContentTypeValue, out parametrs); if (!strContentTypeValue.StartsWith("multipart/", true, CultureInfo.InvariantCulture)) { // Simple Email [1/27/2004] MemoryStream strmEntry = new MemoryStream(); strmEntry.Write(buffer, unparsed, size - unparsed); this.Add(new MimeEntry(strmEntry, headers)); } else { // Parse Multipart Value string boundaryID = (string)parametrs["boundary"]; // Step 1. Unpack multipart [2/10/2004] StreamLineReader lineReader = new StreamLineReader(buffer, unparsed, size); byte[] lineData = lineReader.ReadLine(); // Step 1.1 Search first entry while (lineData != null) { string strLine = System.Text.Encoding.Default.GetString(lineData); if (strLine.StartsWith("--" + boundaryID)) { lineData = lineReader.ReadLine(); break; } lineData = lineReader.ReadLine(); } // Step 1.2 Start reading entries MemoryStream strmEntry = new MemoryStream(); while (lineData != null) { string strLine = System.Text.Encoding.Default.GetString(lineData); if (strLine.StartsWith("--" + boundaryID) && strmEntry.Length > 0) { // Step 1.3 Add Entry try { MimeEntry newEntry = new MimeEntry(strmEntry); this.Add(newEntry); } catch (Pop3ServerIncorectEMailFormatException ex) { // Skeep Broken Entry if (ex.InnerException != null) { throw; } } strmEntry.SetLength(0); } else { strmEntry.Write(lineData, 0, lineData.Length); strmEntry.Write(new byte[] { (byte)'\r', (byte)'\n' }, 0, 2); } lineData = lineReader.ReadLine(); } } return(DataParseStatus.Done); }