Beispiel #1
1
        static void ExtractAttachments(TnefReader reader, BodyBuilder builder)
        {
            var             attachMethod = TnefAttachMethod.ByValue;
            var             filter = new BestEncodingFilter();
            var             prop = reader.TnefPropertyReader;
            MimePart        attachment = null;
            int             outIndex, outLength;
            TnefAttachFlags flags;

            string[] mimeType;
            byte[]   attachData;
            string   text;

            do
            {
                if (reader.AttributeLevel != TnefAttributeLevel.Attachment)
                {
                    break;
                }

                switch (reader.AttributeTag)
                {
                case TnefAttributeTag.AttachRenderData:
                    attachMethod = TnefAttachMethod.ByValue;
                    attachment   = new MimePart();
                    break;

                case TnefAttributeTag.Attachment:
                    if (attachment == null)
                    {
                        break;
                    }

                    attachData = null;

                    while (prop.ReadNextProperty())
                    {
                        switch (prop.PropertyTag.Id)
                        {
                        case TnefPropertyId.AttachLongFilename:
                            attachment.FileName = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachFilename:
                            if (attachment.FileName == null)
                            {
                                attachment.FileName = prop.ReadValueAsString();
                            }
                            break;

                        case TnefPropertyId.AttachContentLocation:
                            attachment.ContentLocation = prop.ReadValueAsUri();
                            break;

                        case TnefPropertyId.AttachContentBase:
                            attachment.ContentBase = prop.ReadValueAsUri();
                            break;

                        case TnefPropertyId.AttachContentId:
                            text = prop.ReadValueAsString();

                            var buffer = CharsetUtils.UTF8.GetBytes(text);
                            int index  = 0;

                            if (ParseUtils.TryParseMsgId(buffer, ref index, buffer.Length, false, false, out string msgid))
                            {
                                attachment.ContentId = msgid;
                            }
                            break;

                        case TnefPropertyId.AttachDisposition:
                            text = prop.ReadValueAsString();
                            if (ContentDisposition.TryParse(text, out ContentDisposition disposition))
                            {
                                attachment.ContentDisposition = disposition;
                            }
                            break;

                        case TnefPropertyId.AttachData:
                            attachData = prop.ReadValueAsBytes();
                            break;

                        case TnefPropertyId.AttachMethod:
                            attachMethod = (TnefAttachMethod)prop.ReadValueAsInt32();
                            break;

                        case TnefPropertyId.AttachMimeTag:
                            mimeType = prop.ReadValueAsString().Split('/');
                            if (mimeType.Length == 2)
                            {
                                attachment.ContentType.MediaType    = mimeType[0].Trim();
                                attachment.ContentType.MediaSubtype = mimeType[1].Trim();
                            }
                            break;

                        case TnefPropertyId.AttachFlags:
                            flags = (TnefAttachFlags)prop.ReadValueAsInt32();
                            if ((flags & TnefAttachFlags.RenderedInBody) != 0)
                            {
                                if (attachment.ContentDisposition == null)
                                {
                                    attachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline);
                                }
                                else
                                {
                                    attachment.ContentDisposition.Disposition = ContentDisposition.Inline;
                                }
                            }
                            break;

                        case TnefPropertyId.AttachSize:
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition();
                            }

                            attachment.ContentDisposition.Size = prop.ReadValueAsInt64();
                            break;

                        case TnefPropertyId.DisplayName:
                            attachment.ContentType.Name = prop.ReadValueAsString();
                            break;
                        }
                    }

                    if (attachData != null)
                    {
                        int count = attachData.Length;
                        int index = 0;

                        if (attachMethod == TnefAttachMethod.EmbeddedMessage)
                        {
                            attachment.ContentTransferEncoding = ContentEncoding.Base64;
                            attachment = PromoteToTnefPart(attachment);
                            count     -= 16;
                            index      = 16;
                        }
                        else
                        {
                            filter.Flush(attachData, index, count, out outIndex, out outLength);
                            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                            filter.Reset();
                        }

                        attachment.Content = new MimeContent(new MemoryStream(attachData, index, count, false));
                        builder.Attachments.Add(attachment);
                    }
                    break;

                case TnefAttributeTag.AttachCreateDate:
                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.CreationDate = prop.ReadValueAsDateTime();
                    }
                    break;

                case TnefAttributeTag.AttachModifyDate:
                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.ModificationDate = prop.ReadValueAsDateTime();
                    }
                    break;

                case TnefAttributeTag.AttachTitle:
                    if (attachment != null && string.IsNullOrEmpty(attachment.FileName))
                    {
                        attachment.FileName = prop.ReadValueAsString();
                    }
                    break;

                case TnefAttributeTag.AttachMetaFile:
                    if (attachment == null)
                    {
                        break;
                    }

                    // TODO: what to do with the meta data?
                    break;

                case TnefAttributeTag.AttachData:
                    if (attachment == null || attachMethod != TnefAttachMethod.ByValue)
                    {
                        break;
                    }

                    attachData = prop.ReadValueAsBytes();
                    filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength);
                    attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    attachment.Content = new MimeContent(new MemoryStream(attachData, false));
                    filter.Reset();

                    builder.Attachments.Add(attachment);
                    break;
                }
            } while (reader.ReadNextAttribute());
        }
