/// <summary> /// Initializes a new instance of the <see cref="MimeKit.Tnef.TnefReader"/> class. /// </summary> /// <remarks> /// <para>When reading a TNEF stream using the <see cref="TnefComplianceMode.Strict"/> mode, /// a <see cref="TnefException"/> will be thrown immediately at the first sign of /// invalid or corrupted data.</para> /// <para>When reading a TNEF stream using the <see cref="TnefComplianceMode.Loose"/> mode, /// however, compliance issues are accumulated in the <see cref="ComplianceMode"/> /// property, but exceptions are not raised unless the stream is too corrupted to continue.</para> /// </remarks> /// <param name="inputStream">The input stream.</param> /// <param name="defaultMessageCodepage">The default message codepage.</param> /// <param name="complianceMode">The compliance mode.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="inputStream"/> is <c>null</c>. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="defaultMessageCodepage"/> is not a valid codepage. /// </exception> /// <exception cref="System.NotSupportedException"> /// <paramref name="defaultMessageCodepage"/> is not a supported codepage. /// </exception> /// <exception cref="TnefException"> /// The TNEF stream is corrupted or invalid. /// </exception> public TnefReader(Stream inputStream, int defaultMessageCodepage, TnefComplianceMode complianceMode) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } if (defaultMessageCodepage < 0) { throw new ArgumentOutOfRangeException("defaultMessageCodepage"); } if (defaultMessageCodepage != 0) { // make sure that this codepage is valid... var encoding = Encoding.GetEncoding(defaultMessageCodepage); codepage = encoding.CodePage; } else { codepage = 1252; } TnefPropertyReader = new TnefPropertyReader(this); ComplianceMode = complianceMode; InputStream = inputStream; DecodeHeader(); }
private void ParseAttachmentProperties() { TnefPropertyReader propertyReader = this.reader.PropertyReader; while (propertyReader.ReadNextProperty()) { this.ParseTnefProperty(propertyReader, false); } }
private void ParseMapiProperties(bool forceTransmittable) { TnefPropertyReader propertyReader = this.reader.PropertyReader; while (propertyReader.ReadNextProperty()) { this.CheckTnefComplianceStatus(); this.ParseTnefProperty(propertyReader, forceTransmittable); } }
private void ParseAttachRenderData() { TnefPropertyReader propertyReader = this.reader.PropertyReader; while (propertyReader.ReadNextProperty()) { if (propertyReader.PropertyTag != TnefPropertyTag.AttachMethod) { this.ParseTnefProperty(propertyReader, false); } } }
internal static void WriteUnicodePropertyValue(TnefWriter writer, TnefPropertyReader propertyReader, ref char[] buffer) { if (buffer == null) { buffer = new char[1024]; } int count; while ((count = propertyReader.ReadTextValue(buffer, 0, buffer.Length)) != 0) { writer.WritePropertyTextValue(buffer, 0, count); } }
private void ParseTnefProperty(TnefPropertyReader propertyReader, bool forceTransmittable) { this.CheckTnefComplianceStatus(); TnefNameId?namedProperty = propertyReader.IsNamedProperty ? new TnefNameId?(propertyReader.PropertyNameId) : null; NativeStorePropertyDefinition nativeStorePropertyDefinition = base.CreatePropertyDefinition(propertyReader.PropertyTag, namedProperty); if (nativeStorePropertyDefinition == null) { return; } AbstractInboundConverter.IPromotionRule propertyPromotionRule = base.GetPropertyPromotionRule(nativeStorePropertyDefinition); if (propertyPromotionRule != null) { propertyPromotionRule.PromoteProperty(this, nativeStorePropertyDefinition); } }
/// <summary> /// Advances to the next attribute in the TNEF stream. /// </summary> /// <remarks> /// Advances to the next attribute in the TNEF stream. /// </remarks> /// <returns><c>true</c> if there is another attribute available to be read; otherwise <c>false</c>.</returns> /// <exception cref="TnefException"> /// The TNEF stream is corrupted or invalid. /// </exception> public bool ReadNextAttribute() { CheckDisposed(); if (AttributeRawValueStreamOffset != 0 && !SkipAttributeRawValue()) { return(false); } try { AttributeLevel = (TnefAttributeLevel)ReadByte(); } catch (EndOfStreamException) { return(false); } CheckAttributeLevel(); try { AttributeTag = (TnefAttributeTag)ReadInt32(); AttributeRawValueLength = ReadInt32(); AttributeRawValueStreamOffset = StreamOffset; checksum = 0; } catch (EndOfStreamException) { SetComplianceError(TnefComplianceStatus.StreamTruncated); return(false); } CheckAttributeTag(); if (AttributeRawValueLength < 0) { SetComplianceError(TnefComplianceStatus.InvalidAttributeLength); return(false); } try { TnefPropertyReader.Load(); } catch (EndOfStreamException) { SetComplianceError(TnefComplianceStatus.StreamTruncated); return(false); } return(true); }
private void ParseRecipientTable() { string valueOrDefault = base.CoreItem.PropertyBag.GetValueOrDefault <string>(InternalSchema.ItemClass); if (base.ConversionOptions.IsSenderTrusted || !base.MessageWriter.IsTopLevelWriter || ObjectClass.IsNonSendableWithRecipients(valueOrDefault) || ObjectClass.IsDsn(valueOrDefault)) { TnefPropertyReader propertyReader = this.reader.PropertyReader; while (propertyReader.ReadNextRow()) { this.NewRecipient(); while (propertyReader.ReadNextProperty()) { this.ParseTnefProperty(propertyReader, false); } this.EndRecipient(); this.isRecipientTablePromoted = true; } } }
internal static void WriteUnicodeProperty(TnefWriter writer, TnefPropertyReader propertyReader, TnefPropertyTag tag, ref char[] buffer) { if (tag.IsNamed) { TnefNameId propertyNameId = propertyReader.PropertyNameId; writer.StartProperty(tag, propertyNameId.PropertySetGuid, propertyNameId.Id); } else { writer.StartProperty(tag); } if (tag.IsMultiValued) { while (propertyReader.ReadNextValue()) { writer.StartPropertyValue(); TnefPropertyBag.WriteUnicodePropertyValue(writer, propertyReader, ref buffer); } return; } TnefPropertyBag.WriteUnicodePropertyValue(writer, propertyReader, ref buffer); }
private void StreamBody(StorePropertyDefinition property, TnefPropertyReader reader) { Charset charset = null; if (this.internetCpid != 0) { ConvertUtils.TryGetValidCharset(this.internetCpid, out charset); } string text = (charset != null) ? charset.Name : null; BodyWriteConfiguration bodyWriteConfiguration = null; if (property == InternalSchema.TextBody) { bodyWriteConfiguration = new BodyWriteConfiguration(BodyFormat.TextPlain, ConvertUtils.UnicodeCharset.Name); bodyWriteConfiguration.SetTargetFormat(BodyFormat.TextPlain, text); } else if (property == InternalSchema.HtmlBody) { bodyWriteConfiguration = new BodyWriteConfiguration(BodyFormat.TextHtml, text); bodyWriteConfiguration.SetTargetFormat(BodyFormat.TextHtml, text); } else if (property == InternalSchema.RtfBody) { bodyWriteConfiguration = new BodyWriteConfiguration(BodyFormat.ApplicationRtf); bodyWriteConfiguration.SetTargetFormat(BodyFormat.ApplicationRtf, text); } int trailingNulls; using (Stream stream = this.OpenValueReadStream(out trailingNulls)) { base.CoreItem.CharsetDetector.DetectionOptions = base.ConversionOptions.DetectionOptions; using (Stream stream2 = base.CoreItem.Body.InternalOpenWriteStream(bodyWriteConfiguration, null)) { Util.StreamHandler.CopyStreamData(stream, stream2, null, trailingNulls, 65536); } } }
internal bool Load(TnefReader reader, DataStorage tnefStorage, long tnefStart, long tnefEnd, TnefAttributeLevel level, int embeddingDepth, Charset binaryCharset) { bool result; while ((result = reader.ReadNextAttribute()) && TnefAttributeTag.AttachRenderData != reader.AttributeTag && level == reader.AttributeLevel) { if (TnefAttributeTag.RecipientTable == reader.AttributeTag) { if (level == TnefAttributeLevel.Message && this.parentMessage != null && 0 < embeddingDepth) { this.parentMessage.LoadRecipients(reader.PropertyReader); } } else { TnefPropertyReader propertyReader = reader.PropertyReader; while (propertyReader.ReadNextProperty()) { this.LoadProperty(propertyReader, tnefStorage, tnefStart, tnefEnd, level, embeddingDepth, binaryCharset); } } } return(result); }
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(); } }
private bool WriteModifiedProperty(TnefWriter writer, TnefReader reader, TnefPropertyTag propertyTag, object value, bool forceUnicode, ref bool startAttribute, byte[] scratchBuffer) { TnefPropertyReader propertyReader = reader.PropertyReader; TnefAttributeTag attributeTag = reader.AttributeTag; TnefAttributeLevel attributeLevel = reader.AttributeLevel; StoragePropertyValue storagePropertyValue = value as StoragePropertyValue; if (storagePropertyValue != null) { if (this.attachmentData != null && this.attachmentData.EmbeddedMessage != null && propertyReader.IsEmbeddedMessage) { using (TnefReader embeddedMessageReader = propertyReader.GetEmbeddedMessageReader()) { TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref startAttribute); writer.StartProperty(propertyTag); EmailMessage embeddedMessage = this.attachmentData.EmbeddedMessage; PureTnefMessage pureTnefMessage = embeddedMessage.PureTnefMessage; Charset textCharset = pureTnefMessage.TextCharset; using (TnefWriter embeddedMessageWriter = writer.GetEmbeddedMessageWriter(textCharset.CodePage)) { pureTnefMessage.WriteMessage(embeddedMessageReader, embeddedMessageWriter, scratchBuffer); } return(true); } } using (Stream readStream = storagePropertyValue.GetReadStream()) { int num = readStream.Read(scratchBuffer, 0, scratchBuffer.Length); if (num > 0) { propertyTag = storagePropertyValue.PropertyTag; if (propertyTag.ValueTnefType == TnefPropertyType.Unicode && TnefPropertyBag.IsLegacyAttribute(attributeTag)) { return(false); } TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref startAttribute); writer.StartProperty(propertyTag); do { writer.WritePropertyRawValue(scratchBuffer, 0, num); num = readStream.Read(scratchBuffer, 0, scratchBuffer.Length); }while (num > 0); } return(true); } } if (propertyTag.ValueTnefType == TnefPropertyType.String8 && forceUnicode) { if (TnefPropertyBag.IsLegacyAttribute(attributeTag)) { return(false); } TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref startAttribute); writer.WriteProperty(propertyTag.ToUnicode(), value); } else { TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref startAttribute); writer.WriteProperty(propertyTag, value); } return(true); }
static string GetHtmlBody(TnefPropertyReader prop, int codepage, out Encoding encoding) { var rawValue = prop.ReadValueAsBytes(); int rawLength = rawValue.Length; while (rawLength > 0 && rawValue[rawLength - 1] == 0) { rawLength--; } // Try and extract the charset from the HTML meta Content-Type value. using (var stream = new MemoryStream(rawValue, 0, rawLength)) { // It should be safe to assume ISO-8859-1 for this purpose. We don't want to risk using UTF-8 (or any other charset) and having it throw an exception... using (var reader = new StreamReader(stream, CharsetUtils.Latin1, true)) { var tokenizer = new HtmlTokenizer(reader); HtmlToken token; while (tokenizer.ReadNextToken(out token)) { if (token.Kind != HtmlTokenKind.Tag) { continue; } var tag = (HtmlTagToken)token; if (tag.Id == HtmlTagId.Body || (tag.Id == HtmlTagId.Head && tag.IsEndTag)) { break; } if (tag.Id != HtmlTagId.Meta || tag.IsEndTag) { continue; } string httpEquiv = null; string content = null; for (int i = 0; i < tag.Attributes.Count; i++) { switch (tag.Attributes[i].Id) { case HtmlAttributeId.HttpEquiv: httpEquiv = httpEquiv ?? tag.Attributes[i].Value; break; case HtmlAttributeId.Content: content = content ?? tag.Attributes[i].Value; break; } } if (httpEquiv == null || !httpEquiv.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)) { continue; } if (!ContentType.TryParse(content, out var contentType) || string.IsNullOrEmpty(contentType.Charset)) { break; } try { encoding = Encoding.GetEncoding(contentType.Charset, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); // If this converts cleanly, then we're golden. return(encoding.GetString(rawValue, 0, rawLength)); } catch { // Otherwise, fall back to assuming the TNEF message codepage. break; } } encoding = Encoding.GetEncoding(codepage); return(encoding.GetString(rawValue, 0, rawLength)); } } }
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 { } } }
internal bool Write(TnefReader reader, TnefWriter writer, TnefAttributeLevel level, bool dropRecipientTable, bool forceUnicode, byte[] scratchBuffer) { IDictionary <TnefPropertyTag, object> dictionary = null; char[] array = null; bool result; for (;;) { TnefPropertyReader propertyReader = reader.PropertyReader; if (0 >= propertyReader.PropertyCount) { goto IL_37A; } TnefAttributeTag attributeTag = reader.AttributeTag; TnefAttributeLevel attributeLevel = reader.AttributeLevel; bool flag = true; while (propertyReader.ReadNextProperty()) { TnefPropertyTag propertyTag = propertyReader.PropertyTag; if (TnefPropertyType.Null != propertyTag.ValueTnefType) { if (propertyReader.IsNamedProperty) { TnefNameId propertyNameId = propertyReader.PropertyNameId; TnefNameTag key = new TnefNameTag(propertyNameId, propertyTag.ValueTnefType); int num; if (this.supportedNamedProperties.TryGetValue(key, out num) && this.properties[num].IsDirty) { object obj = this[propertyNameId]; if (obj != null) { TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref flag); writer.StartProperty(propertyTag, propertyNameId.PropertySetGuid, propertyNameId.Id); writer.WritePropertyValue(obj); continue; } continue; } } else { TnefPropertyId id = propertyTag.Id; int num2; if (this.supportedProperties.TryGetValue(propertyTag, out num2) && this.properties[num2].IsDirty && (this.attachmentData == null || this.attachmentData.EmbeddedMessage == null || TnefAttributeLevel.Attachment != level || TnefAttributeTag.AttachData != attributeTag || TnefPropertyId.AttachData != id)) { object obj = this[id]; if (obj == null) { continue; } if (!this.WriteModifiedProperty(writer, reader, propertyTag, obj, forceUnicode, ref flag, scratchBuffer)) { if (dictionary == null) { dictionary = new Dictionary <TnefPropertyTag, object>(TnefPropertyBag.PropertyTagComparer); } if (!dictionary.ContainsKey(propertyTag)) { dictionary.Add(propertyTag, obj); continue; } continue; } else { if (dictionary != null && dictionary.ContainsKey(propertyTag)) { dictionary.Remove(propertyTag); continue; } continue; } } } if (propertyTag.ValueTnefType == TnefPropertyType.String8 && forceUnicode) { if (!TnefPropertyBag.IsLegacyAttribute(attributeTag)) { TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref flag); TnefPropertyBag.WriteUnicodeProperty(writer, propertyReader, propertyTag.ToUnicode(), ref array); } } else if (propertyTag.IsTnefTypeValid) { TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref flag); writer.WriteProperty(propertyReader); } } } if ((TnefAttributeTag.MapiProperties == attributeTag && level == TnefAttributeLevel.Message) || (TnefAttributeTag.Attachment == attributeTag && level == TnefAttributeLevel.Attachment)) { if (this.newProperties != null) { foreach (KeyValuePair <TnefPropertyTag, object> keyValuePair in this.newProperties) { object obj = keyValuePair.Value; if (obj != null) { this.WriteModifiedProperty(writer, reader, keyValuePair.Key, obj, forceUnicode, ref flag, scratchBuffer); } } } if (dictionary != null) { foreach (KeyValuePair <TnefPropertyTag, object> keyValuePair2 in dictionary) { this.WriteModifiedProperty(writer, reader, keyValuePair2.Key, keyValuePair2.Value, forceUnicode, ref flag, scratchBuffer); } } if (this.newNamedProperties != null) { using (IEnumerator <KeyValuePair <TnefNameTag, object> > enumerator3 = this.newNamedProperties.GetEnumerator()) { while (enumerator3.MoveNext()) { KeyValuePair <TnefNameTag, object> keyValuePair3 = enumerator3.Current; object obj = keyValuePair3.Value; if (obj != null) { TnefPropertyTag tag = new TnefPropertyTag((TnefPropertyId)(-32768), keyValuePair3.Key.Type); if (forceUnicode) { tag = tag.ToUnicode(); } TnefPropertyBag.StartAttributeIfNecessary(writer, attributeTag, attributeLevel, ref flag); writer.StartProperty(tag, keyValuePair3.Key.Id.PropertySetGuid, keyValuePair3.Key.Id.Id); writer.WritePropertyValue(obj); } } goto IL_3AC; } goto IL_37A; } } IL_3AC: if (!(result = reader.ReadNextAttribute()) || level != reader.AttributeLevel || TnefAttributeTag.AttachRenderData == reader.AttributeTag) { break; } continue; IL_37A: if (level != TnefAttributeLevel.Message || TnefAttributeTag.RecipientTable != reader.AttributeTag) { writer.WriteAttribute(reader); goto IL_3AC; } if (!dropRecipientTable) { this.parentMessage.WriteRecipients(reader.PropertyReader, writer, ref array); goto IL_3AC; } goto IL_3AC; } return(result); }