public void TestBase64Encode() { using (var original = new MemoryStream()) { using (var file = File.OpenRead("../../TestData/encoders/photo.b64")) { using (var filtered = new FilteredStream(original)) { filtered.Add(new Dos2UnixFilter()); file.CopyTo(filtered, 4096); filtered.Flush(); } } using (var encoded = new MemoryStream()) { using (var filtered = new FilteredStream(encoded)) { filtered.Add(EncoderFilter.Create(ContentEncoding.Base64)); using (var file = File.OpenRead("../../TestData/encoders/photo.jpg")) file.CopyTo(filtered, 4096); filtered.Flush(); } var buf0 = original.GetBuffer(); var buf1 = encoded.GetBuffer(); int n = (int)original.Length; Assert.AreEqual(original.Length, encoded.Length, "Encoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(buf0[i], buf1[i], "The byte at offset {0} does not match.", i); } } } }
/// <summary> /// Asynchronously writes the <see cref="MimeKit.MimePart"/> to the specified output stream. /// </summary> /// <remarks> /// Writes the MIME part to the output stream. /// </remarks> /// <param name="options">The formatting options.</param> /// <param name="stream">The output stream.</param> /// <param name="contentOnly"><c>true</c> if only the content should be written; otherwise, <c>false</c>.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="stream"/> is <c>null</c>.</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 override async Task WriteToAsync(FormatOptions options, Stream stream, bool contentOnly, CancellationToken cancellationToken = default(CancellationToken)) { await base.WriteToAsync(options, stream, contentOnly, cancellationToken).ConfigureAwait(false); if (Content == null) { return; } if (Content.Encoding != encoding) { if (encoding == ContentEncoding.UUEncode) { var begin = string.Format("begin 0644 {0}", FileName ?? "unknown"); var buffer = Encoding.UTF8.GetBytes(begin); await stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); await stream.WriteAsync(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken).ConfigureAwait(false); } // transcode the content into the desired Content-Transfer-Encoding using (var filtered = new FilteredStream(stream)) { filtered.Add(EncoderFilter.Create(encoding)); if (encoding != ContentEncoding.Binary) { filtered.Add(options.CreateNewLineFilter(EnsureNewLine)); } await Content.DecodeToAsync(filtered, cancellationToken).ConfigureAwait(false); await filtered.FlushAsync(cancellationToken).ConfigureAwait(false); } if (encoding == ContentEncoding.UUEncode) { var buffer = Encoding.ASCII.GetBytes("end"); await stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); await stream.WriteAsync(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken).ConfigureAwait(false); } } else if (encoding != ContentEncoding.Binary) { using (var filtered = new FilteredStream(stream)) { // Note: if we are writing the top-level MimePart, make sure it ends with a new-line so that // MimeMessage.WriteTo() *always* ends with a new-line. filtered.Add(options.CreateNewLineFilter(EnsureNewLine)); await Content.WriteToAsync(filtered, cancellationToken).ConfigureAwait(false); await filtered.FlushAsync(cancellationToken).ConfigureAwait(false); } } else { await Content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); } }
public void TestCreateEncoders() { Assert.Throws <ArgumentNullException> (() => EncoderFilter.Create(null)); Assert.Throws <ArgumentNullException> (() => DecoderFilter.Create(null)); AssertIsEncoderFilter(ContentEncoding.Base64, ContentEncoding.Base64); AssertIsEncoderFilter("base64", ContentEncoding.Base64); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.Binary)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("binary")); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.Default)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("x-invalid")); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.EightBit)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("8bit")); AssertIsEncoderFilter(ContentEncoding.QuotedPrintable, ContentEncoding.QuotedPrintable); AssertIsEncoderFilter("quoted-printable", ContentEncoding.QuotedPrintable); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.SevenBit)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("7bit")); AssertIsEncoderFilter(ContentEncoding.UUEncode, ContentEncoding.UUEncode); AssertIsEncoderFilter("x-uuencode", ContentEncoding.UUEncode); AssertIsEncoderFilter("uuencode", ContentEncoding.UUEncode); }
/// <summary> /// Writes the <see cref="MimeKit.MimePart"/> to the specified output stream. /// </summary> /// <param name="options">The formatting options.</param> /// <param name="stream">The output stream.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="stream"/> is <c>null</c>.</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 override void WriteTo(FormatOptions options, Stream stream, CancellationToken cancellationToken) { base.WriteTo(options, stream, cancellationToken); if (ContentObject == null) { return; } if (ContentObject.Encoding != encoding) { if (encoding == ContentEncoding.UUEncode) { cancellationToken.ThrowIfCancellationRequested(); var begin = string.Format("begin 0644 {0}", FileName ?? "unknown"); var buffer = Encoding.UTF8.GetBytes(begin); stream.Write(buffer, 0, buffer.Length); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); } // transcode the content into the desired Content-Transfer-Encoding using (var filtered = new FilteredStream(stream)) { filtered.Add(EncoderFilter.Create(encoding)); if (encoding != ContentEncoding.Binary) { filtered.Add(options.CreateNewLineFilter()); } ContentObject.DecodeTo(filtered, cancellationToken); filtered.Flush(); } if (encoding == ContentEncoding.UUEncode) { cancellationToken.ThrowIfCancellationRequested(); var buffer = Encoding.ASCII.GetBytes("end"); stream.Write(buffer, 0, buffer.Length); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); } } else if (encoding != ContentEncoding.Binary) { using (var filtered = new FilteredStream(stream)) { filtered.Add(options.CreateNewLineFilter()); ContentObject.WriteTo(filtered, cancellationToken); filtered.Flush(); } } else { ContentObject.WriteTo(stream, cancellationToken); } }
static void AssertIsEncoderFilter(string encoding, ContentEncoding expected) { var filter = EncoderFilter.Create(encoding); Assert.IsInstanceOf <EncoderFilter> (filter, "Expected EncoderFilter for \"{0}\"", encoding); var encoder = (EncoderFilter)filter; Assert.AreEqual(expected, encoder.Encoding, "Expected encoder's Encoding to be ContentEncoding.{0}", expected); }
void TestEncoder(ContentEncoding encoding, byte[] rawData, string encodedFile, int bufferSize) { int n; using (var original = new MemoryStream()) { using (var file = File.OpenRead(Path.Combine(dataDir, encodedFile))) { using (var filtered = new FilteredStream(original)) { filtered.Add(new Dos2UnixFilter()); file.CopyTo(filtered, 4096); filtered.Flush(); } } using (var encoded = new MemoryStream()) { if (encoding == ContentEncoding.UUEncode) { var begin = Encoding.ASCII.GetBytes("begin 644 photo.jpg\n"); encoded.Write(begin, 0, begin.Length); } using (var filtered = new FilteredStream(encoded)) { filtered.Add(EncoderFilter.Create(encoding)); using (var memory = new MemoryStream(rawData, false)) { var buffer = new byte[bufferSize]; while ((n = memory.Read(buffer, 0, bufferSize)) > 0) { filtered.Write(buffer, 0, n); } } filtered.Flush(); } if (encoding == ContentEncoding.UUEncode) { var end = Encoding.ASCII.GetBytes("end\n"); encoded.Write(end, 0, end.Length); } var buf0 = original.GetBuffer(); var buf1 = encoded.GetBuffer(); n = (int)original.Length; Assert.AreEqual(original.Length, encoded.Length, "Encoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(buf0[i], buf1[i], "The byte at offset {0} does not match.", i); } } } }
public void TestFilterArguments() { AssertFilterArguments(new Dos2UnixFilter()); AssertFilterArguments(new Unix2DosFilter()); AssertFilterArguments(new ArmoredFromFilter()); AssertFilterArguments(new BestEncodingFilter()); AssertFilterArguments(new CharsetFilter("iso-8859-1", "utf-8")); AssertFilterArguments(DecoderFilter.Create(ContentEncoding.Base64)); AssertFilterArguments(EncoderFilter.Create(ContentEncoding.Base64)); AssertFilterArguments(DecoderFilter.Create(ContentEncoding.QuotedPrintable)); AssertFilterArguments(EncoderFilter.Create(ContentEncoding.QuotedPrintable)); AssertFilterArguments(DecoderFilter.Create(ContentEncoding.UUEncode)); AssertFilterArguments(EncoderFilter.Create(ContentEncoding.UUEncode)); AssertFilterArguments(new TrailingWhitespaceFilter()); AssertFilterArguments(new DkimRelaxedBodyFilter()); AssertFilterArguments(new DkimSimpleBodyFilter()); }
public void TestUUEncode() { using (var original = new MemoryStream()) { using (var file = File.OpenRead("../../TestData/encoders/photo.uu")) { using (var filtered = new FilteredStream(original)) { filtered.Add(new Dos2UnixFilter()); file.CopyTo(filtered, 4096); filtered.Flush(); } } using (var encoded = new MemoryStream()) { var begin = Encoding.ASCII.GetBytes("begin 644 photo.jpg\n"); var end = Encoding.ASCII.GetBytes("end\n"); encoded.Write(begin, 0, begin.Length); using (var filtered = new FilteredStream(encoded)) { filtered.Add(EncoderFilter.Create(ContentEncoding.UUEncode)); using (var file = File.OpenRead("../../TestData/encoders/photo.jpg")) file.CopyTo(filtered, 4096); filtered.Flush(); } encoded.Write(end, 0, end.Length); var buf0 = original.GetBuffer(); var buf1 = encoded.GetBuffer(); int n = (int)original.Length; Assert.AreEqual(original.Length, encoded.Length, "Encoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(buf0[i], buf1[i], "The byte at offset {0} does not match.", i); } } } }
/// <summary> /// Writes the <see cref="MimeKit.MimePart"/> to the specified output stream. /// </summary> /// <remarks> /// Writes the MIME part to the output stream. /// </remarks> /// <param name="options">The formatting options.</param> /// <param name="stream">The output stream.</param> /// <param name="contentOnly"><c>true</c> if only the content should be written; otherwise, <c>false</c>.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="stream"/> is <c>null</c>.</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 override void WriteTo(FormatOptions options, Stream stream, bool contentOnly, CancellationToken cancellationToken = default(CancellationToken)) { base.WriteTo(options, stream, contentOnly, cancellationToken); if (ContentObject == null) { return; } var cancellable = stream as ICancellableStream; if (ContentObject.Encoding != encoding) { if (encoding == ContentEncoding.UUEncode) { var begin = string.Format("begin 0644 {0}", FileName ?? "unknown"); var buffer = Encoding.UTF8.GetBytes(begin); if (cancellable != null) { cancellable.Write(buffer, 0, buffer.Length, cancellationToken); cancellable.Write(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken); } else { cancellationToken.ThrowIfCancellationRequested(); stream.Write(buffer, 0, buffer.Length); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); } } // transcode the content into the desired Content-Transfer-Encoding using (var filtered = new FilteredStream(stream)) { filtered.Add(EncoderFilter.Create(encoding)); if (encoding != ContentEncoding.Binary) { filtered.Add(options.CreateNewLineFilter(true)); } ContentObject.DecodeTo(filtered, cancellationToken); filtered.Flush(cancellationToken); } if (encoding == ContentEncoding.UUEncode) { var buffer = Encoding.ASCII.GetBytes("end"); if (cancellable != null) { cancellable.Write(buffer, 0, buffer.Length, cancellationToken); cancellable.Write(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken); } else { cancellationToken.ThrowIfCancellationRequested(); stream.Write(buffer, 0, buffer.Length); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); } } } else if (encoding != ContentEncoding.Binary) { using (var filtered = new FilteredStream(stream)) { // Note: if we are writing the top-level MimePart, make sure it ends with a new-line so that // MimeMessage.WriteTo() *always* ends with a new-line. filtered.Add(options.CreateNewLineFilter(EnsureNewLine)); ContentObject.WriteTo(filtered, cancellationToken); filtered.Flush(cancellationToken); } } else { ContentObject.WriteTo(stream, cancellationToken); } }
/// <summary> /// Asynchronously write the <see cref="MimePart"/> to the specified output stream. /// </summary> /// <remarks> /// Asynchronously writes the MIME part to the output stream. /// </remarks> /// <returns>An awaitable task.</returns> /// <param name="options">The formatting options.</param> /// <param name="stream">The output stream.</param> /// <param name="contentOnly"><c>true</c> if only the content should be written; otherwise, <c>false</c>.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="stream"/> is <c>null</c>.</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 override async Task WriteToAsync(FormatOptions options, Stream stream, bool contentOnly, CancellationToken cancellationToken = default(CancellationToken)) { await base.WriteToAsync(options, stream, contentOnly, cancellationToken).ConfigureAwait(false); if (Content == null) { return; } var isText = ContentType.IsMimeType("text", "*") || ContentType.IsMimeType("message", "*"); if (Content.Encoding != encoding) { if (encoding == ContentEncoding.UUEncode) { var begin = string.Format("begin 0644 {0}", FileName ?? "unknown"); var buffer = Encoding.UTF8.GetBytes(begin); await stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); await stream.WriteAsync(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken).ConfigureAwait(false); } // transcode the content into the desired Content-Transfer-Encoding using (var filtered = new FilteredStream(stream)) { filtered.Add(EncoderFilter.Create(encoding)); if (encoding != ContentEncoding.Binary) { filtered.Add(options.CreateNewLineFilter(EnsureNewLine)); } await Content.DecodeToAsync(filtered, cancellationToken).ConfigureAwait(false); await filtered.FlushAsync(cancellationToken).ConfigureAwait(false); } if (encoding == ContentEncoding.UUEncode) { var buffer = Encoding.ASCII.GetBytes("end"); await stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); await stream.WriteAsync(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken).ConfigureAwait(false); } } else if (encoding == ContentEncoding.Binary) { // Do not alter binary content. await Content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); } else if (options.VerifyingSignature && Content.NewLineFormat.HasValue && Content.NewLineFormat.Value == NewLineFormat.Mixed) { // Allow pass-through of the original parsed content without canonicalization when verifying signatures // if the content contains a mix of line-endings. // // See https://github.com/jstedfast/MimeKit/issues/569 for details. await Content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); } else { using (var filtered = new FilteredStream(stream)) { // Note: if we are writing the top-level MimePart, make sure it ends with a new-line so that // MimeMessage.WriteTo() *always* ends with a new-line. filtered.Add(options.CreateNewLineFilter(EnsureNewLine)); await Content.WriteToAsync(filtered, cancellationToken).ConfigureAwait(false); await filtered.FlushAsync(cancellationToken).ConfigureAwait(false); } } }