Beispiel #2
1
        static void ExtractAttachments(TnefReader reader, BodyBuilder builder)
        {
            var      filter = new BestEncodingFilter();
            var      prop = reader.TnefPropertyReader;
            MimePart attachment = null;
            int      outIndex, outLength;

            byte[] attachData;
            string text;

            do
            {
                if (reader.AttributeLevel != TnefAttributeLevel.Attachment)
                {
                    break;
                }

                switch (reader.AttributeTag)
                {
                case TnefAttributeTag.AttachRenderData:
                    if (attachment != null)
                    {
                        builder.Attachments.Add(attachment);
                    }

                    attachment = new MimePart();
                    break;

                case TnefAttributeTag.Attachment:
                    if (attachment == null)
                    {
                        break;
                    }

                    while (prop.ReadNextProperty())
                    {
                        switch (prop.PropertyTag.Id)
                        {
                        case TnefPropertyId.AttachLongFilename:
                            attachment.FileName = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachFilename:
                            if (attachment.FileName == null)
                            {
                                attachment.FileName = prop.ReadValueAsString();
                            }
                            break;

                        case TnefPropertyId.AttachContentLocation:
                            text = prop.ReadValueAsString();
                            if (Uri.IsWellFormedUriString(text, UriKind.Absolute))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Absolute);
                            }
                            else if (Uri.IsWellFormedUriString(text, UriKind.Relative))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Relative);
                            }
                            break;

                        case TnefPropertyId.AttachContentBase:
                            text = prop.ReadValueAsString();
                            attachment.ContentBase = new Uri(text, UriKind.Absolute);
                            break;

                        case TnefPropertyId.AttachContentId:
                            attachment.ContentId = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachDisposition:
                            text = prop.ReadValueAsString();
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition(text);
                            }
                            else
                            {
                                attachment.ContentDisposition.Disposition = text;
                            }
                            break;

                        case TnefPropertyId.AttachData:
                            // TODO: implement this...
                            break;
                        }
                    }
                    break;

                case TnefAttributeTag.AttachData:
                    if (attachment == null)
                    {
                        break;
                    }

                    attachData = prop.ReadValueAsBytes();
                    filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength);
                    attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    attachment.ContentObject           = new ContentObject(new MemoryStream(attachData, false), ContentEncoding.Default);
                    filter.Reset();
                    break;
                }

                if (attachment != null)
                {
                    builder.Attachments.Add(attachment);
                }
            } while (reader.ReadNextAttribute());
        }
Beispiel #3
0
        static void LoadContent(MimePart attachment, Stream stream)
        {
            var content = new MemoryBlockStream();

            if (attachment.ContentType.IsMimeType("text", "*"))
            {
                var filter = new BestEncodingFilter();
                var buf = new byte[4096];
                int index, length;
                int nread;

                while ((nread = stream.Read(buf, 0, buf.Length)) > 0)
                {
                    filter.Filter(buf, 0, nread, out index, out length);
                    content.Write(buf, 0, nread);
                }

                filter.Flush(buf, 0, 0, out index, out length);

                attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            }
            else
            {
                attachment.ContentTransferEncoding = ContentEncoding.Base64;
                stream.CopyTo(content, 4096);
            }

            content.Position = 0;

            attachment.Content = new MimeContent(content);
        }
        void LoadContent(MimePart attachment, string fileName)
        {
            var content = new MemoryBlockStream();
            var filter  = new BestEncodingFilter();

            using (var stream = File.OpenRead(fileName)) {
                var buf = new byte[4096];
                int index, length;
                int nread;

                while ((nread = stream.Read(buf, 0, buf.Length)) > 0)
                {
                    filter.Filter(buf, 0, nread, out index, out length);
                    content.Write(buf, 0, nread);
                }

                filter.Flush(buf, 0, 0, out index, out length);
            }

            content.Position = 0;

            if (linked)
            {
                attachment.ContentLocation = new Uri(Path.GetFileName(fileName), UriKind.Relative);
            }

            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            attachment.ContentObject           = new ContentObject(content, ContentEncoding.Default);
        }
