A MIME part containing a partial message as its content.
Represents a MIME part with a Content-Type of message/partial.
Inheritance: MimePart
Example #1
0
		public void TestReassemble ()
		{
			var message1 = Load (Path.Combine ("..", "..", "TestData", "partial", "message-partial.1.msg.txt"));
			var message2 = Load (Path.Combine ("..", "..", "TestData", "partial", "message-partial.2.msg.txt"));

			Assert.IsNotNull (message1, "Failed to parse message-partial.1.msg");
			Assert.IsNotNull (message2, "Failed to parse message-partial.2.msg");

			Assert.IsTrue (message1.Body is MessagePartial, "The body of message-partial.1.msg is not a message/partial");
			Assert.IsTrue (message2.Body is MessagePartial, "The body of message-partial.2.msg is not a message/partial");

			var partials = new MessagePartial[] { (MessagePartial) message1.Body, (MessagePartial) message2.Body };
			Assert.Throws<ArgumentNullException> (() => MessagePartial.Join (null, partials));
			Assert.Throws<ArgumentNullException> (() => MessagePartial.Join (null));
			var message = MessagePartial.Join (partials);

			Assert.IsNotNull (message, "Failed to reconstruct the message");
			Assert.AreEqual ("{15_3779; Victoria & Cherry}: suzeFan - 2377h003.jpg", message.Subject, "Subjects do not match");
			Assert.IsTrue (message.Body is Multipart, "Parsed message body is not a multipart");

			var multipart = (Multipart) message.Body;
			Assert.AreEqual (2, multipart.Count, "Multipart does not contain the expected number of parts");

			var part = multipart[1] as MimePart;
			Assert.IsNotNull (part, "Second part is null or not a MimePart");
			Assert.IsTrue (part.ContentType.IsMimeType ("image", "jpeg"), "Attachment is not an image/jpeg");
			Assert.AreEqual ("2377h003.jpg", part.FileName, "Attachment filename is not the expected value");
		}
Example #2
0
        static int PartialCompare(MessagePartial partial1, MessagePartial partial2)
        {
            if (!partial1.Number.HasValue || !partial2.Number.HasValue || partial1.Id != partial2.Id)
            {
                throw new ArgumentException("Partial messages have mismatching identifiers.", "partials");
            }

            return(partial1.Number.Value - partial2.Number.Value);
        }
Example #3
0
        static int PartialCompare(MessagePartial partial1, MessagePartial partial2)
        {
            if (!partial1.Number.HasValue || !partial2.Number.HasValue || partial1.Id != partial2.Id)
            {
                throw new ArgumentException("partial");
            }

            return(partial1.Number.Value - partial2.Number.Value);
        }
Example #4
0
        /// <summary>
        /// Splits the specified message into multiple messages.
        /// </summary>
        /// <remarks>
        /// Splits the specified message into multiple messages, each with a
        /// message/partial body no larger than the max size specified.
        /// </remarks>
        /// <returns>An enumeration of partial messages.</returns>
        /// <param name="message">The message.</param>
        /// <param name="maxSize">The maximum size for each message body.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="message"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <paramref name="maxSize"/> is less than <c>1</c>.
        /// </exception>
        public static IEnumerable <MimeMessage> Split(MimeMessage message, int maxSize)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (maxSize < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(maxSize));
            }

            var options = FormatOptions.Default.Clone();

            foreach (HeaderId id in Enum.GetValues(typeof(HeaderId)))
            {
                switch (id)
                {
                case HeaderId.Subject:
                case HeaderId.MessageId:
                case HeaderId.Encrypted:
                case HeaderId.MimeVersion:
                case HeaderId.ContentAlternative:
                case HeaderId.ContentBase:
                case HeaderId.ContentClass:
                case HeaderId.ContentDescription:
                case HeaderId.ContentDisposition:
                case HeaderId.ContentDuration:
                case HeaderId.ContentFeatures:
                case HeaderId.ContentId:
                case HeaderId.ContentIdentifier:
                case HeaderId.ContentLanguage:
                case HeaderId.ContentLength:
                case HeaderId.ContentLocation:
                case HeaderId.ContentMd5:
                case HeaderId.ContentReturn:
                case HeaderId.ContentTransferEncoding:
                case HeaderId.ContentTranslationType:
                case HeaderId.ContentType:
                    break;

                default:
                    options.HiddenHeaders.Add(id);
                    break;
                }
            }

            var memory = new MemoryStream();

            message.WriteTo(options, memory);
            memory.Seek(0, SeekOrigin.Begin);

            if (memory.Length <= maxSize)
            {
                memory.Dispose();

                yield return(message);

                yield break;
            }

            var streams = new List <Stream> ();

