async void StartTwitterStream(IToken token)
        {
            var stream = new FilteredStream();

            CrawlingLog.Log.Info("Init TwitterUpdateStrategy with Hashtag '{0}'".FormatWith(HashtagTrigger));
            Log.Info("Init TwitterUpdateStrategy with Hashtag '{0}'".FormatWith(HashtagTrigger), this);

            stream.AddTrack(HashtagTrigger);

            stream.StreamStarted += (sender, args) => CrawlingLog.Log.Info("Twitter stream started");

            // The following call blocks
            stream.StartStream(token, x => HandleTweet(x));
        }
示例#2
0
        static byte[] ReadAllBytes(Stream stream, bool text)
        {
            using (var memory = new MemoryStream()) {
                using (var filtered = new FilteredStream(memory)) {
                    if (text)
                    {
                        filtered.Add(new Dos2UnixFilter(true));
                    }
                    stream.CopyTo(filtered, 4096);
                    filtered.Flush();

                    return(memory.ToArray());
                }
            }
        }
示例#3
0
        public ImapReplayCommand(string command, string resource)
        {
            Command = command;

            using (var stream = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Imap.Resources." + resource)) {
                var memory = new MemoryBlockStream();

                using (var filtered = new FilteredStream(memory)) {
                    filtered.Add(new Unix2DosFilter());
                    stream.CopyTo(filtered, 4096);
                }

                Response = memory.ToArray();
            }
        }
示例#4
0
        public void TestIssue358()
        {
            // Note: This particular message has a badly folded header value for "x-microsoft-exchange-diagnostics:"
            // which was causing MimeParser.StepHeaders[Async]() to abort because ReadAhead() already had more than
            // ReadAheadSize bytes buffered, so it assumed it had reached EOF when in fact it had not.
            using (var stream = File.OpenRead(Path.Combine(MessagesDataDir, "issue358.txt"))) {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(new Unix2DosFilter());

                    var message = MimeMessage.Load(filtered);

                    // make sure that the top-level MIME part is a multipart/alternative
                    Assert.IsInstanceOf(typeof(MultipartAlternative), message.Body);
                }
            }
        }
示例#5
0
        public void TestYDecodeStateTransitions()
        {
            using (var file = File.OpenRead(Path.Combine(DataDir, "state-changes.ntx"))) {
                using (var decoded = new MemoryStream()) {
                    var ydec = new YDecoder();

                    using (var filtered = new FilteredStream(decoded)) {
                        filtered.Add(new DecoderFilter(ydec));
                        file.CopyTo(filtered, 1);
                        filtered.Flush();
                    }

                    Assert.AreEqual(584, decoded.Length, "The decoded size does not match.");
                    Assert.AreEqual(0xded29f4f, ydec.Checksum ^ 0xffffffff, "The decoded checksum does not match.");
                }
            }
        }
示例#6
0
        public ImapReplayCommand(Encoding encoding, string command, string resource, bool compressed = false)
        {
            string tag = null;

            CommandBuffer = encoding.GetBytes(command);
            Compressed    = compressed;
            Encoding      = encoding;
            Command       = command;

            if (command.StartsWith("A00000", StringComparison.Ordinal))
            {
                tag = command.Substring(0, 9);
            }

            using (var stream = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Imap.Resources." + resource)) {
                using (var memory = new MemoryBlockStream()) {
                    using (Stream compress = new CompressedStream(memory)) {
                        using (var filtered = new FilteredStream(compressed ? compress : memory)) {
                            if (tag != null)
                            {
                                filtered.Add(new ImapReplayFilter("A########", tag));
                            }

                            filtered.Add(new Unix2DosFilter());
                            stream.CopyTo(filtered, 4096);
                            filtered.Flush();
                        }

                        Response = memory.ToArray();
                    }
                }
            }

            if (compressed)
            {
                using (var memory = new MemoryStream()) {
                    using (var compress = new CompressedStream(memory)) {
                        compress.Write(CommandBuffer, 0, CommandBuffer.Length);
                        compress.Flush();

                        CommandBuffer = memory.ToArray();
                    }
                }
            }
        }
