Пример #1
0
        public void TestRtfCompressedToRtfByteByByte()
        {
            var          input = new byte[] { (byte)'-', 0x00, 0x00, 0x00, (byte)'+', 0x00, 0x00, 0x00, (byte)'L', (byte)'Z', (byte)'F', (byte)'u', 0xf1, 0xc5, 0xc7, 0xa7, 0x03, 0x00, (byte)'\n', 0x00, (byte)'r', (byte)'c', (byte)'p', (byte)'g', (byte)'1', (byte)'2', (byte)'5', (byte)'B', (byte)'2', (byte)'\n', 0xf3, (byte)' ', (byte)'h', (byte)'e', (byte)'l', (byte)'\t', 0x00, (byte)' ', (byte)'b', (byte)'w', 0x05, 0xb0, (byte)'l', (byte)'d', (byte)'}', (byte)'\n', 0x80, 0x0f, 0xa0 };
            const string expected = "{\\rtf1\\ansi\\ansicpg1252\\pard hello world}\r\n";
            var          filter = new RtfCompressedToRtf();
            int          outputIndex, outputLength;

            byte[] output;

            using (var memory = new MemoryStream()) {
                for (int i = 0; i < input.Length; i++)
                {
                    output = filter.Filter(input, i, 1, out outputIndex, out outputLength);
                    memory.Write(output, outputIndex, outputLength);
                }

                output = filter.Flush(input, 0, 0, out outputIndex, out outputLength);
                memory.Write(output, outputIndex, outputLength);

                output = memory.ToArray();
            }

            Assert.AreEqual(43, output.Length, "outputLength");
            Assert.IsTrue(filter.IsValidCrc32, "IsValidCrc32");
            Assert.AreEqual(RtfCompressionMode.Compressed, filter.CompressionMode, "ComnpressionMode");

            var text = Encoding.ASCII.GetString(output);

            Assert.AreEqual(expected, text);
        }
Пример #2
0
        public void TestRtfCompressedToRtfRawByteByByte()
        {
            var          input = new byte[] { (byte)'.', 0x00, 0x00, 0x00, (byte)'\"', 0x00, 0x00, 0x00, (byte)'M', (byte)'E', (byte)'L', (byte)'A', (byte)' ', 0xdf, 0x12, 0xce, (byte)'{', (byte)'\\', (byte)'r', (byte)'t', (byte)'f', (byte)'1', (byte)'\\', (byte)'a', (byte)'n', (byte)'s', (byte)'i', (byte)'\\', (byte)'a', (byte)'n', (byte)'s', (byte)'i', (byte)'c', (byte)'p', (byte)'g', (byte)'1', (byte)'2', (byte)'5', (byte)'2', (byte)'\\', (byte)'p', (byte)'a', (byte)'r', (byte)'d', (byte)' ', (byte)'t', (byte)'e', (byte)'s', (byte)'t', (byte)'}' };
            const string expected = "{\\rtf1\\ansi\\ansicpg1252\\pard test}";
            var          filter = new RtfCompressedToRtf();
            int          outputIndex, outputLength;

            byte[] output;

            using (var memory = new MemoryStream()) {
                for (int i = 0; i < input.Length; i++)
                {
                    output = filter.Filter(input, i, 1, out outputIndex, out outputLength);
                    memory.Write(output, outputIndex, outputLength);
                }

                output = filter.Flush(input, 0, 0, out outputIndex, out outputLength);
                memory.Write(output, outputIndex, outputLength);

                output = memory.ToArray();
            }

            Assert.AreEqual(34, output.Length, "outputLength");
            Assert.IsTrue(filter.IsValidCrc32, "IsValidCrc32");
            Assert.AreEqual(RtfCompressionMode.Uncompressed, filter.CompressionMode, "ComnpressionMode");

            var text = Encoding.ASCII.GetString(output);

            Assert.AreEqual(expected, text);
        }