Beispiel #5
0
        private bool StoreEntities(OutgoingEmail email, List <string> attachmentList)
        {
            foreach (string iter in attachmentList)
            {
                FileStream stream = File.OpenRead(iter);
                if (!stream.CanRead)
                {
                    return(false);
                }

                string      mimeType = MimeTypes.GetMimeType(iter);
                ContentType fileType = ContentType.Parse(mimeType);
                MimePart    attachment;
                if (fileType.IsMimeType("text", "*"))
                {
                    attachment = new TextPart(fileType.MediaSubtype);
                    foreach (var param in fileType.Parameters)
                    {
                        attachment.ContentType.Parameters.Add(param);
                    }
                }
                else
                {
                    attachment = new MimePart(fileType);
                }
                attachment.FileName     = Path.GetFileName(iter);
                attachment.IsAttachment = true;

                MemoryBlockStream  memoryBlockStream = new MemoryBlockStream();
                BestEncodingFilter encodingFilter = new BestEncodingFilter();
                byte[]             fileBuffer = new byte[4096];
                int index, length, bytesRead;

                while ((bytesRead = stream.Read(fileBuffer, 0, fileBuffer.Length)) > 0)
                {
                    encodingFilter.Filter(fileBuffer, 0, bytesRead, out index, out length);
                    memoryBlockStream.Write(fileBuffer, 0, bytesRead);
                }

                encodingFilter.Flush(fileBuffer, 0, 0, out index, out length);
                memoryBlockStream.Position = 0;

                attachment.ContentTransferEncoding = encodingFilter.GetBestEncoding(EncodingConstraint.SevenBit);
                attachment.ContentObject           = new ContentObject(memoryBlockStream);

                if (attachment != null)
                {
                    email.AttachmentList.Add(attachment);
                }
            }
            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// Calculates the most efficient content encoding given the specified constraint.
        /// </summary>
        /// <remarks>
        /// If no <see cref="ContentObject"/> is set, <see cref="ContentEncoding.SevenBit"/> will be returned.
        /// </remarks>
        /// <returns>The most efficient content encoding.</returns>
        /// <param name="constraint">The encoding constraint.</param>
        /// <param name="maxLineLength">The maximum allowable length for a line (not counting the CRLF). Must be between <c>72</c> and <c>998</c> (inclusive).</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <para><paramref name="maxLineLength"/> is not between <c>72</c> and <c>998</c> (inclusive).</para>
        /// <para>-or-</para>
        /// <para><paramref name="constraint"/> is not a valid value.</para>
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        public ContentEncoding GetBestEncoding(EncodingConstraint constraint, int maxLineLength, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (ContentObject == null)
            {
                return(ContentEncoding.SevenBit);
            }

            using (var measure = new MeasuringStream()) {
                using (var filtered = new FilteredStream(measure)) {
                    var filter = new BestEncodingFilter();

                    filtered.Add(filter);
                    ContentObject.DecodeTo(filtered, cancellationToken);
                    filtered.Flush();

                    return(filter.GetBestEncoding(constraint, maxLineLength));
                }
            }
        }
        void LoadContent(MimePart attachment, string fileName, byte[] data)
        {
            var content = new MemoryBlockStream();
            var filter = new BestEncodingFilter();
            int index, length;

            filter.Flush(data, 0, data.Length, out index, out length);
            content.Write(data, 0, data.Length);

            content.Position = 0;

            if (linked)
            {
                attachment.ContentLocation = new Uri(Path.GetFileName(fileName), UriKind.Relative);
            }

            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            attachment.ContentObject           = new ContentObject(content, ContentEncoding.Default);
        }
        static void LoadContent(MimePart attachment, Stream stream)
        {
            var content = new MemoryBlockStream();
            var filter = new BestEncodingFilter();
            var buf = new byte[4096];
            int index, length;
            int nread;

            while ((nread = stream.Read(buf, 0, buf.Length)) > 0)
            {
                filter.Filter(buf, 0, nread, out index, out length);
                content.Write(buf, 0, nread);
            }

            filter.Flush(buf, 0, 0, out index, out length);
            content.Position = 0;

            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            attachment.ContentObject           = new ContentObject(content);
        }
Beispiel #9
0
        static async Task LoadContentAsync(MimePart attachment, Stream stream, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var content = new MemoryBlockStream();

            if (attachment.ContentType.IsMimeType("text", "*"))
            {
                var buf = ArrayPool <byte> .Shared.Rent(BufferLength);

                var filter = new BestEncodingFilter();
                int index, length;
                int nread;

                try {
                    while ((nread = await stream.ReadAsync(buf, 0, BufferLength, cancellationToken).ConfigureAwait(false)) > 0)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        filter.Filter(buf, 0, nread, out index, out length);
                        content.Write(buf, 0, nread);
                    }

                    filter.Flush(buf, 0, 0, out index, out length);
                } finally {
                    ArrayPool <byte> .Shared.Return(buf);
                }

                attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            }
            else
            {
                attachment.ContentTransferEncoding = ContentEncoding.Base64;
                await stream.CopyToAsync(content, 4096, cancellationToken).ConfigureAwait(false);
            }

            content.Position = 0;

            attachment.Content = new MimeContent(content);
        }