示例#7
0
        /// <summary>
        /// Gets the decoded text content using the provided charset to override
        /// the charset specified in the Content-Type parameters.
        /// </summary>
        /// <returns>The decoded text.</returns>
        /// <param name="charset">The charset encoding to use.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="charset"/> is <c>null</c>.
        /// </exception>
        public string GetText(Encoding charset)
        {
            if (charset == null)
            {
                throw new ArgumentNullException("charset");
            }

            using (var memory = new MemoryStream()) {
                using (var filtered = new FilteredStream(memory)) {
                    filtered.Add(new CharsetFilter(charset, Encoding.UTF8));

                    ContentObject.DecodeTo(filtered);
                    filtered.Flush();

                    return(Encoding.UTF8.GetString(memory.GetBuffer(), 0, (int)memory.Length));
                }
            }
        }
        /// <summary>
        /// Converts the contents of <paramref name="source"/> from the <see cref="InputFormat"/> to the
        /// <see cref="OutputFormat"/> and writes the resulting text to <paramref name="destination"/>.
        /// </summary>
        /// <remarks>
        /// Converts the contents of <paramref name="source"/> from the <see cref="InputFormat"/> to the
        /// <see cref="OutputFormat"/> and writes the resulting text to <paramref name="destination"/>.
        /// </remarks>
        /// <param name="source">The source stream.</param>
        /// <param name="destination">The destination stream.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="source"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="destination"/> is <c>null</c>.</para>
        /// </exception>
        public void Convert(Stream source, Stream destination)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }

            using (var filtered = new FilteredStream(destination)) {
                filtered.Add(this);
                source.CopyTo(filtered, 4096);
                filtered.Flush();
            }
        }
示例#9
0
        /// <summary>
        /// Writes the <see cref="MimeKit.MimePart"/> to the specified stream.
        /// </summary>
        /// <param name="options">The formatting options.</param>
        /// <param name="stream">The stream.</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>
        public override void WriteTo(FormatOptions options, Stream stream)
        {
            base.WriteTo(options, stream);

            if (ContentObject == null)
            {
                return;
            }

            if (ContentObject.Encoding != encoding)
            {
                if (encoding == ContentEncoding.UUEncode)
                {
                    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));
                    filtered.Add(options.CreateNewLineFilter());
                    ContentObject.DecodeTo(filtered);
                    filtered.Flush();
                }

                if (encoding == ContentEncoding.UUEncode)
                {
                    var buffer = Encoding.ASCII.GetBytes("end");
                    stream.Write(buffer, 0, buffer.Length);
                    stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length);
                }
            }
            else
            {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(options.CreateNewLineFilter());
                    ContentObject.WriteTo(filtered);
                    filtered.Flush();
                }
            }
        }
示例#10
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));
                }
            }
        }
示例#11
0
        public static void SearchTwitterStreaming()
        {
            var token = new TwitterToken.Token(_accessToken, _accessTokenSecret, _consumerKey, _consumerSecret);

            // Create the stream
            var myStream = new FilteredStream();

            myStream.AddTrack("#apple");
            myStream.AddTrack("#google");
            myStream.AddTrack("#twitter");
            myStream.AddTrack("#tesla");
            myStream.AddTrack("#ford");
            myStream.AddTrack("#shell");
            myStream.AddTrack("#bks");


            // Starting the stream by specifying credentials thanks to the Token and a delegate specifying what you want to do when you receive a tweet
            using (var conn = new SqlCeConnection(_sqlConnection))
            {
                conn.Open();
                var insert = new SqlCeCommand("INSERT INTO Tweets(Text, UserFollowers, RetweetCount, CreatedAt) Values(@Text, @UserFollowers, @RetweetCount, @CreatedAt)", conn);
                try
                {
                    myStream.StartStream(token, tweet =>
                    {
                        insert.Parameters.Clear();
                        insert.Parameters.AddWithValue("@Text", tweet.Text);
                        insert.Parameters.AddWithValue("@UserFollowers", tweet.Creator.FollowersCount);
                        insert.Parameters.AddWithValue("@RetweetCount", tweet.RetweetCount);
                        insert.Parameters.AddWithValue("@CreatedAt", tweet.CreatedAt);
                        var status = insert.ExecuteNonQuery();
                        //Console.WriteLine("{0}: {1}", status, tweet.Text);
                    });
                }
                catch
                {
                }
                finally
                {
                    conn.Close();
                }
            }
        }
示例#12
0
        public void StartStreamTrackRandomUniqueWord()
        {
            // Arrange
            var  randomWord      = String.Format("Tweetinvi{0}", new Random().Next());
            var  expectedMessage = String.Format("Hello {0}", randomWord);
            bool result          = false;

            Thread t = new Thread(() =>
            {
                IFilteredStream stream = new FilteredStream();

                stream.AddTrack(randomWord);

                Func <ITweet, bool> listen = delegate(ITweet tweet)
                {
                    if (tweet != null)
                    {
                        result = tweet.Text == expectedMessage;
                    }

                    // End the stream
                    return(false);
                };

                stream.StartStream(TokenSingleton.Token, listen);
            });

            t.Start();

            // Act
            ITweet newTweet = new Tweet(expectedMessage, TokenTestSingleton.Instance);

            newTweet.Publish();

            Thread.Sleep(500);
            t.Join();

            // Assert
            Assert.AreEqual(result, true);

            // Cleanup
            newTweet.Destroy();
        }