Пример #3
0
        private void CreateDetectionStream(BodyStreamFormat format, Charset contentCharset, string extraData, bool trustHtmlMetaTag)
        {
            this.detectorCache = new PooledMemoryStream(8192);
            if (extraData != null)
            {
                byte[] bytes = ConvertUtils.UnicodeEncoding.GetBytes(extraData);
                this.detectorCache.Write(bytes, 0, bytes.Length);
            }
            switch (format)
            {
            case BodyStreamFormat.Text:
            {
                if (contentCharset.CodePage == 1200)
                {
                    this.detectorConversionStream = new StreamWrapper(this.detectorCache, false);
                    return;
                }
                TextToText textToText = new TextToText(TextToTextConversionMode.ConvertCodePageOnly);
                textToText.InputEncoding          = contentCharset.GetEncoding();
                textToText.OutputEncoding         = ConvertUtils.UnicodeEncoding;
                textToText.OutputStreamBufferSize = 1024;
                textToText.InputStreamBufferSize  = 1024;
                this.detectorConversionStream     = new ConverterStream(new StreamWrapper(this.detectorCache, false), textToText, ConverterStreamAccess.Write);
                return;
            }

            case BodyStreamFormat.Html:
            {
                HtmlToText htmlToText = new HtmlToText(TextExtractionMode.ExtractText);
                htmlToText.InputEncoding             = contentCharset.GetEncoding();
                htmlToText.OutputEncoding            = ConvertUtils.UnicodeEncoding;
                htmlToText.DetectEncodingFromMetaTag = trustHtmlMetaTag;
                htmlToText.OutputStreamBufferSize    = 1024;
                htmlToText.InputStreamBufferSize     = 1024;
                this.detectorConversionStream        = new ConverterStream(new StreamWrapper(this.detectorCache, false), htmlToText, ConverterStreamAccess.Write);
                return;
            }

            case BodyStreamFormat.RtfCompressed:
            case BodyStreamFormat.RtfUncompressed:
            {
                RtfToText rtfToText = new RtfToText(TextExtractionMode.ExtractText);
                rtfToText.OutputEncoding         = ConvertUtils.UnicodeEncoding;
                rtfToText.OutputStreamBufferSize = 1024;
                rtfToText.InputStreamBufferSize  = 1024;
                this.detectorConversionStream    = new ConverterStream(new StreamWrapper(this.detectorCache, false), rtfToText, ConverterStreamAccess.Write);
                if (format == BodyStreamFormat.RtfCompressed)
                {
                    RtfCompressedToRtf rtfCompressedToRtf = new RtfCompressedToRtf();
                    rtfCompressedToRtf.OutputStreamBufferSize = 1024;
                    rtfCompressedToRtf.InputStreamBufferSize  = 1024;
                    this.detectorConversionStream             = new ConverterStream(this.detectorConversionStream, rtfCompressedToRtf, ConverterStreamAccess.Write);
                }
                return;
            }

            default:
                return;
            }
        }
Пример #4
0
        public void TestRtfCompressedToRtfInvalidCrc()
        {
            var input = new byte[] { 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, (byte)'L', (byte)'Z', (byte)'F', (byte)'u', 0xff, 0xff, 0xff, 0xff };
            var filter = new RtfCompressedToRtf();
            int outputIndex, outputLength;

            byte[] output;

            output = filter.Flush(input, 0, input.Length, out outputIndex, out outputLength);

            Assert.AreEqual(0, outputIndex, "outputIndex");
            Assert.AreEqual(0, outputLength, "outputLength");
            Assert.IsFalse(filter.IsValidCrc32, "IsValidCrc32");
            Assert.AreEqual(RtfCompressionMode.Compressed, filter.CompressionMode, "ComnpressionMode");
        }
Пример #5
0
        public void TestRtfCompressedToRtfUnknownCompressionType()
        {
            var input = new byte[] { 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, (byte)'A', (byte)'B', (byte)'C', (byte)'D', 0xff, 0xff, 0xff, 0xff };
            var filter = new RtfCompressedToRtf();
            int outputIndex, outputLength;

            byte[] output;

            output = filter.Flush(input, 0, input.Length, out outputIndex, out outputLength);

            Assert.AreEqual(16, outputIndex, "outputIndex");
            Assert.AreEqual(0, outputLength, "outputLength");
            Assert.IsFalse(filter.IsValidCrc32, "IsValidCrc32");
            Assert.AreEqual((RtfCompressionMode)1145258561, filter.CompressionMode, "ComnpressionMode");
        }