Beispiel #10
0
        /// <summary>
        /// Calculates the most efficient content encoding given the specified constraint.
        /// </summary>
        /// <remarks>
        /// If no <see cref="Content"/> is set, <see cref="ContentEncoding.SevenBit"/> will be returned.
        /// </remarks>
        /// <returns>The most efficient content encoding.</returns>
        /// <param name="constraint">The encoding constraint.</param>
        /// <param name="maxLineLength">The maximum allowable length for a line (not counting the CRLF). Must be between <c>72</c> and <c>998</c> (inclusive).</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <para><paramref name="maxLineLength"/> is not between <c>72</c> and <c>998</c> (inclusive).</para>
        /// <para>-or-</para>
        /// <para><paramref name="constraint"/> is not a valid value.</para>
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        public ContentEncoding GetBestEncoding(EncodingConstraint constraint, int maxLineLength, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (ContentType.IsMimeType("text", "*") || ContentType.IsMimeType("message", "*"))
            {
                if (Content == null)
                {
                    return(ContentEncoding.SevenBit);
                }

                using (var measure = new MeasuringStream()) {
                    using (var filtered = new FilteredStream(measure)) {
                        var filter = new BestEncodingFilter();

                        filtered.Add(filter);
                        Content.DecodeTo(filtered, cancellationToken);
                        filtered.Flush();

                        return(filter.GetBestEncoding(constraint, maxLineLength));
                    }
                }
            }

            return(constraint == EncodingConstraint.None ? ContentEncoding.Binary : ContentEncoding.Base64);
        }
Beispiel #11
0
        static void ExtractAttachments(TnefReader reader, BodyBuilder builder)
        {
            var             attachMethod = TnefAttachMethod.ByValue;
            var             filter = new BestEncodingFilter();
            var             prop = reader.TnefPropertyReader;
            MimePart        attachment = null;
            int             outIndex, outLength;
            TnefAttachFlags flags;

            string[] mimeType;
            byte[]   attachData;
            DateTime time;
            string   text;

            //Console.WriteLine ("Extracting attachments...");

            do
            {
                if (reader.AttributeLevel != TnefAttributeLevel.Attachment)
                {
                    Assert.Fail("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 MimePart();
                    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: {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:
                            text = prop.ReadValueAsString();
                            if (Uri.IsWellFormedUriString(text, UriKind.Absolute))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Absolute);
                            }
                            else if (Uri.IsWellFormedUriString(text, UriKind.Relative))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Relative);
                            }
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachContentBase:
                            text = prop.ReadValueAsString();
                            attachment.ContentBase = new Uri(text, UriKind.Absolute);
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachContentId:
                            attachment.ContentId = prop.ReadValueAsString();
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, attachment.ContentId);
                            break;

                        case TnefPropertyId.AttachDisposition:
                            text = prop.ReadValueAsString();
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition(text);
                            }
                            else
                            {
                                attachment.ContentDisposition.Disposition = text;
                            }
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachMethod:
                            attachMethod = (TnefAttachMethod)prop.ReadValueAsInt32();
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, attachMethod);
                            break;

                        case TnefPropertyId.AttachMimeTag:
                            text     = prop.ReadValueAsString();
                            mimeType = text.Split('/');
                            if (mimeType.Length == 2)
                            {
                                attachment.ContentType.MediaType    = mimeType[0].Trim();
                                attachment.ContentType.MediaSubtype = mimeType[1].Trim();
                            }
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachFlags:
                            flags = (TnefAttachFlags)prop.ReadValueAsInt32();
                            if ((flags & TnefAttachFlags.RenderedInBody) != 0)
                            {
                                if (attachment.ContentDisposition == null)
                                {
                                    attachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline);
                                }
                                else
                                {
                                    attachment.ContentDisposition.Disposition = ContentDisposition.Inline;
                                }
                            }
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, flags);
                            break;

                        case TnefPropertyId.AttachData:
                            var stream  = prop.GetRawValueReadStream();
                            var content = new MemoryStream();
                            var guid    = new byte[16];

                            if (attachMethod == TnefAttachMethod.EmbeddedMessage)
                            {
                                var tnef = new TnefPart();

                                foreach (var param in attachment.ContentType.Parameters)
                                {
                                    tnef.ContentType.Parameters[param.Name] = param.Value;
                                }

                                if (attachment.ContentDisposition != null)
                                {
                                    tnef.ContentDisposition = attachment.ContentDisposition;
                                }

                                attachment = tnef;
                            }

                            stream.Read(guid, 0, 16);

                            stream.CopyTo(content, 4096);

                            var buffer = content.GetBuffer();
                            filter.Flush(buffer, 0, (int)content.Length, out outIndex, out outLength);
                            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                            attachment.Content = new MimeContent(content);
                            filter.Reset();

                            //Console.WriteLine ("Attachment Property: {0} has GUID {1}", prop.PropertyTag.Id, new Guid (guid));

                            builder.Attachments.Add(attachment);
                            break;

                        case TnefPropertyId.DisplayName:
                            attachment.ContentType.Name = prop.ReadValueAsString();
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, attachment.ContentType.Name);
                            break;

                        case TnefPropertyId.AttachSize:
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition();
                            }

                            attachment.ContentDisposition.Size = prop.ReadValueAsInt64();
                            //Console.WriteLine ("Attachment Property: {0} = {1}", prop.PropertyTag.Id, attachment.ContentDisposition.Size.Value);
                            break;

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

                case TnefAttributeTag.AttachData:
                    //Console.WriteLine ("Attachment Attribute: {0}", reader.AttributeTag);
                    if (attachment == null || attachMethod != TnefAttachMethod.ByValue)
                    {
                        break;
                    }

                    attachData = prop.ReadValueAsBytes();
                    filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength);
                    attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    attachment.Content = new MimeContent(new MemoryStream(attachData, false));
                    filter.Reset();

                    builder.Attachments.Add(attachment);
                    break;

                case TnefAttributeTag.AttachCreateDate:
                    time = prop.ReadValueAsDateTime();

                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.CreationDate = time;
                    }

                    //Console.WriteLine ("Attachment Attribute: {0} = {1}", reader.AttributeTag, time);
                    break;

                case TnefAttributeTag.AttachModifyDate:
                    time = prop.ReadValueAsDateTime();

                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.ModificationDate = time;
                    }

                    //Console.WriteLine ("Attachment Attribute: {0} = {1}", reader.AttributeTag, time);
                    break;

                case TnefAttributeTag.AttachTitle:
                    text = prop.ReadValueAsString();

                    if (attachment != null && string.IsNullOrEmpty(attachment.FileName))
                    {
                        attachment.FileName = text;
                    }

                    //Console.WriteLine ("Attachment Attribute: {0} = {1}", reader.AttributeTag, text);
                    break;

                //case TnefAttributeTag.AttachMetaFile:
                //	break;
                default:
                    var type  = prop.ValueType;
                    var value = prop.ReadValue();
                    //Console.WriteLine ("Attachment Attribute (unhandled): {0} = {1}", reader.AttributeTag, value);
                    Assert.AreEqual(type, value.GetType(), "Unexpected value type for {0}: {1}", reader.AttributeTag, value.GetType().Name);
                    break;
                }
            } while (reader.ReadNextAttribute());
        }