#if !NETSTANDARD1_3 && !NETSTANDARD1_6
            var buf = memory.GetBuffer();
#else
            var buf = memory.ToArray();
#endif
            long startIndex = 0;

            while (startIndex < memory.Length)
            {
                // Preferably, we'd split on whole-lines if we can,
                // but if that's not possible, split on max size
                long endIndex = Math.Min(memory.Length, startIndex + maxSize);

                if (endIndex < memory.Length)
                {
                    long ebx = endIndex;

                    while (ebx > (startIndex + 1) && buf[ebx] != (byte)'\n')
                    {
                        ebx--;
                    }

                    if (buf[ebx] == (byte)'\n')
                    {
                        endIndex = ebx + 1;
                    }
                }

                streams.Add(new BoundStream(memory, startIndex, endIndex, true));
                startIndex = endIndex;
            }

            var msgid  = message.MessageId ?? MimeUtils.GenerateMessageId();
            int number = 1;

            foreach (var stream in streams)
            {
                var part = new MessagePartial(msgid, number++, streams.Count)
                {
                    Content = new MimeContent(stream)
                };

                var submessage = CloneMessage(message);
                submessage.MessageId = MimeUtils.GenerateMessageId();
                submessage.Body      = part;

                yield return(submessage);
            }

            yield break;
        }
Example #5
0
 /// <summary>
 /// Visit the message/partial MIME entity.
 /// </summary>
 /// <remarks>
 /// Visits the message/partial MIME entity.
 /// </remarks>
 /// <param name="entity">The message/partial MIME entity.</param>
 protected internal virtual void VisitMessagePartial(MessagePartial entity)
 {
     VisitMimePart(entity);
 }
Example #6
0
        static int PartialCompare(MessagePartial partial1, MessagePartial partial2)
        {
            if (!partial1.Number.HasValue || !partial2.Number.HasValue || partial1.Id != partial2.Id)
                throw new ArgumentException ("partial");

            return partial1.Number.Value - partial2.Number.Value;
        }
Example #7
0
        /// <summary>
        /// Split the specified message into multiple messages, each with a
        /// message/partial body no larger than the max size specified.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="maxSize">The maximum size for each message body.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="message"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <paramref name="maxSize"/> is less than <c>1</c>.
        /// </exception>
        public static IEnumerable<MimeMessage> Split(MimeMessage message, int maxSize)
        {
            if (message == null)
                throw new ArgumentNullException ("message");

            if (maxSize < 1)
                throw new ArgumentOutOfRangeException ("maxSize");

            using (var memory = new MemoryStream ()) {
                message.WriteTo (memory);
                memory.Seek (0, SeekOrigin.Begin);

                if (memory.Length <= maxSize) {
                    yield return message;
                    yield break;
                }

                var streams = new List<Stream> ();
                var buf = memory.GetBuffer ();
                long startIndex = 0;

                while (startIndex < memory.Length) {
                    // Preferably, we'd split on whole-lines if we can,
                    // but if that's not possible, split on max size
                    long endIndex = Math.Min (memory.Length, startIndex + maxSize);

                    if (endIndex < memory.Length) {
                        long ebx = endIndex;

                        while (ebx > (startIndex + 1) && buf[ebx] != (byte) '\n')
                            ebx--;

                        if (buf[ebx] == (byte) '\n')
                            endIndex = ebx + 1;
                    }

                    streams.Add (new BoundStream (memory, startIndex, endIndex, true));
                    startIndex = endIndex;
                }

                var id = message.MessageId ?? MimeUtils.GenerateMessageId ();
                int number = 1;

                foreach (var stream in streams) {
                    var part = new MessagePartial (id, number++, streams.Count);
                    part.ContentObject = new ContentObject (stream, ContentEncoding.Default);

                    var submessage = CloneMessage (message);
                    submessage.MessageId = MimeUtils.GenerateMessageId ();
                    submessage.Body = part;

                    yield return submessage;
                }
            }

            yield break;
        }