Пример #6
0
        public void TestRtfCompressedToRtfRaw()
        {
            var          input = new byte[] { (byte)'.', 0x00, 0x00, 0x00, (byte)'\"', 0x00, 0x00, 0x00, (byte)'M', (byte)'E', (byte)'L', (byte)'A', (byte)' ', 0xdf, 0x12, 0xce, (byte)'{', (byte)'\\', (byte)'r', (byte)'t', (byte)'f', (byte)'1', (byte)'\\', (byte)'a', (byte)'n', (byte)'s', (byte)'i', (byte)'\\', (byte)'a', (byte)'n', (byte)'s', (byte)'i', (byte)'c', (byte)'p', (byte)'g', (byte)'1', (byte)'2', (byte)'5', (byte)'2', (byte)'\\', (byte)'p', (byte)'a', (byte)'r', (byte)'d', (byte)' ', (byte)'t', (byte)'e', (byte)'s', (byte)'t', (byte)'}' };
            const string expected = "{\\rtf1\\ansi\\ansicpg1252\\pard test}";
            var          filter = new RtfCompressedToRtf();
            int          outputIndex, outputLength;

            byte[] output;

            output = filter.Flush(input, 0, input.Length, out outputIndex, out outputLength);

            Assert.AreEqual(16, outputIndex, "outputIndex");
            Assert.AreEqual(34, outputLength, "outputLength");
            Assert.IsTrue(filter.IsValidCrc32, "IsValidCrc32");
            Assert.AreEqual(RtfCompressionMode.Uncompressed, filter.CompressionMode, "ComnpressionMode");

            var text = Encoding.ASCII.GetString(output, outputIndex, outputLength);

            Assert.AreEqual(expected, text);
        }
        public void TestCrossingWritePositionExample()
        {
            // http://msdn.microsoft.com/en-us/library/ee158471(v=exchg.80).aspx
            var compressedRtfData = new byte[] {
                // header
                0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x4c, 0x5a, 0x46, 0x75, 0xe2, 0xd4, 0x4b, 0x51,

                // data
                0x41, 0x00, 0x04, 0x20, 0x57, 0x58, 0x59, 0x5a, 0x0d, 0x6e, 0x7d, 0x01, 0x0e, 0xb0
            };
            var expected = "{\\rtf1 WXYZWXYZWXYZWXYZWXYZ}";

            var converter = new RtfCompressedToRtf();
            int outputLength, outputIndex;

            var decompressed = converter.Flush(compressedRtfData, 0, compressedRtfData.Length, out outputIndex, out outputLength);
            var text         = Encoding.UTF8.GetString(decompressed, outputIndex, outputLength);

            Assert.AreEqual(expected, text, "Decompressed RTF data does not match.");
            Assert.IsTrue(converter.IsValidCrc32, "Invalid CRC32 checksum.");
        }
        public void TestSimpleCompressedRtfExample()
        {
            // http://msdn.microsoft.com/en-us/library/ee217938(v=exchg.80).aspx
            var compressedRtfData = new byte[] {
                // header
                0x2d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x4c, 0x5a, 0x46, 0x75, 0xf1, 0xc5, 0xc7, 0xa7,

                // data
                0x03, 0x00, 0x0a, 0x00, 0x72, 0x63, 0x70, 0x67, 0x31, 0x32, 0x35, 0x42, 0x32, 0x0a, 0xf3, 0x20,
                0x68, 0x65, 0x6c, 0x09, 0x00, 0x20, 0x62, 0x77, 0x05, 0xb0, 0x6c, 0x64, 0x7d, 0x0a, 0x80, 0x0f,
                0xa0
            };
            var expected = "{\\rtf1\\ansi\\ansicpg1252\\pard hello world}\r\n";

            var converter = new RtfCompressedToRtf();
            int outputLength, outputIndex;

            var decompressed = converter.Flush(compressedRtfData, 0, compressedRtfData.Length, out outputIndex, out outputLength);
            var text         = Encoding.UTF8.GetString(decompressed, outputIndex, outputLength);

            Assert.AreEqual(expected, text, "Decompressed RTF data does not match.");
            Assert.IsTrue(converter.IsValidCrc32, "Invalid CRC32 checksum.");
        }