Beispiel #12
0
        public void TestBestEncodingFilter()
        {
            const string fromLines = "This text is meant to test that the filter will armor lines beginning with\nFrom (like mbox).\n";
            const string ascii     = "This is some ascii text to make sure that\nthe filter returns 7bit encoding...\n";
            const string french    = "Wikipédia est un projet d’encyclopédie collective en ligne, universelle, multilingue et fonctionnant sur le principe du wiki. Wikipédia a pour objectif d’offrir un contenu librement réutilisable, objectif et vérifiable, que chacun peut modifier et améliorer.\n\nTous les rédacteurs des articles de Wikipédia sont bénévoles. Ils coordonnent leurs efforts au sein d'une communauté collaborative, sans dirigeant.";
            var          filter    = new BestEncodingFilter();

            TestArgumentExceptions(filter);

            Assert.Throws <ArgumentOutOfRangeException> (() => filter.GetBestEncoding(EncodingConstraint.SevenBit, 10));

            // Test ASCII text
            using (var stream = new MemoryStream()) {
                using (var filtered = new FilteredStream(stream)) {
                    var             buffer = Encoding.UTF8.GetBytes(ascii);
                    ContentEncoding encoding;

                    Assert.IsFalse(filtered.CanTimeout, "CanTimeout");
                    Assert.Throws <InvalidOperationException> (() => { var x = filtered.ReadTimeout; });
                    Assert.Throws <InvalidOperationException> (() => { var x = filtered.WriteTimeout; });
                    Assert.Throws <InvalidOperationException> (() => filtered.ReadTimeout  = 50);
                    Assert.Throws <InvalidOperationException> (() => filtered.WriteTimeout = 50);
                    Assert.Throws <NotSupportedException> (() => { long x = filtered.Length; });
                    Assert.Throws <NotSupportedException> (() => filtered.SetLength(100));
                    Assert.Throws <NotSupportedException> (() => { long x = filtered.Position; });
                    Assert.Throws <NotSupportedException> (() => filtered.Position = 0);

                    Assert.Throws <ArgumentNullException> (() => filtered.Add(null));
                    Assert.Throws <ArgumentNullException> (() => filtered.Contains(null));
                    Assert.Throws <ArgumentNullException> (() => filtered.Remove(null));

                    filtered.Add(filter);

                    Assert.IsTrue(filtered.Contains(filter), "Contains");

                    filtered.Write(buffer, 0, buffer.Length);
                    filtered.Flush();

                    encoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    Assert.AreEqual(ContentEncoding.SevenBit, encoding, "ASCII 7bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    Assert.AreEqual(ContentEncoding.SevenBit, encoding, "ASCII 8bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.None);
                    Assert.AreEqual(ContentEncoding.SevenBit, encoding, "ASCII no constraint.");

                    Assert.IsTrue(filtered.Remove(filter), "Remove");
                }
            }

            filter.Reset();

            // Test ASCII text with a line beginning with "From "
            using (var stream = new MemoryStream()) {
                using (var filtered = new FilteredStream(stream)) {
                    int             fromIndex = fromLines.IndexOf("\nFrom ", StringComparison.Ordinal);
                    var             buffer    = Encoding.UTF8.GetBytes(fromLines);
                    ContentEncoding encoding;

                    filtered.Add(filter);

                    // write out a buffer where the end boundary falls in the middle of "From "
                    int endIndex = fromIndex + 3;
                    filtered.Write(buffer, 0, endIndex);

                    // write out the rest
                    filtered.Write(buffer, endIndex, buffer.Length - endIndex);
                    filtered.Flush();

                    encoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "From-line 7bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "From-line 8bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.None);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "From-line no constraint.");
                }
            }

            filter.Reset();

            // Test some French Latin1 text
            using (var stream = new MemoryStream()) {
                using (var filtered = new FilteredStream(stream)) {
                    var             buffer = Encoding.UTF8.GetBytes(french);
                    ContentEncoding encoding;

                    filtered.Add(filter);

                    // We'll write only 60 chars at first to not exceed the 78 char max
                    filtered.Write(buffer, 0, 60);
                    filtered.Flush();

                    encoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "French 7bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    Assert.AreEqual(ContentEncoding.EightBit, encoding, "French 8bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.None);
                    Assert.AreEqual(ContentEncoding.EightBit, encoding, "French no constraint.");

                    filter.Reset();

                    // write the entire French text this time (longest line exceeds 78 chars)
                    filtered.Write(buffer, 0, buffer.Length);
                    filtered.Flush();

                    encoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "French (long lines) 7bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "French (long lines) 8bit constraint.");

                    encoding = filter.GetBestEncoding(EncodingConstraint.None);
                    Assert.AreEqual(ContentEncoding.QuotedPrintable, encoding, "French (long lines) no constraint.");
                }
            }
        }