示例#13
0
        public void TestDecodeSimpleYEncMessage()
        {
            using (var file = File.OpenRead("../../TestData/yenc/simple.msg")) {
                var message = MimeMessage.Load(file);

                using (var decoded = new MemoryStream()) {
                    var ydec = new YDecoder();

                    using (var filtered = new FilteredStream(decoded)) {
                        filtered.Add(new DecoderFilter(ydec));

                        ((MimePart)message.Body).ContentObject.WriteTo(filtered);
                    }

                    Assert.AreEqual(584, decoded.Length, "The decoded size does not match.");
                    Assert.AreEqual(0xded29f4f, ydec.Checksum ^ 0xffffffff, "The checksum does not match.");
                }
            }
        }
示例#14
0
        Header GenerateArcSeal(FormatOptions options, int instance, TimeSpan t, ArcHeaderSet[] sets, int count, Header aar, Header ams)
        {
            var value = CreateArcHeaderBuilder(instance);

            byte[] signature;
            Header seal;

            // FIXME: where should this value come from?
            value.Append("; cv=pass");

            value.AppendFormat("; d={0}; s={1}", Domain, Selector);
            value.AppendFormat("; t={0}", (long)t.TotalSeconds);

            using (var stream = new DkimSignatureStream(CreateSigningContext())) {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(options.CreateNewLineFilter());

                    for (int i = 0; i < count; i++)
                    {
                        DkimVerifierBase.WriteHeaderRelaxed(options, filtered, sets[i].ArcAuthenticationResult, false);
                        DkimVerifierBase.WriteHeaderRelaxed(options, filtered, sets[i].ArcMessageSignature, false);
                        DkimVerifierBase.WriteHeaderRelaxed(options, filtered, sets[i].ArcSeal, false);
                    }

                    DkimVerifierBase.WriteHeaderRelaxed(options, filtered, aar, false);
                    DkimVerifierBase.WriteHeaderRelaxed(options, filtered, ams, false);

                    value.Append("; b=");

                    seal = new Header(HeaderId.ArcSeal, value.ToString());
                    DkimVerifierBase.WriteHeaderRelaxed(options, filtered, seal, true);

                    filtered.Flush();
                }

                signature = stream.GenerateSignature();

                seal.Value += Convert.ToBase64String(signature);

                return(seal);
            }
        }
示例#15
0
        /// <summary>
        /// Writes the <see cref="MimeKit.HeaderList"/> to the specified output stream.
        /// </summary>
        /// <remarks>
        /// Writes all of the headers to the output stream.
        /// </remarks>
        /// <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 void WriteTo(FormatOptions options, Stream stream, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            using (var filtered = new FilteredStream(stream)) {
                if (options.NewLineFormat != FormatOptions.Default.NewLineFormat)
                {
                    filtered.Add(options.CreateNewLineFilter());
                }

                foreach (var header in headers)
                {
                    var    name = Encoding.ASCII.GetBytes(header.Field);
                    byte[] rawValue;

                    filtered.Write(name, 0, name.Length, cancellationToken);
                    filtered.Write(new [] { (byte)':' }, 0, 1, cancellationToken);

                    if (options.International)
                    {
                        rawValue = header.GetRawValue(options, Encoding.UTF8);
                    }
                    else
                    {
                        rawValue = header.RawValue;
                    }

                    filtered.Write(rawValue, 0, rawValue.Length, cancellationToken);
                }

                filtered.Flush(cancellationToken);
            }
        }
示例#16
0
        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);
                    }
                }
            }
        }
示例#17
0
        Stream GetResourceStream(string name)
        {
            using (var response = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Pop3.Resources." + name)) {
                var memory = new MemoryBlockStream();

                using (var filtered = new FilteredStream(memory)) {
                    if (testUnixFormat)
                    {
                        filtered.Add(new Dos2UnixFilter());
                    }
                    else
                    {
                        filtered.Add(new Unix2DosFilter());
                    }
                    response.CopyTo(filtered, 4096);
                }

                memory.Position = 0;
                return(memory);
            }
        }