Пример #9
0
        static void ExtractMapiProperties(TnefReader reader, MimeMessage message, BodyBuilder builder)
        {
            var prop  = reader.TnefPropertyReader;
            var chars = new char[1024];
            var buf   = new byte[1024];

            while (prop.ReadNextProperty())
            {
                var    type = prop.ValueType;
                object value;

                switch (prop.PropertyTag.Id)
                {
                case TnefPropertyId.InternetMessageId:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        message.MessageId = prop.ReadValueAsString();
                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, message.MessageId);
                    }
                    else
                    {
                        Assert.Fail("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)
                    {
                        message.Subject = prop.ReadValueAsString();
                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, message.Subject);
                    }
                    else
                    {
                        Assert.Fail("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.Content      = new MimeContent(content);
                        content.Position = 0;

                        builder.Attachments.Add(rtf);

                        //Console.WriteLine ("Message Property: {0} = <compressed rtf data>", prop.PropertyTag.Id);
                    }
                    else
                    {
                        Assert.Fail("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)
                    {
                        var html = new TextPart("html");
                        html.ContentType.Name = "body.html";
                        html.Text             = prop.ReadValueAsString();

                        builder.Attachments.Add(html);

                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, html.Text);
                    }
                    else
                    {
                        Assert.Fail("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)
                    {
                        var plain = new TextPart("plain");
                        plain.ContentType.Name = "body.txt";
                        plain.Text             = prop.ReadValueAsString();

                        builder.Attachments.Add(plain);

                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, plain.Text);
                    }
                    else
                    {
                        Assert.Fail("Unknown property type for {0}: {1}", prop.PropertyTag.Id, prop.PropertyTag.ValueTnefType);
                    }
                    break;

                case TnefPropertyId.AlternateRecipientAllowed:
                    Assert.AreEqual(typeof(bool), type);
                    value = prop.ReadValueAsBoolean();
                    break;

                case TnefPropertyId.MessageClass:
                    Assert.AreEqual(typeof(string), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.Importance:
                    Assert.AreEqual(typeof(int), type);
                    value = prop.ReadValueAsInt16();
                    break;

                case TnefPropertyId.Priority:
                    Assert.AreEqual(typeof(int), type);
                    value = prop.ReadValueAsInt16();
                    break;

                case TnefPropertyId.Sensitivity:
                    Assert.AreEqual(typeof(int), type);
                    value = prop.ReadValueAsInt16();
                    break;

                case TnefPropertyId.ClientSubmitTime:
                    Assert.AreEqual(typeof(DateTime), type);
                    value = prop.ReadValueAsDateTime();
                    break;

                case TnefPropertyId.SubjectPrefix:
                    Assert.AreEqual(typeof(string), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.MessageSubmissionId:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.ConversationTopic:
                    Assert.AreEqual(typeof(string), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.ConversationIndex:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsBytes();
                    break;

                case TnefPropertyId.SenderName:
                    Assert.AreEqual(typeof(string), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.NormalizedSubject:
                    Assert.AreEqual(typeof(string), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.CreationTime:
                    Assert.AreEqual(typeof(DateTime), type);
                    value = prop.ReadValueAsDateTime();
                    break;

                case TnefPropertyId.LastModificationTime:
                    Assert.AreEqual(typeof(DateTime), type);
                    value = prop.ReadValueAsDateTime();
                    break;

                case TnefPropertyId.InternetCPID:
                    Assert.AreEqual(typeof(int), type);
                    value = prop.ReadValueAsInt32();
                    break;

                case TnefPropertyId.MessageCodepage:
                    Assert.AreEqual(typeof(int), type);
                    value = prop.ReadValueAsInt32();
                    break;

                case TnefPropertyId.INetMailOverrideFormat:
                    Assert.AreEqual(typeof(int), type);
                    value = prop.ReadValueAsInt32();
                    break;

                case TnefPropertyId.ReadReceiptRequested:
                    Assert.AreEqual(typeof(bool), type);
                    value = prop.ReadValueAsBoolean();
                    break;

                case TnefPropertyId.OriginatorDeliveryReportRequested:
                    Assert.AreEqual(typeof(bool), type);
                    value = prop.ReadValueAsBoolean();
                    break;

                case TnefPropertyId.TnefCorrelationKey:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.SenderSearchKey:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.DeleteAfterSubmit:
                    Assert.AreEqual(typeof(bool), type);
                    value = prop.ReadValueAsBoolean();
                    break;

                case TnefPropertyId.MessageDeliveryTime:
                    Assert.AreEqual(typeof(DateTime), type);
                    value = prop.ReadValueAsDateTime();
                    break;

                case TnefPropertyId.SentmailEntryId:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsString();
                    break;

                case TnefPropertyId.RtfInSync:
                    Assert.AreEqual(typeof(bool), type);
                    value = prop.ReadValueAsBoolean();
                    break;

                case TnefPropertyId.MappingSignature:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsBytes();
                    break;

                case TnefPropertyId.StoreRecordKey:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsBytes();
                    break;

                case TnefPropertyId.StoreEntryId:
                    Assert.AreEqual(typeof(byte[]), type);
                    value = prop.ReadValueAsBytes();
                    break;

                default:
                    Assert.Throws <ArgumentNullException> (() => prop.ReadTextValue(null, 0, chars.Length));
                    Assert.Throws <ArgumentOutOfRangeException> (() => prop.ReadTextValue(chars, -1, chars.Length));
                    Assert.Throws <ArgumentOutOfRangeException> (() => prop.ReadTextValue(chars, 0, -1));

                    Assert.Throws <ArgumentNullException> (() => prop.ReadRawValue(null, 0, buf.Length));
                    Assert.Throws <ArgumentOutOfRangeException> (() => prop.ReadRawValue(buf, -1, buf.Length));
                    Assert.Throws <ArgumentOutOfRangeException> (() => prop.ReadRawValue(buf, 0, -1));

                    if (type == typeof(int) || type == typeof(long) || type == typeof(bool) || type == typeof(double) || type == typeof(float))
                    {
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsString());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsGuid());
                    }
                    else if (type == typeof(string))
                    {
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsBoolean());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsDouble());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsFloat());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsInt16());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsInt32());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsInt64());
                        Assert.Throws <InvalidOperationException> (() => prop.ReadValueAsGuid());
                    }

                    try {
                        value = prop.ReadValue();
                    } catch (Exception ex) {
                        Console.WriteLine("Error in prop.ReadValue(): {0}", ex);
                        value = null;
                    }

                    //Console.WriteLine ("Message Property (unhandled): {0} = {1}", prop.PropertyTag.Id, value);
                    Assert.AreEqual(type, value.GetType(), "Unexpected value type for {0}: {1}", prop.PropertyTag, value.GetType().Name);
                    break;
                }
            }
        }