Beispiel #13
0
        static void ExtractAttachments(TnefReader reader, BodyBuilder builder)
        {
            var             attachMethod = TnefAttachMethod.ByValue;
            var             filter = new BestEncodingFilter();
            var             prop = reader.TnefPropertyReader;
            MimePart        attachment = null;
            int             outIndex, outLength;
            TnefAttachFlags flags;

            string[] mimeType;
            byte[]   attachData;
            string   text;

            do
            {
                if (reader.AttributeLevel != TnefAttributeLevel.Attachment)
                {
                    break;
                }

                switch (reader.AttributeTag)
                {
                case TnefAttributeTag.AttachRenderData:
                    attachMethod = TnefAttachMethod.ByValue;
                    attachment   = new MimePart();
                    break;

                case TnefAttributeTag.Attachment:
                    if (attachment == null)
                    {
                        break;
                    }

                    while (prop.ReadNextProperty())
                    {
                        switch (prop.PropertyTag.Id)
                        {
                        case TnefPropertyId.AttachLongFilename:
                            attachment.FileName = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachFilename:
                            if (attachment.FileName == null)
                            {
                                attachment.FileName = prop.ReadValueAsString();
                            }
                            break;

                        case TnefPropertyId.AttachContentLocation:
                            text = prop.ReadValueAsString();
                            if (Uri.IsWellFormedUriString(text, UriKind.Absolute))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Absolute);
                            }
                            else if (Uri.IsWellFormedUriString(text, UriKind.Relative))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Relative);
                            }
                            break;

                        case TnefPropertyId.AttachContentBase:
                            text = prop.ReadValueAsString();
                            attachment.ContentBase = new Uri(text, UriKind.Absolute);
                            break;

                        case TnefPropertyId.AttachContentId:
                            attachment.ContentId = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachDisposition:
                            text = prop.ReadValueAsString();
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition(text);
                            }
                            else
                            {
                                attachment.ContentDisposition.Disposition = text;
                            }
                            break;

                        case TnefPropertyId.AttachData:
                            var stream  = prop.GetRawValueReadStream();
                            var content = new MemoryStream();
                            var guid    = new byte[16];

                            if (attachMethod == TnefAttachMethod.EmbeddedMessage)
                            {
                                var tnef = new TnefPart();

                                foreach (var param in attachment.ContentType.Parameters)
                                {
                                    tnef.ContentType.Parameters[param.Name] = param.Value;
                                }

                                if (attachment.ContentDisposition != null)
                                {
                                    tnef.ContentDisposition = attachment.ContentDisposition;
                                }

                                attachment = tnef;
                            }

                            // read the GUID
                            stream.Read(guid, 0, 16);

                            // the rest is content
                            using (var filtered = new FilteredStream(content)) {
                                filtered.Add(filter);
                                stream.CopyTo(filtered, 4096);
                                filtered.Flush();
                            }

                            content.Position = 0;

                            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                            attachment.Content = new MimeContent(content);
                            filter.Reset();

                            builder.Attachments.Add(attachment);
                            break;

                        case TnefPropertyId.AttachMethod:
                            attachMethod = (TnefAttachMethod)prop.ReadValueAsInt32();
                            break;

                        case TnefPropertyId.AttachMimeTag:
                            mimeType = prop.ReadValueAsString().Split('/');
                            if (mimeType.Length == 2)
                            {
                                attachment.ContentType.MediaType    = mimeType[0].Trim();
                                attachment.ContentType.MediaSubtype = mimeType[1].Trim();
                            }
                            break;

                        case TnefPropertyId.AttachFlags:
                            flags = (TnefAttachFlags)prop.ReadValueAsInt32();
                            if ((flags & TnefAttachFlags.RenderedInBody) != 0)
                            {
                                if (attachment.ContentDisposition == null)
                                {
                                    attachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline);
                                }
                                else
                                {
                                    attachment.ContentDisposition.Disposition = ContentDisposition.Inline;
                                }
                            }
                            break;

                        case TnefPropertyId.AttachSize:
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition();
                            }

                            attachment.ContentDisposition.Size = prop.ReadValueAsInt64();
                            break;

                        case TnefPropertyId.DisplayName:
                            attachment.ContentType.Name = prop.ReadValueAsString();
                            break;
                        }
                    }
                    break;

                case TnefAttributeTag.AttachCreateDate:
                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.CreationDate = prop.ReadValueAsDateTime();
                    }
                    break;

                case TnefAttributeTag.AttachModifyDate:
                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.ModificationDate = prop.ReadValueAsDateTime();
                    }
                    break;

                case TnefAttributeTag.AttachTitle:
                    if (attachment != null && string.IsNullOrEmpty(attachment.FileName))
                    {
                        attachment.FileName = prop.ReadValueAsString();
                    }
                    break;

                case TnefAttributeTag.AttachMetaFile:
                    if (attachment == null)
                    {
                        break;
                    }

                    // TODO: what to do with the meta data?
                    break;

                case TnefAttributeTag.AttachData:
                    if (attachment == null || attachMethod != TnefAttachMethod.ByValue)
                    {
                        break;
                    }

                    attachData = prop.ReadValueAsBytes();
                    filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength);
                    attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    attachment.Content = new MimeContent(new MemoryStream(attachData, false));
                    filter.Reset();

                    builder.Attachments.Add(attachment);
                    break;
                }
            } while (reader.ReadNextAttribute());
        }