示例#18
0
        /// <summary>
        /// Creates a new <see cref="MultipartEncrypted"/>.
        /// </summary>
        /// <remarks>
        /// Encrypts the entity to the specified recipients, encapsulating the result in a
        /// new multipart/encrypted part.
        /// </remarks>
        /// <returns>A new <see cref="MimeKit.Cryptography.MultipartEncrypted"/> instance containing
        /// the encrypted version of the specified entity.</returns>
        /// <param name="ctx">The OpenPGP cryptography context to use for encrypting.</param>
        /// <param name="recipients">The recipients for the encrypted entity.</param>
        /// <param name="entity">The entity to sign and encrypt.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="recipients"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// One or more of the recipient keys cannot be used for encrypting.
        /// </exception>
        public static MultipartEncrypted Create(OpenPgpContext ctx, IEnumerable <PgpPublicKey> recipients, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }

            if (recipients == null)
            {
                throw new ArgumentNullException("recipients");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            using (var memory = new MemoryBlockStream()) {
                using (var filtered = new FilteredStream(memory)) {
                    filtered.Add(new Unix2DosFilter());

                    PrepareEntityForEncrypting(entity);
                    entity.WriteTo(filtered);
                    filtered.Flush();
                }

                memory.Position = 0;

                var encrypted = new MultipartEncrypted();
                encrypted.ContentType.Parameters["protocol"] = ctx.EncryptionProtocol;

                // add the protocol version part
                encrypted.Add(new ApplicationPgpEncrypted());

                // add the encrypted entity as the second part
                encrypted.Add(ctx.Encrypt(recipients, memory));

                return(encrypted);
            }
        }
示例#19
0
        void Data(MimeMessage message, CancellationToken cancellationToken)
        {
            var response = SendCommand("DATA", cancellationToken);

            if (response.StatusCode != SmtpStatusCode.StartMailInput)
            {
                throw new SmtpCommandException(SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);
            }

            var options = FormatOptions.Default.Clone();

            options.NewLineFormat = NewLineFormat.Dos;

            options.HiddenHeaders.Add(HeaderId.ContentLength);
            options.HiddenHeaders.Add(HeaderId.ResentBcc);
            options.HiddenHeaders.Add(HeaderId.Bcc);

            using (var filtered = new FilteredStream(stream)) {
                filtered.Add(new SmtpDataFilter());
                message.WriteTo(options, filtered, cancellationToken);
                filtered.Flush();
            }

            stream.Write(EndData, 0, EndData.Length);

            response = ReadResponse(cancellationToken);

            switch (response.StatusCode)
            {
            default:
                throw new SmtpCommandException(SmtpErrorCode.MessageNotAccepted, response.StatusCode, response.Response);

            case SmtpStatusCode.AuthenticationRequired:
                throw new UnauthorizedAccessException(response.Response);

            case SmtpStatusCode.Ok:
                break;
            }
        }
示例#20
0
        public void TestYDecodeMultiPart()
        {
            var expected = File.ReadAllBytes(Path.Combine(DataDir, "joystick.jpg"));

            using (var decoded = new MemoryStream()) {
                using (var file = File.OpenRead(Path.Combine(DataDir, "00000020.ntx"))) {
                    var ydec = new YDecoder();

                    using (var filtered = new FilteredStream(decoded)) {
                        filtered.Add(new DecoderFilter(ydec));
                        file.CopyTo(filtered, 1);
                        filtered.Flush();
                    }

                    Assert.AreEqual(11250, decoded.Length, "The decoded size does not match (part 1).");
                    Assert.AreEqual(0xbfae5c0b, ydec.Checksum ^ 0xffffffff, "The decoded checksum does not match (part 1).");
                }

                using (var file = File.OpenRead(Path.Combine(DataDir, "00000021.ntx"))) {
                    var ydec = new YDecoder();

                    using (var filtered = new FilteredStream(decoded)) {
                        filtered.Add(new DecoderFilter(ydec));
                        file.CopyTo(filtered, 1);
                        filtered.Flush();
                    }

                    Assert.AreEqual(19338, decoded.Length, "The decoded size does not match (part 2).");
                    Assert.AreEqual(0xaca76043, ydec.Checksum ^ 0xffffffff, "The decoded checksum does not match (part 2).");
                }

                var actual = decoded.GetBuffer();

                for (int i = 0; i < expected.Length; i++)
                {
                    Assert.AreEqual(expected[i], actual[i], "different content at index {0}", i);
                }
            }
        }
示例#21
0
        Stream GetResponseStream(ImapReplayCommand command)
        {
            MemoryStream memory;

            if (testUnixFormat)
            {
                memory = new MemoryStream();

                using (var filtered = new FilteredStream(memory)) {
                    filtered.Add(new Dos2UnixFilter());
                    filtered.Write(command.Response, 0, command.Response.Length);
                    filtered.Flush();
                }

                memory.Position = 0;
            }
            else
            {
                memory = new MemoryStream(command.Response, false);
            }

            return(memory);
        }
