public void Parse() { using (var reader = new TnefReader(new MemoryStream(this.RawBinary), 0, TnefComplianceMode.Loose)) { while (reader.ReadNextAttribute()) { if (reader.AttributeLevel == TnefAttributeLevel.Attachment) { break; } TnefPropertyReader prop = reader.TnefPropertyReader; switch (reader.AttributeTag) { case TnefAttributeTag.RecipientTable: while (prop.ReadNextRow()) { string name = null, addr = null; while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.RecipientType: int recipientType = prop.ReadValueAsInt32(); switch (recipientType) { case 1: Console.WriteLine("To:"); break; case 2: Console.WriteLine("Cc:"); break; case 3: Console.WriteLine("Bcc:"); break; } break; case TnefPropertyId.TransmitableDisplayName: if (string.IsNullOrEmpty(name)) { name = prop.ReadValueAsString(); } else { } break; case TnefPropertyId.DisplayName: name = prop.ReadValueAsString(); break; case TnefPropertyId.EmailAddress: if (string.IsNullOrEmpty(addr)) { addr = prop.ReadValueAsString(); } else { } break; case TnefPropertyId.SmtpAddress: // The SmtpAddress, if it exists, should take precedence over the EmailAddress // (since the SmtpAddress is meant to be used in the RCPT TO command). addr = prop.ReadValueAsString(); break; default: break; } } } break; case TnefAttributeTag.MapiProperties: while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.InternetMessageId: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { } else { } break; case TnefPropertyId.Subject: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { this.Subject = prop.ReadValueAsString(); } else { } break; case TnefPropertyId.RtfCompressed: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { //var rtf = new TextPart("rtf"); //rtf.ContentType.Name = "body.rtf"; //var converter = new RtfCompressedToRtf(); //var content = new MemoryStream(); //using (var filtered = new FilteredStream(content)) //{ // filtered.Add(converter); // using (var compressed = prop.GetRawValueReadStream()) // { // compressed.CopyTo(filtered, 4096); // filtered.Flush(); // } //} //rtf.ContentObject = new ContentObject(content); //content.Position = 0; //builder.Attachments.Add(rtf); } else { } break; case TnefPropertyId.BodyHtml: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { this.HtmlBody = prop.ReadValueAsString(); } else { } break; case TnefPropertyId.Body: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { this.TextBody = prop.ReadValueAsString(); } else { } break; default: object val; try { val = prop.ReadValue(); } catch { val = null; } String key = prop.PropertyTag.Id.ToString(); switch (key) { case "SenderName": if (this.Sender == null) { this.Sender = new TnefAddress(); } this.Sender.Display = val.ToString().Trim(); break; case "SenderEmailAddress": if (this.Sender == null) { this.Sender = new TnefAddress(); } this.Sender.Address = val.ToString().Trim(); break; } break; } } break; case TnefAttributeTag.DateSent: this.DateSent = prop.ReadValueAsDateTime(); break; case TnefAttributeTag.Body: break; case TnefAttributeTag.OemCodepage: int codepage = prop.ReadValueAsInt32(); try { var encoding = Encoding.GetEncoding(codepage); } catch { } break; } } if (reader.AttributeLevel == TnefAttributeLevel.Attachment) { TnefPropertyReader propertyReader = reader.TnefPropertyReader; TnefAttachMethod attachMethod = TnefAttachMethod.ByValue; TnefAttachFlags attachFlags; TnefAttachment attachment = null; do { if (reader.AttributeLevel != TnefAttributeLevel.Attachment) { } switch (reader.AttributeTag) { case TnefAttributeTag.AttachRenderData: attachMethod = TnefAttachMethod.ByValue; attachment = new TnefAttachment(); break; case TnefAttributeTag.Attachment: if (attachment == null) { break; } while (propertyReader.ReadNextProperty()) { switch (propertyReader.PropertyTag.Id) { case TnefPropertyId.AttachLongFilename: attachment.FileName = propertyReader.ReadValueAsString(); break; case TnefPropertyId.AttachFilename: if (String.IsNullOrEmpty(attachment.FileName)) { attachment.FileName = propertyReader.ReadValueAsString(); } else { } break; case TnefPropertyId.AttachContentLocation: break; case TnefPropertyId.AttachContentBase: break; case TnefPropertyId.AttachContentId: break; case TnefPropertyId.AttachDisposition: break; case TnefPropertyId.AttachMethod: attachMethod = (TnefAttachMethod)propertyReader.ReadValueAsInt32(); break; case TnefPropertyId.AttachMimeTag: attachment.MimeType = propertyReader.ReadValueAsString(); break; case TnefPropertyId.AttachFlags: attachFlags = (TnefAttachFlags)propertyReader.ReadValueAsInt32(); break; case TnefPropertyId.AttachData: Stream stream = propertyReader.GetRawValueReadStream(); byte[] guid = new byte[16]; stream.Read(guid, 0, 16); break; case TnefPropertyId.DisplayName: break; case TnefPropertyId.AttachSize: break; default: break; } } break; case TnefAttributeTag.AttachData: if (attachment == null || attachMethod != TnefAttachMethod.ByValue) { break; } attachment.BinaryContent = propertyReader.ReadValueAsBytes(); this.Attachments.Add(attachment); break; case TnefAttributeTag.AttachCreateDate: break; case TnefAttributeTag.AttachModifyDate: break; case TnefAttributeTag.AttachTitle: break; default: break; } }while (reader.ReadNextAttribute()); } else { } } }
public void Debug() { using (var reader = new TnefReader(new MemoryStream(this.RawBinary), 0, TnefComplianceMode.Loose)) { while (reader.ReadNextAttribute()) { if (reader.AttributeLevel == TnefAttributeLevel.Attachment) { break; } TnefPropertyReader prop = reader.TnefPropertyReader; switch (reader.AttributeTag) { case TnefAttributeTag.RecipientTable: while (prop.ReadNextRow()) { string name = null, addr = null; while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.RecipientType: int recipientType = prop.ReadValueAsInt32(); switch (recipientType) { case 1: Console.WriteLine("To:"); break; case 2: Console.WriteLine("Cc:"); break; case 3: Console.WriteLine("Bcc:"); break; } Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, recipientType); break; case TnefPropertyId.TransmitableDisplayName: if (string.IsNullOrEmpty(name)) { name = prop.ReadValueAsString(); Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, name); } else { Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); } break; case TnefPropertyId.DisplayName: name = prop.ReadValueAsString(); Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, name); break; case TnefPropertyId.EmailAddress: if (string.IsNullOrEmpty(addr)) { addr = prop.ReadValueAsString(); Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, addr); } else { Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); } break; case TnefPropertyId.SmtpAddress: // The SmtpAddress, if it exists, should take precedence over the EmailAddress // (since the SmtpAddress is meant to be used in the RCPT TO command). addr = prop.ReadValueAsString(); Console.WriteLine("RecipientTable Property: {0} = {1}", prop.PropertyTag.Id, addr); break; default: Console.WriteLine("RecipientTable Property (unhandled): {0} = {1}", prop.PropertyTag.Id, prop.ReadValue()); break; } } } break; case TnefAttributeTag.MapiProperties: while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.InternetMessageId: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { Console.WriteLine("Message Property (InternetMessageId): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); } else { Console.WriteLine("Unknown property type for Message-Id: {0}", prop.PropertyTag.ValueTnefType); } break; case TnefPropertyId.Subject: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode) { this.Subject = prop.ReadValueAsString(); Console.WriteLine("Message Property (Subject): {0} = {1}", prop.PropertyTag.Id, this.Subject); } else { Console.WriteLine("Unknown property type for Subject: {0}", prop.PropertyTag.ValueTnefType); } break; case TnefPropertyId.RtfCompressed: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { //var rtf = new TextPart("rtf"); //rtf.ContentType.Name = "body.rtf"; //var converter = new RtfCompressedToRtf(); //var content = new MemoryStream(); //using (var filtered = new FilteredStream(content)) //{ // filtered.Add(converter); // using (var compressed = prop.GetRawValueReadStream()) // { // compressed.CopyTo(filtered, 4096); // filtered.Flush(); // } //} //rtf.ContentObject = new ContentObject(content); //content.Position = 0; //builder.Attachments.Add(rtf); Console.WriteLine("Message Property (RtfCompressed): {0} = <compressed rtf data>", prop.PropertyTag.Id); } else { Console.WriteLine("Unknown property type for {0}: {1}", prop.PropertyTag.Id, prop.PropertyTag.ValueTnefType); } break; case TnefPropertyId.BodyHtml: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { this.HtmlBody = prop.ReadValueAsString(); Console.WriteLine("Message Property (BodyHtml): {0} = {1}", prop.PropertyTag.Id, this.HtmlBody); } else { Console.WriteLine("Unknown property type for {0}: {1}", prop.PropertyTag.Id, prop.PropertyTag.ValueTnefType); } break; case TnefPropertyId.Body: if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 || prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode || prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary) { this.TextBody = prop.ReadValueAsString(); Console.WriteLine("Message Property (Body): {0} = {1}", prop.PropertyTag.Id, this.TextBody); } else { Console.WriteLine("Unknown property type for {0}: {1}", prop.PropertyTag.Id, prop.PropertyTag.ValueTnefType); } break; default: object val; try { val = prop.ReadValue(); } catch { val = null; } String key = prop.PropertyTag.Id.ToString(); switch (key) { case "SenderName": if (this.Sender == null) { this.Sender = new TnefAddress(); } this.Sender.Display = val.ToString().Trim(); break; case "SenderEmailAddress": if (this.Sender == null) { this.Sender = new TnefAddress(); } this.Sender.Address = val.ToString().Trim(); break; } Console.WriteLine("Message Property (unhandled): {0} = {1}", prop.PropertyTag.Id, val); break; } } break; case TnefAttributeTag.DateSent: this.DateSent = prop.ReadValueAsDateTime(); Console.WriteLine("Message Attribute (DateSent): {0} = {1}", reader.AttributeTag, this.DateSent); break; case TnefAttributeTag.Body: Console.WriteLine("Message Attribute (Body): {0} = {1}", reader.AttributeTag, prop.ReadValueAsString()); break; case TnefAttributeTag.OemCodepage: int codepage = prop.ReadValueAsInt32(); try { var encoding = Encoding.GetEncoding(codepage); Console.WriteLine("Message Attribute: OemCodepage = {0}", encoding.HeaderName); } catch { Console.WriteLine("Message Attribute: OemCodepage = {0}", codepage); } break; } } if (reader.AttributeLevel == TnefAttributeLevel.Attachment) { Console.WriteLine("attachments found"); TnefPropertyReader prop = reader.TnefPropertyReader; TnefAttachMethod attachMethod = TnefAttachMethod.ByValue; TnefAttachFlags flags; TnefAttachment attachment = null; Console.WriteLine("Extracting attachments..."); do { if (reader.AttributeLevel != TnefAttributeLevel.Attachment) { Console.WriteLine("Expected attachment attribute level: {0}", reader.AttributeLevel); } switch (reader.AttributeTag) { case TnefAttributeTag.AttachRenderData: Console.WriteLine("Attachment Attribute: {0}", reader.AttributeTag); attachMethod = TnefAttachMethod.ByValue; attachment = new TnefAttachment(); break; case TnefAttributeTag.Attachment: Console.WriteLine("Attachment Attribute: {0}", reader.AttributeTag); if (attachment == null) { break; } while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.AttachLongFilename: attachment.FileName = prop.ReadValueAsString(); Console.WriteLine("Attachment Property (AttachLongFilename): {0} = {1}", prop.PropertyTag.Id, attachment.FileName); break; case TnefPropertyId.AttachFilename: if (attachment.FileName == null) { attachment.FileName = prop.ReadValueAsString(); Console.WriteLine("Attachment Property: {0} = {1}", prop.PropertyTag.Id, attachment.FileName); } else { Console.WriteLine("Attachment Property: {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); } break; case TnefPropertyId.AttachContentLocation: Console.WriteLine("Attachment Property (AttachContentLocation): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); break; case TnefPropertyId.AttachContentBase: Console.WriteLine("Attachment Property (AttachContentBase): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); break; case TnefPropertyId.AttachContentId: Console.WriteLine("Attachment Property (AttachContentId): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); break; case TnefPropertyId.AttachDisposition: Console.WriteLine("Attachment Property (AttachDisposition): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); break; case TnefPropertyId.AttachMethod: attachMethod = (TnefAttachMethod)prop.ReadValueAsInt32(); Console.WriteLine("Attachment Property (AttachMethod): {0} = {1}", prop.PropertyTag.Id, attachMethod); break; case TnefPropertyId.AttachMimeTag: attachment.MimeType = prop.ReadValueAsString(); Console.WriteLine("Attachment Property (AttachMimeTag): {0} = {1}", prop.PropertyTag.Id, attachment.MimeType); break; case TnefPropertyId.AttachFlags: flags = (TnefAttachFlags)prop.ReadValueAsInt32(); Console.WriteLine("Attachment Property (AttachFlags): {0} = {1}", prop.PropertyTag.Id, flags); break; case TnefPropertyId.AttachData: Stream stream = prop.GetRawValueReadStream(); byte[] guid = new byte[16]; stream.Read(guid, 0, 16); Console.WriteLine("Attachment Property (AttachData): {0} has GUID {1}", prop.PropertyTag.Id, new Guid(guid)); break; case TnefPropertyId.DisplayName: Console.WriteLine("Attachment Property (DisplayName): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsString()); break; case TnefPropertyId.AttachSize: Console.WriteLine("Attachment Property (AttachSize): {0} = {1}", prop.PropertyTag.Id, prop.ReadValueAsInt64()); break; default: Console.WriteLine("Attachment Property (unhandled): {0} = {1}", prop.PropertyTag.Id, prop.ReadValue()); break; } } break; case TnefAttributeTag.AttachData: if (attachment == null || attachMethod != TnefAttachMethod.ByValue) { break; } attachment.BinaryContent = prop.ReadValueAsBytes(); this.Attachments.Add(attachment); Console.WriteLine("Attachment Attribute (AttachData): {0}", reader.AttributeTag); break; case TnefAttributeTag.AttachCreateDate: Console.WriteLine("Attachment Attribute (AttachCreateDate): {0} = {1}", reader.AttributeTag, prop.ReadValueAsDateTime()); break; case TnefAttributeTag.AttachModifyDate: Console.WriteLine("Attachment Attribute (AttachModifyDate): {0} = {1}", reader.AttributeTag, prop.ReadValueAsDateTime()); break; case TnefAttributeTag.AttachTitle: Console.WriteLine("Attachment Attribute (AttachTitle): {0} = {1}", reader.AttributeTag, prop.ReadValueAsString()); break; default: Console.WriteLine("Attachment Attribute (unhandled): {0} = {1}", reader.AttributeTag, prop.ReadValue()); break; } }while (reader.ReadNextAttribute()); } else { Console.WriteLine("no attachments"); } } }
private void LoadProperty(TnefPropertyReader propertyReader, DataStorage tnefStorage, long tnefStart, long tnefEnd, TnefAttributeLevel level, int embeddingDepth, Charset binaryCharset) { TnefPropertyTag propertyTag = propertyReader.PropertyTag; if (propertyTag.IsMultiValued) { return; } if (TnefPropertyType.Null == propertyTag.ValueTnefType) { return; } if (propertyReader.IsNamedProperty) { TnefNameId propertyNameId = propertyReader.PropertyNameId; TnefNameTag key = new TnefNameTag(propertyNameId, propertyTag.ValueTnefType); if (this.supportedNamedProperties.ContainsKey(key)) { if (propertyReader.IsLargeValue) { return; } this[this.GetIndex(propertyNameId)] = propertyReader.ReadValue(); } return; } if (!this.supportedProperties.ContainsKey(propertyTag)) { return; } TnefPropertyId id = propertyTag.Id; int index = this.GetIndex(id); if (TnefPropertyId.Body == id || TnefPropertyId.RtfCompressed == id || TnefPropertyId.BodyHtml == id) { tnefStart += (long)propertyReader.RawValueStreamOffset; tnefEnd = tnefStart + (long)propertyReader.RawValueLength; this[index] = new StoragePropertyValue(propertyTag, tnefStorage, tnefStart, tnefEnd); return; } if (TnefPropertyId.AttachData == id) { tnefStart += (long)propertyReader.RawValueStreamOffset; tnefEnd = tnefStart + (long)propertyReader.RawValueLength; this[index] = new StoragePropertyValue(propertyTag, tnefStorage, tnefStart, tnefEnd); if (!propertyReader.IsEmbeddedMessage) { return; } if (++embeddingDepth > 100) { throw new MimeException(EmailMessageStrings.NestingTooDeep(embeddingDepth, 100)); } using (TnefReader embeddedMessageReader = propertyReader.GetEmbeddedMessageReader()) { PureTnefMessage pureTnefMessage = new PureTnefMessage(this.attachmentData, tnefStorage, tnefStart, tnefEnd); pureTnefMessage.Load(embeddedMessageReader, embeddingDepth, binaryCharset); EmailMessage embeddedMessage = new EmailMessage(pureTnefMessage); this.attachmentData.EmbeddedMessage = embeddedMessage; return; } } if (propertyReader.IsLargeValue) { return; } if (TnefPropertyId.InternetCPID == id) { if (TnefPropertyType.Long == propertyTag.TnefType) { int num = propertyReader.ReadValueAsInt32(); this[index] = num; return; } } else { this[index] = propertyReader.ReadValue(); } }