Пример #10
0
        static void ExtractMapiProperties(TnefReader reader, MimeMessage message, BodyBuilder builder)
        {
            var prop = reader.TnefPropertyReader;

            while (prop.ReadNextProperty())
            {
                switch (prop.PropertyTag.Id)
                {
                case TnefPropertyId.InternetMessageId:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        message.MessageId = prop.ReadValueAsString();
                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, message.MessageId);
                    }
                    else
                    {
                        Assert.Fail("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)
                    {
                        message.Subject = prop.ReadValueAsString();
                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, message.Subject);
                    }
                    else
                    {
                        Assert.Fail("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: {0} = <compressed rtf data>", prop.PropertyTag.Id);
                    }
                    else
                    {
                        Assert.Fail("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)
                    {
                        var html = new TextPart("html");
                        html.ContentType.Name = "body.html";
                        html.Text             = prop.ReadValueAsString();

                        builder.Attachments.Add(html);

                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, html.Text);
                    }
                    else
                    {
                        Assert.Fail("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)
                    {
                        var plain = new TextPart("plain");
                        plain.ContentType.Name = "body.txt";
                        plain.Text             = prop.ReadValueAsString();

                        builder.Attachments.Add(plain);

                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, plain.Text);
                    }
                    else
                    {
                        Assert.Fail("Unknown property type for {0}: {1}", prop.PropertyTag.Id, prop.PropertyTag.ValueTnefType);
                    }
                    break;

                default:
                    object value;

                    try {
                        value = prop.ReadValue();
                    } catch (Exception ex) {
                        Console.WriteLine("Error in prop.ReadValue(): {0}", ex);
                        value = null;
                    }

                    //Console.WriteLine ("Message Property (unhandled): {0} = {1}", prop.PropertyTag.Id, value);
                    break;
                }
            }
        }