示例#22
0
        internal async Task SaveToPickupDirectoryAsync(MimeMessage message)
        {
            var    path = Path.Combine("C:/Emails", Guid.NewGuid().ToString() + ".eml");
            Stream stream;

            stream = File.Open(path, FileMode.CreateNew);
            using (stream)
            {
                using (var filtered = new FilteredStream(stream))
                {
                    filtered.Add(new SmtpDataFilter());

                    var options = FormatOptions.Default.Clone();
                    options.NewLineFormat = NewLineFormat.Dos;

                    await message.WriteToAsync(options, filtered);

                    await filtered.FlushAsync();

                    return;
                }
            }
        }
示例#23
0
        public void TestCanReadWriteSeekTimeout()
        {
            var buffer = new byte[1024];

            using (var filtered = new FilteredStream(new CanReadWriteSeekStream(true, false, false, false))) {
                Assert.IsTrue(filtered.CanRead);
                Assert.IsFalse(filtered.CanWrite);
                Assert.IsFalse(filtered.CanSeek);
                Assert.IsFalse(filtered.CanTimeout);

                Assert.Throws <NotImplementedException> (() => filtered.Read(buffer, 0, buffer.Length));
                Assert.Throws <NotSupportedException> (() => filtered.Write(buffer, 0, buffer.Length));
                Assert.Throws <NotSupportedException> (() => filtered.Seek(0, SeekOrigin.End));
            }

            using (var filtered = new FilteredStream(new CanReadWriteSeekStream(false, true, false, false))) {
                Assert.IsFalse(filtered.CanRead);
                Assert.IsTrue(filtered.CanWrite);
                Assert.IsFalse(filtered.CanSeek);
                Assert.IsFalse(filtered.CanTimeout);

                Assert.Throws <NotSupportedException> (() => filtered.Read(buffer, 0, buffer.Length));
                Assert.Throws <NotImplementedException> (() => filtered.Write(buffer, 0, buffer.Length));
                Assert.Throws <NotSupportedException> (() => filtered.Seek(0, SeekOrigin.End));
            }

            using (var filtered = new FilteredStream(new CanReadWriteSeekStream(false, false, true, false))) {
                Assert.IsFalse(filtered.CanRead);
                Assert.IsFalse(filtered.CanWrite);
                Assert.IsFalse(filtered.CanSeek);                   // FilteredStream can never seek
                Assert.IsFalse(filtered.CanTimeout);

                Assert.Throws <NotSupportedException> (() => filtered.Read(buffer, 0, buffer.Length));
                Assert.Throws <NotSupportedException> (() => filtered.Write(buffer, 0, buffer.Length));
                Assert.Throws <NotSupportedException> (() => filtered.Seek(0, SeekOrigin.End));                 // FilteredStream can never seek
            }
        }
示例#24
0
        static void TestOpenPgpBlockFilter(OpenPgpBlockFilter filter, byte[] buffer, string expected, int increment)
        {
            using (var stream = new MemoryStream()) {
                using (var filtered = new FilteredStream(stream)) {
                    int startIndex = 0;

                    filtered.Add(filter);

                    while (startIndex < buffer.Length)
                    {
                        int n = Math.Min(buffer.Length - startIndex, increment);

                        filtered.Write(buffer, startIndex, n);
                        startIndex += n;
                    }

                    filtered.Flush();

                    var actual = Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);

                    Assert.AreEqual(expected, actual, "increment of {0} failed.", increment);
                }
            }
        }
示例#25
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);
        }
示例#26
0
        void TestDecoder(ContentEncoding encoding, byte[] rawData, string encodedFile, int bufferSize, bool unix = false)
        {
            int n;

            using (var decoded = new MemoryStream()) {
                using (var filtered = new FilteredStream(decoded)) {
                    filtered.Add(DecoderFilter.Create(encoding));

                    if (unix)
                    {
                        filtered.Add(new Dos2UnixFilter());
                    }

                    using (var file = File.OpenRead(Path.Combine(dataDir, encodedFile))) {
                        var buffer = new byte[bufferSize];

                        while ((n = file.Read(buffer, 0, bufferSize)) > 0)
                        {
                            filtered.Write(buffer, 0, n);
                        }
                    }

                    filtered.Flush();
                }

                var buf = decoded.GetBuffer();
                n = rawData.Length;

                Assert.AreEqual(rawData.Length, decoded.Length, "Decoded length is incorrect.");

                for (int i = 0; i < n; i++)
                {
                    Assert.AreEqual(rawData[i], buf[i], "The byte at offset {0} does not match.", i);
                }
            }
        }