Example #8
0
		/// <summary>
		/// Visit the message/partial MIME entity.
		/// </summary>
		/// <remarks>
		/// Visits the message/partial MIME entity.
		/// </remarks>
		/// <param name="entity">The message/partial MIME entity.</param>
		protected internal virtual void VisitMessagePartial (MessagePartial entity)
		{
			VisitMimePart (entity);
		}
Example #9
0
        /// <summary>
        /// Splits the specified message into multiple messages.
        /// </summary>
        /// <remarks>
        /// Splits the specified message into multiple messages, each with a
        /// message/partial body no larger than the max size specified.
        /// </remarks>
        /// <returns>An enumeration of partial messages.</returns>
        /// <param name="message">The message.</param>
        /// <param name="maxSize">The maximum size for each message body.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="message"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <paramref name="maxSize"/> is less than <c>1</c>.
        /// </exception>
        public static IEnumerable <MimeMessage> Split(MimeMessage message, int maxSize)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (maxSize < 1)
            {
                throw new ArgumentOutOfRangeException("maxSize");
            }

            using (var memory = new MemoryStream()) {
                message.WriteTo(memory);
                memory.Seek(0, SeekOrigin.Begin);

                if (memory.Length <= maxSize)
                {
                    yield return(message);

                    yield break;
                }

                var streams = new List <Stream> ();
#if PORTABLE
                var buf = memory.ToArray();
#else
                var buf = memory.GetBuffer();
#endif
                long startIndex = 0;

                while (startIndex < memory.Length)
                {
                    // Preferably, we'd split on whole-lines if we can,
                    // but if that's not possible, split on max size
                    long endIndex = Math.Min(memory.Length, startIndex + maxSize);

                    if (endIndex < memory.Length)
                    {
                        long ebx = endIndex;

                        while (ebx > (startIndex + 1) && buf[ebx] != (byte)'\n')
                        {
                            ebx--;
                        }

                        if (buf[ebx] == (byte)'\n')
                        {
                            endIndex = ebx + 1;
                        }
                    }

                    streams.Add(new BoundStream(memory, startIndex, endIndex, true));
                    startIndex = endIndex;
                }

                var id     = message.MessageId ?? MimeUtils.GenerateMessageId();
                int number = 1;

                foreach (var stream in streams)
                {
                    var part = new MessagePartial(id, number++, streams.Count);
                    part.ContentObject = new ContentObject(stream, ContentEncoding.Default);

                    var submessage = CloneMessage(message);
                    submessage.MessageId = MimeUtils.GenerateMessageId();
                    submessage.Body      = part;

                    yield return(submessage);
                }
            }

            yield break;
        }
Example #10
0
		public void TestSplit ()
		{
			var message1 = Load (Path.Combine ("..", "..", "TestData", "partial", "message-partial.1.msg.txt"));
			var message2 = Load (Path.Combine ("..", "..", "TestData", "partial", "message-partial.2.msg.txt"));
			var partials = new MessagePartial[] { (MessagePartial) message1.Body, (MessagePartial) message2.Body };
			var message = MessagePartial.Join (partials);
			var split = MessagePartial.Split (message, 1024 * 16).ToList ();
			var parts = new List<MessagePartial> ();

			Assert.AreEqual (10, split.Count, "Unexpected count");

			for (int i = 0; i < split.Count; i++) {
				parts.Add ((MessagePartial) split[i].Body);

				Assert.AreEqual (10, parts[i].Total, "Total");
				Assert.AreEqual (i + 1, parts[i].Number, "Number");
			}

			var combined = MessagePartial.Join (parts);

			using (var stream = new MemoryStream ()) {
				var options = FormatOptions.Default.Clone ();
				options.NewLineFormat = NewLineFormat.Unix;

				message.WriteTo (options, stream);

				var bytes0 = new byte[stream.Position];
				Array.Copy (stream.GetBuffer (), 0, bytes0, 0, (int) stream.Position);

				stream.Position = 0;

				combined.WriteTo (options, stream);

				var bytes1 = new byte[stream.Position];
				Array.Copy (stream.GetBuffer (), 0, bytes1, 0, (int) stream.Position);

				Assert.AreEqual (bytes0.Length, bytes1.Length, "bytes");

				for (int i = 0; i < bytes0.Length; i++)
					Assert.AreEqual (bytes0[i], bytes1[i], "bytes[{0}]", i);
			}
		}