Beispiel #14
0
        static void ExtractAttachments(TnefReader reader, BodyBuilder builder)
        {
            var      filter = new BestEncodingFilter();
            var      prop = reader.TnefPropertyReader;
            MimePart attachment = null;
            int      outIndex, outLength;

            byte[] attachData;
            string text;

            Console.WriteLine("Extracting attachments...");

            do
            {
                if (reader.AttributeLevel != TnefAttributeLevel.Attachment)
                {
                    Assert.Fail("Expected attachment attribute level: {0}", reader.AttributeLevel);
                }

                switch (reader.AttributeTag)
                {
                case TnefAttributeTag.AttachRenderData:
                    attachment = new MimePart();
                    builder.Attachments.Add(attachment);
                    break;

                case TnefAttributeTag.Attachment:
                    if (attachment == null)
                    {
                        break;
                    }

                    while (prop.ReadNextProperty())
                    {
                        switch (prop.PropertyTag.Id)
                        {
                        case TnefPropertyId.AttachLongFilename:
                            attachment.FileName = prop.ReadValueAsString();

                            Console.WriteLine("Attachment Property: {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:
                            text = prop.ReadValueAsString();
                            if (Uri.IsWellFormedUriString(text, UriKind.Absolute))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Absolute);
                            }
                            else if (Uri.IsWellFormedUriString(text, UriKind.Relative))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Relative);
                            }
                            Console.WriteLine("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachContentBase:
                            text = prop.ReadValueAsString();
                            attachment.ContentBase = new Uri(text, UriKind.Absolute);
                            Console.WriteLine("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachContentId:
                            attachment.ContentId = prop.ReadValueAsString();
                            Console.WriteLine("Attachment Property: {0} = {1}", prop.PropertyTag.Id, attachment.ContentId);
                            break;

                        case TnefPropertyId.AttachDisposition:
                            text = prop.ReadValueAsString();
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition(text);
                            }
                            else
                            {
                                attachment.ContentDisposition.Disposition = text;
                            }
                            Console.WriteLine("Attachment Property: {0} = {1}", prop.PropertyTag.Id, text);
                            break;

                        case TnefPropertyId.AttachData:
                            if (prop.IsEmbeddedMessage)
                            {
                                Console.WriteLine("Attachment Property: {0} is an EmbeddedMessage", prop.PropertyTag.Id);
                                var stream = prop.GetRawValueReadStream();
                                using (var tnef = new TnefReader(stream, reader.MessageCodepage, reader.ComplianceMode)) {
                                    var embedded = ExtractTnefMessage(tnef);
                                    Console.WriteLine("embedded attachments = {0}", embedded.BodyParts.Count());
                                    foreach (var part in embedded.BodyParts)
                                    {
                                        builder.Attachments.Add(part);
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("Attachment Property: {0} is not an EmbeddedMessage", prop.PropertyTag.Id);
                            }
                            break;

                        default:
                            Console.WriteLine("Attachment Property (unhandled): {0} = {1}", prop.PropertyTag.Id, prop.ReadValue());
                            break;
                        }
                    }
                    break;

                case TnefAttributeTag.AttachData:
                    if (attachment == null)
                    {
                        break;
                    }

                    attachData = prop.ReadValueAsBytes();
                    filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength);
                    attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                    attachment.ContentObject           = new ContentObject(new MemoryStream(attachData, false));
                    filter.Reset();
                    break;

                default:
                    Console.WriteLine("Attachment Attribute (unhandled): {0} = {1}", reader.AttributeTag, prop.ReadValue());
                    break;
                }
            } while (reader.ReadNextAttribute());
        }