示例#27
0
        static void ExtractMapiProperties(TnefReader reader, MimeMessage message, BodyBuilder builder)
        {
            var prop  = reader.TnefPropertyReader;
            var chars = new char[1024];
            var buf   = new byte[1024];

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

                switch (prop.PropertyTag.Id)
                {
                case TnefPropertyId.InternetMessageId:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        message.MessageId = prop.ReadValueAsString();
                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, message.MessageId);
                    }
                    else
                    {
                        Assert.Fail("Unknown property type for Message-Id: {0}", prop.PropertyTag.ValueTnefType);
                    }
                    break;

                case TnefPropertyId.Subject:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        message.Subject = prop.ReadValueAsString();
                        //Console.WriteLine ("Message Property: {0} = {1}", prop.PropertyTag.Id, message.Subject);
                    }
                    else
                    {
                        Assert.Fail("Unknown property type for Subject: {0}", prop.PropertyTag.ValueTnefType);
                    }
                    break;

                case TnefPropertyId.RtfCompressed:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        var rtf = new TextPart("rtf");
                        rtf.ContentType.Name = "body.rtf";

                        var converter = new RtfCompressedToRtf();
                        var content   = new MemoryStream();

                        using (var filtered = new FilteredStream(content)) {
                            filtered.Add(converter);

                            using (var compressed = prop.GetRawValueReadStream()) {
                                compressed.CopyTo(filtered, 4096);
                                filtered.Flush();
                            }
                        }

                        rtf.Content      = new MimeContent(content);
                        content.Position = 0;

                        builder.Attachments.Add(rtf);

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

                case TnefPropertyId.BodyHtml:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        var html = new TextPart("html");
                        html.ContentType.Name = "body.html";
                        html.Text             = prop.ReadValueAsString();

                        builder.Attachments.Add(html);

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

                case TnefPropertyId.Body:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        var plain = new TextPart("plain");
                        plain.ContentType.Name = "body.txt";
                        plain.Text             = prop.ReadValueAsString();

                        builder.Attachments.Add(plain);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    //Console.WriteLine ("Message Property (unhandled): {0} = {1}", prop.PropertyTag.Id, value);
                    Assert.AreEqual(type, value.GetType(), "Unexpected value type for {0}: {1}", prop.PropertyTag, value.GetType().Name);
                    break;
                }
            }
        }
示例#28
0
        async Task <bool> VerifyAsync(FormatOptions options, MimeMessage message, Header dkimSignature, bool doAsync, CancellationToken cancellationToken)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (dkimSignature == null)
            {
                throw new ArgumentNullException(nameof(dkimSignature));
            }

            if (dkimSignature.Id != HeaderId.DkimSignature)
            {
                throw new ArgumentException("The signature parameter MUST be a DKIM-Signature header.", nameof(dkimSignature));
            }

            var parameters = ParseParameterTags(dkimSignature.Id, dkimSignature.Value);
            DkimCanonicalizationAlgorithm headerAlgorithm, bodyAlgorithm;
            DkimSignatureAlgorithm        signatureAlgorithm;
            AsymmetricKeyParameter        key;
            string d, s, q, bh, b;

            string[] headers;
            int      maxLength;

            ValidateDkimSignatureParameters(parameters, out signatureAlgorithm, out headerAlgorithm, out bodyAlgorithm,
                                            out d, out s, out q, out headers, out bh, out b, out maxLength);

            if (!IsEnabled(signatureAlgorithm))
            {
                return(false);
            }

            if (doAsync)
            {
                key = await PublicKeyLocator.LocatePublicKeyAsync(q, d, s, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                key = PublicKeyLocator.LocatePublicKey(q, d, s, cancellationToken);
            }

            if ((key is RsaKeyParameters rsa) && rsa.Modulus.BitLength < MinimumRsaKeyLength)
            {
                return(false);
            }

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;

            // first check the body hash (if that's invalid, then the entire signature is invalid)
            var hash = Convert.ToBase64String(message.HashBody(options, signatureAlgorithm, bodyAlgorithm, maxLength));

            if (hash != bh)
            {
                return(false);
            }

            using (var stream = new DkimSignatureStream(CreateVerifyContext(signatureAlgorithm, key))) {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(options.CreateNewLineFilter());

                    WriteHeaders(options, message, headers, headerAlgorithm, filtered);

                    // now include the DKIM-Signature header that we are verifying,
                    // but only after removing the "b=" signature value.
                    var header = GetSignedSignatureHeader(dkimSignature);

                    switch (headerAlgorithm)
                    {
                    case DkimCanonicalizationAlgorithm.Relaxed:
                        WriteHeaderRelaxed(options, filtered, header, true);
                        break;

                    default:
                        WriteHeaderSimple(options, filtered, header, true);
                        break;
                    }

                    filtered.Flush();
                }

                return(stream.VerifySignature(b));
            }
        }
示例#29
0
        static void ExtractMapiProperties(TnefReader reader, MimeMessage message, BodyBuilder builder)
        {
            var            prop              = reader.TnefPropertyReader;
            var            recipient         = new EmailAddress();
            var            sender            = new EmailAddress();
            string         normalizedSubject = null;
            string         subjectPrefix     = null;
            MailboxAddress mailbox;
            var            msgid = false;

            while (prop.ReadNextProperty())
            {
                switch (prop.PropertyTag.Id)
                {
                case TnefPropertyId.InternetMessageId:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        message.MessageId = prop.ReadValueAsString();
                        msgid             = true;
                    }
                    break;

                case TnefPropertyId.TnefCorrelationKey:
                    // According to MSDN, PidTagTnefCorrelationKey is a unique key that is
                    // meant to be used to tie the TNEF attachment to the encapsulating
                    // message. It can be a string or a binary blob. It seems that most
                    // implementations use the Message-Id string, so if this property
                    // value looks like a Message-Id, then us it as one (unless we get a
                    // InternetMessageId property, in which case we use that instead.
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        if (!msgid)
                        {
                            var value = prop.ReadValueAsString();

                            if (value.Length > 5 && value[0] == '<' && value[value.Length - 1] == '>' && value.IndexOf('@') != -1)
                            {
                                message.MessageId = value;
                            }
                        }
                    }
                    break;

                case TnefPropertyId.Subject:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        message.Subject = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.SubjectPrefix:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        subjectPrefix = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.NormalizedSubject:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        normalizedSubject = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.SenderName:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        sender.Name = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.SenderEmailAddress:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        sender.Addr = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.SenderSearchKey:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        sender.SearchKey = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.SenderAddrtype:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        sender.AddrType = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.ReceivedByName:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        recipient.Name = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.ReceivedByEmailAddress:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        recipient.Addr = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.ReceivedBySearchKey:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        recipient.SearchKey = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.ReceivedByAddrtype:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode)
                    {
                        recipient.AddrType = prop.ReadValueAsString();
                    }
                    break;

                case TnefPropertyId.RtfCompressed:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        var rtf = new TextPart("rtf");

                        var converter = new RtfCompressedToRtf();
                        var content   = new MemoryBlockStream();

                        using (var filtered = new FilteredStream(content)) {
                            filtered.Add(converter);

                            using (var compressed = prop.GetRawValueReadStream()) {
                                compressed.CopyTo(filtered, 4096);
                                filtered.Flush();
                            }
                        }

                        rtf.Content      = new MimeContent(content);
                        content.Position = 0;

                        builder.Attachments.Add(rtf);
                    }
                    break;

                case TnefPropertyId.BodyHtml:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        var      html = new TextPart("html");
                        Encoding encoding;

                        if (prop.PropertyTag.ValueTnefType != TnefPropertyType.Unicode)
                        {
                            encoding = Encoding.GetEncoding(reader.MessageCodepage);
                        }
                        else
                        {
                            encoding = CharsetUtils.UTF8;
                        }

                        html.SetText(encoding, prop.ReadValueAsString());

                        builder.Attachments.Add(html);
                    }
                    break;

                case TnefPropertyId.Body:
                    if (prop.PropertyTag.ValueTnefType == TnefPropertyType.String8 ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Unicode ||
                        prop.PropertyTag.ValueTnefType == TnefPropertyType.Binary)
                    {
                        var      plain = new TextPart("plain");
                        Encoding encoding;

                        if (prop.PropertyTag.ValueTnefType != TnefPropertyType.Unicode)
                        {
                            encoding = Encoding.GetEncoding(reader.MessageCodepage);
                        }
                        else
                        {
                            encoding = CharsetUtils.UTF8;
                        }

                        plain.SetText(encoding, prop.ReadValueAsString());

                        builder.Attachments.Add(plain);
                    }
                    break;

                case TnefPropertyId.Importance:
                    // https://msdn.microsoft.com/en-us/library/ee237166(v=exchg.80).aspx
                    switch (prop.ReadValueAsInt32())
                    {
                    case 2: message.Importance = MessageImportance.High; break;

                    case 1: message.Importance = MessageImportance.Normal; break;

                    case 0: message.Importance = MessageImportance.Low; break;
                    }
                    break;

                case TnefPropertyId.Priority:
                    // https://msdn.microsoft.com/en-us/library/ee159473(v=exchg.80).aspx
                    switch (prop.ReadValueAsInt32())
                    {
                    case  1: message.Priority = MessagePriority.Urgent; break;

                    case  0: message.Priority = MessagePriority.Normal; break;

                    case -1: message.Priority = MessagePriority.NonUrgent; break;
                    }
                    break;

                case TnefPropertyId.Sensitivity:
                    // https://msdn.microsoft.com/en-us/library/ee217353(v=exchg.80).aspx
                    // https://tools.ietf.org/html/rfc2156#section-5.3.4
                    switch (prop.ReadValueAsInt32())
                    {
                    case 1: message.Headers[HeaderId.Sensitivity] = "Personal"; break;

                    case 2: message.Headers[HeaderId.Sensitivity] = "Private"; break;

                    case 3: message.Headers[HeaderId.Sensitivity] = "Company-Confidential"; break;

                    case 0: message.Headers.Remove(HeaderId.Sensitivity); break;
                    }
                    break;
                }
            }

            if (string.IsNullOrEmpty(message.Subject) && !string.IsNullOrEmpty(normalizedSubject))
            {
                if (!string.IsNullOrEmpty(subjectPrefix))
                {
                    message.Subject = subjectPrefix + normalizedSubject;
                }
                else
                {
                    message.Subject = normalizedSubject;
                }
            }

            if (sender.TryGetMailboxAddress(out mailbox))
            {
                message.From.Add(mailbox);
            }

            if (recipient.TryGetMailboxAddress(out mailbox))
            {
                message.To.Add(mailbox);
            }
        }