Beispiel #15
0
        static void ExtractAttachments(TnefReader reader, BodyBuilder builder)
        {
            var      attachMethod = TnefAttachMethod.ByValue;
            var      filter = new BestEncodingFilter();
            var      prop = reader.TnefPropertyReader;
            MimePart attachment = null;
            int      outIndex, outLength;

            byte[] attachData;
            string text;

            do
            {
                if (reader.AttributeLevel != TnefAttributeLevel.Attachment)
                {
                    break;
                }

                switch (reader.AttributeTag)
                {
                case TnefAttributeTag.AttachRenderData:
                    attachMethod = TnefAttachMethod.ByValue;
                    attachment   = new MimePart();
                    break;

                case TnefAttributeTag.Attachment:
                    if (attachment == null)
                    {
                        break;
                    }

                    while (prop.ReadNextProperty())
                    {
                        switch (prop.PropertyTag.Id)
                        {
                        case TnefPropertyId.AttachLongFilename:
                            attachment.FileName = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachFilename:
                            if (attachment.FileName == null)
                            {
                                attachment.FileName = prop.ReadValueAsString();
                            }
                            break;

                        case TnefPropertyId.AttachContentLocation:
                            text = prop.ReadValueAsString();
                            if (Uri.IsWellFormedUriString(text, UriKind.Absolute))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Absolute);
                            }
                            else if (Uri.IsWellFormedUriString(text, UriKind.Relative))
                            {
                                attachment.ContentLocation = new Uri(text, UriKind.Relative);
                            }
                            break;

                        case TnefPropertyId.AttachContentBase:
                            text = prop.ReadValueAsString();
                            attachment.ContentBase = new Uri(text, UriKind.Absolute);
                            break;

                        case TnefPropertyId.AttachContentId:
                            attachment.ContentId = prop.ReadValueAsString();
                            break;

                        case TnefPropertyId.AttachDisposition:
                            text = prop.ReadValueAsString();
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition(text);
                            }
                            else
                            {
                                attachment.ContentDisposition.Disposition = text;
                            }
                            break;

                        case TnefPropertyId.AttachData:
                            var stream  = prop.GetRawValueReadStream();
                            var content = new MemoryStream();
                            var guid    = new byte[16];

                            if (attachMethod == TnefAttachMethod.EmbeddedMessage)
                            {
                                var tnef = new TnefPart();

                                foreach (var param in attachment.ContentType.Parameters)
                                {
                                    tnef.ContentType.Parameters.Add(param.Name, param.Value);
                                }

                                if (attachment.ContentDisposition != null)
                                {
                                    tnef.ContentDisposition = attachment.ContentDisposition;
                                }

                                attachment = tnef;
                            }

                            // read the GUID
                            stream.Read(guid, 0, 16);

                            // the rest is content
                            stream.CopyTo(content, 4096);

#if !PORTABLE
                            var buffer = content.GetBuffer();
#else
                            var buffer = content.ToArray();
#endif
                            filter.Flush(buffer, 0, (int)content.Length, out outIndex, out outLength);
                            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
                            attachment.ContentObject           = new ContentObject(content);
                            filter.Reset();

                            builder.Attachments.Add(attachment);
                            break;

                        case TnefPropertyId.AttachMethod:
                            attachMethod = (TnefAttachMethod)prop.ReadValueAsInt32();
                            break;

                        case TnefPropertyId.AttachSize:
                            if (attachment.ContentDisposition == null)
                            {
                                attachment.ContentDisposition = new ContentDisposition();
                            }

                            attachment.ContentDisposition.Size = prop.ReadValueAsInt64();
                            break;

                        case TnefPropertyId.DisplayName:
                            attachment.ContentType.Name = prop.ReadValueAsString();
                            break;
                        }
                    }
                    break;

                case TnefAttributeTag.AttachCreateDate:
                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.CreationDate = prop.ReadValueAsDateTime();
                    }
                    break;

                case TnefAttributeTag.AttachModifyDate:
                    if (attachment != null)
                    {
                        if (attachment.ContentDisposition == null)
                        {
                            attachment.ContentDisposition = new ContentDisposition();
                        }

                        attachment.ContentDisposition.ModificationDate = prop.ReadValueAsDateTime();
                    }
                    break;

                case TnefAttributeTag.AttachTitle:
                    if (attachment != null && string.IsNullOrEmpty(attachment.FileName))
                    {
                        attachment.FileName = prop.ReadValueAsString();
                    }
                    break;

                case TnefAttributeTag.AttachMetaFile:
                    if (attachment == null)
                    {
                        break;
                    }

                    // TODO: what to do with the meta data?
                    break;

                case TnefAttributeTag.AttachData:
                    if (attachment == null || attachMethod != TnefAttachMethod.ByValue)
                    {
                        break;
                    }

                    attachData = prop.ReadValueAsBytes();
                    filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength);
                    attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.EightBit);
                    attachment.ContentObject           = new ContentObject(new MemoryStream(attachData, false));
                    filter.Reset();

                    builder.Attachments.Add(attachment);
                    break;
                }
            } while (reader.ReadNextAttribute());
        }