示例#30
0
        private async Task SendAsyncInternal(EmailMessage message, string emailType, bool enableNotification)
        {
            if (enableNotification)
            {
                var notification = new SendEmailNotification(message.ToNotificationEmail(_globalSettings.Smtp?.From), emailType);
                await _eventAggregator.PublishAsync(notification);

                // if a handler handled sending the email then don't continue.
                if (notification.IsHandled)
                {
                    _logger.LogDebug("The email sending for {Subject} was handled by a notification handler", notification.Message.Subject);
                    return;
                }
            }

            if (!_globalSettings.IsSmtpServerConfigured && !_globalSettings.IsPickupDirectoryLocationConfigured)
            {
                _logger.LogDebug("Could not send email for {Subject}. It was not handled by a notification handler and there is no SMTP configured.", message.Subject);
                return;
            }

            if (_globalSettings.IsPickupDirectoryLocationConfigured && !string.IsNullOrWhiteSpace(_globalSettings.Smtp?.From))
            {
                // The following code snippet is the recommended way to handle PickupDirectoryLocation.
                // See more https://github.com/jstedfast/MailKit/blob/master/FAQ.md#q-how-can-i-send-email-to-a-specifiedpickupdirectory
                do
                {
                    var    path = Path.Combine(_globalSettings.Smtp?.PickupDirectoryLocation, Guid.NewGuid() + ".eml");
                    Stream stream;

                    try
                    {
                        stream = File.Open(path, FileMode.CreateNew);
                    }
                    catch (IOException)
                    {
                        if (File.Exists(path))
                        {
                            continue;
                        }
                        throw;
                    }

                    try {
                        using (stream)
                        {
                            using var filtered = new FilteredStream(stream);
                            filtered.Add(new SmtpDataFilter());

                            FormatOptions options = FormatOptions.Default.Clone();
                            options.NewLineFormat = NewLineFormat.Dos;

                            await message.ToMimeMessage(_globalSettings.Smtp?.From).WriteToAsync(options, filtered);

                            filtered.Flush();
                            return;
                        }
                    } catch {
                        File.Delete(path);
                        throw;
                    }
                } while (true);
            }

            using var client = new SmtpClient();

            await client.ConnectAsync(_globalSettings.Smtp.Host,
                                      _globalSettings.Smtp.Port,
                                      (MailKit.Security.SecureSocketOptions)(int) _globalSettings.Smtp.SecureSocketOptions);

            if (!string.IsNullOrWhiteSpace(_globalSettings.Smtp.Username) && !string.IsNullOrWhiteSpace(_globalSettings.Smtp.Password))
            {
                await client.AuthenticateAsync(_globalSettings.Smtp.Username, _globalSettings.Smtp.Password);
            }

            var mailMessage = message.ToMimeMessage(_globalSettings.Smtp.From);

            if (_globalSettings.Smtp.DeliveryMethod == SmtpDeliveryMethod.Network)
            {
                await client.SendAsync(mailMessage);
            }
            else
            {
                client.Send(mailMessage);
            }

            await client.DisconnectAsync(true);
        }
示例#31
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.");
                }
            }
        }