Example #1
0
        public async Task SendSingle()
        {
            var responseMessages  = @"250 Ok (MAIL)
250 Ok (RCPT)
354 End data with <CR><LF>.<CR><LF> (DATA)
250 Ok (DATA with .)
250 Bye (QUIT)
";
            var mockMailReference = new MockMailReference(
                "mock-1",
                "*****@*****.**",
                new[] { "*****@*****.**" }.ToImmutableList(),
                true,
                "Some text",
                _queue);

            _queue.References.Add(mockMailReference);

            using (var outStream = new MemoryStream())
                using (var inStream = new MemoryStream(Encoding.ASCII.GetBytes(responseMessages)))
                    using (var reader = new StreamReader(inStream))
                        using (var writer = new StreamWriter(outStream))
                        {
                            Assert.True(await _transfer.TrySendSingleMailAsync(mockMailReference, writer, reader, CancellationToken.None));
                        }

            Assert.Equal(0, _queue.References.Count);
            Assert.Equal(1, _queue.DeletedReferences.Count);
        }
Example #2
0
        public async Task BasicFailedConversation()
        {
            var responseMessages  = @"554 No clue
554 No clue
";
            var mockMailReference = new MockMailReference(
                "mock-1",
                "*****@*****.**",
                new[] { "*****@*****.**" }.ToImmutableList(),
                true,
                "Some text",
                _queue);

            _queue.References.Add(mockMailReference);

            using (var outStream = new MemoryStream())
                using (var inStream = new MemoryStream(Encoding.ASCII.GetBytes(responseMessages)))
                    using (var reader = new StreamReader(inStream))
                        using (var writer = new StreamWriter(outStream))
                        {
                            Assert.False(await _transfer.TrySendSingleMailAsync(mockMailReference, writer, reader, CancellationToken.None));
                        }

            Assert.Equal(1, _queue.References.Count);
            Assert.Equal(0, _queue.DeletedReferences.Count);
        }
Example #3
0
        public async Task LookupWithFallback_FailedAll()
        {
            var mockMailReference = new MockMailReference(
                "mock-1",
                "*****@*****.**",
                new[] { "*****@*****.**" }.ToImmutableList(),
                true,
                "Some text",
                _queue);

            _queue.References.Add(mockMailReference);
            _dns.AddMx("example.com", "first.example.com", 10);
            _dns.AddIp("first.example.com", IPAddress.Parse("10.0.0.1"));

            Task executeTask = Task.Run(
                () => _transfer.SendMailsToDomain("example.com", new[] { mockMailReference }, CancellationToken.None));

            MockTcpConnectionProvider.MockTcpClient client = await GetClientFor(IPAddress.Parse("10.0.0.1"));
            await WriteToAsync(
                client.HalfStream,
                @"554 Failed
554 Failed
");

            await executeTask;

            Assert.Equal(1, _queue.References.Count);
            Assert.Equal(0, _queue.DeletedReferences.Count);

            SmtpFailureData failure = _failures.GetFailure("mock-1", false);

            Assert.NotNull(failure);
            Assert.Equal(1, failure.Retries);
            Assert.InRange(failure.FirstFailure, DateTimeOffset.UtcNow - TimeSpan.FromSeconds(1), DateTime.UtcNow);
        }
Example #4
0
        public async Task AuthenticatedLargeMessageAccepted()
        {
            var expectedBody = "From:[email protected]\r\n\r\nFirst Line\r\nSecond Line\r\n";

            (MockMailQueue queue, MockMailBuilder builder, MockSmtpChannel channel, DataCommand command) = Prepare(
                expectedBody + ".\r\n",
                TestHelpers.MakeSettings(unauthenticatedMessageSizeLimit: 1));

            channel.AuthenticatedUser = new UserData("*****@*****.**");

            builder.PendingMail = new SmtpMailMessage(new SmtpPath("*****@*****.**"))
            {
                Recipents = { "*****@*****.**" }
            };
            await command.ExecuteAsync(CancellationToken.None);

            Assert.Equal(2, channel.Entries.Count);
            SmtpTestHelper.AssertResponse(channel.Entries[0], SmtpReplyCode.StartMail);
            SmtpTestHelper.AssertResponse(channel.Entries[1], SmtpReplyCode.Okay);
            Assert.Equal(1, queue.References.Count);
            MockMailReference mailReference = queue.References[0];

            Assert.True(mailReference.IsSaved);
            Assert.Equal("*****@*****.**", mailReference.Sender);
            SequenceAssert.SameSet(new[] { "*****@*****.**" }, mailReference.Recipients);
            Assert.Throws <ObjectDisposedException>(() => mailReference.BodyStream.WriteByte(1));
            string mailBody = Encoding.UTF8.GetString(mailReference.BackupBodyStream.ToArray());

            Assert.EndsWith(expectedBody, mailBody);
            Assert.StartsWith("Received:", mailBody);
            Assert.Null(builder.PendingMail);
        }
Example #5
0
        public async Task InternalSenderCanSendAnywhere()
        {
            var body = "My body\nNext Line";

            _queue.References.Add(
                new MockMailReference(
                    "ext-mail",
                    "*****@*****.**",
                    new[] { "*****@*****.**" }.ToImmutableList(),
                    true,
                    body,
                    _queue));

            await _dispatcher.ProcessAllMailReferencesAsync(CancellationToken.None);

            Assert.Empty(_queue.References);
            Assert.Equal(1, _queue.DeletedReferences.Count);
            Assert.Equal(1, _transfer.References.Count(r => r.IsSaved));
            string newBody;

            using (MockMailReference reference = _transfer.References.FirstOrDefault(r => r.IsSaved))
            {
                Assert.NotNull(reference);
                Assert.Equal("*****@*****.**", reference.Sender);
                SequenceAssert.SameSet(new[] { "*****@*****.**" }, reference.Recipients);
                newBody = await StreamUtility.ReadAllFromStreamAsync(reference.BackupBodyStream);
            }

            Assert.Equal(body, newBody);
            Assert.Empty(_mailbox.References);
        }
Example #6
0
        public async Task ProcessAll_EhloStartTlsTest_NotTrusted()
        {
            var responseMessagesPreEncrypt = @"220-STARTTLS
220 example.com greets test.example.com (EHLO)
250 Ok, begin encryption (STARTTLS)
";
            var mockMailReference          = new MockMailReference(
                "mock-1",
                "*****@*****.**",
                new[] { "*****@*****.**" }.ToImmutableList(),
                true,
                "Some text",
                _queue);

            _queue.References.Add(mockMailReference);
            _dns.AddMx("external.example.com", "test.example.com", 10);
            _dns.AddIp("test.example.com", IPAddress.Parse("10.20.30.40"));

            (Stream keep, Stream give) = PairedStream.Create();

            using (var recieveStream = new RedirectableStream(keep))
                using (var reader = new StreamReader(recieveStream))
                {
                    Task <IReadOnlyList <IMailReference> > sendMailsTask = Task.Run(
                        () => _transfer.TrySendMailsToStream(
                            "external.example.com",
                            new[] { mockMailReference },
                            // ReSharper disable once AccessToDisposedClosure
                            new UnclosableStream(give),
                            CancellationToken.None));

                    _transfer.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => false;

                    byte[] responseBytes = Encoding.ASCII.GetBytes(responseMessagesPreEncrypt);
                    await keep.WriteAsync(responseBytes, 0, responseBytes.Length);

                    await AssertCommandRecieved(reader, "EHLO");
                    await AssertCommandRecieved(reader, "STARTTLS");

                    var encrypted = new SslStream(keep);

                    await encrypted.AuthenticateAsServerAsync(TestHelpers.GetSelfSigned());

                    Assert.NotEmpty(await sendMailsTask);

                    Assert.Equal(1, _queue.References.Count);
                    Assert.Equal(0, _queue.DeletedReferences.Count);

                    encrypted.Dispose();
                    keep.Dispose();
                    give.Dispose();
                }
        }
Example #7
0
        public async Task LookupWithFallback()
        {
            var mockMailReference = new MockMailReference(
                "mock-1",
                "*****@*****.**",
                new[] { "*****@*****.**" }.ToImmutableList(),
                true,
                "Some text",
                _queue);

            _queue.References.Add(mockMailReference);
            _dns.AddMx("example.com", "second.example.com", 20);
            _dns.AddMx("example.com", "first.example.com", 10);
            _dns.AddMx("example.com", "third.example.com", 30);

            _dns.AddIp("first.example.com", IPAddress.Parse("10.0.0.1"));
            _dns.AddIp("second.example.com", IPAddress.Parse("10.0.0.2"));
            _dns.AddIp("third.example.com", IPAddress.Parse("10.0.0.3"));

            Task executeTask = Task.Run(
                () => _transfer.SendMailsToDomain("example.com", new[] { mockMailReference }, CancellationToken.None));

            MockTcpConnectionProvider.MockTcpClient client = await GetClientFor(IPAddress.Parse("10.0.0.1"));
            await WriteToAsync(
                client.HalfStream,
                @"554 Failed
554 Failed
");

            client = await GetClientFor(IPAddress.Parse("10.0.0.2"));
            await WriteToAsync(
                client.HalfStream,
                @"554 Failed
554 Failed
");

            client = await GetClientFor(IPAddress.Parse("10.0.0.3"));
            await WriteToAsync(
                client.HalfStream,
                @"220 example.com greets test.example.com (HELO)
250 Ok (MAIL)
250 Ok (RCPT)
354 End data with <CR><LF>.<CR><LF> (DATA)
250 Ok (DATA with .)
250 Bye (QUIT)
");

            await executeTask;

            Assert.Equal(0, _queue.References.Count);
            Assert.Equal(1, _queue.DeletedReferences.Count);
        }
Example #8
0
        public async Task ProcessAll_NoEhloTest()
        {
            var responseMessages  = @"554 No clue (EHLO)
220 example.com greets test.example.com (HELO)
250 Ok (MAIL)
250 Ok (RCPT)
354 End data with <CR><LF>.<CR><LF> (DATA)
250 Ok (DATA with .)
250 Bye (QUIT)
";
            var mockMailReference = new MockMailReference(
                "mock-1",
                "*****@*****.**",
                new[] { "*****@*****.**" }.ToImmutableList(),
                true,
                "Some text",
                _queue);

            _queue.References.Add(mockMailReference);
            _dns.AddMx("external.example.com", "mx.external.example.com", 10);
            _dns.AddIp("mx.external.example.com", IPAddress.Parse("10.20.30.40"));

            (Stream keep, Stream give) = PairedStream.Create();
            using (var reader = new StreamReader(keep))
            {
                byte[] responseBytes = Encoding.ASCII.GetBytes(responseMessages);
                await keep.WriteAsync(responseBytes, 0, responseBytes.Length);

                Assert.Empty(
                    await _transfer.TrySendMailsToStream(
                        "external.example.com",
                        new[] { mockMailReference },
                        new UnclosableStream(give),
                        CancellationToken.None));

                Assert.Equal(0, _queue.References.Count);
                Assert.Equal(1, _queue.DeletedReferences.Count);
                await AssertCommandRecieved(reader, "EHLO");
                await AssertCommandRecieved(reader, "HELO");
                await AssertCommandRecieved(reader, "MAIL");
                await AssertCommandRecieved(reader, "RCPT");
                await AssertCommandRecieved(reader, "DATA");

                give.Dispose();
            }
        }
Example #9
0
        public async Task TooLargeMailRejected()
        {
            var expectedBody = "From:[email protected]\r\n\r\nFirst Line\r\nSecond Line\r\n";

            (MockMailQueue queue, MockMailBuilder builder, MockSmtpChannel channel, DataCommand command) = Prepare(
                expectedBody + ".\r\n",
                TestHelpers.MakeSettings(unauthenticatedMessageSizeLimit: 1));

            builder.PendingMail = new SmtpMailMessage(new SmtpPath("*****@*****.**"))
            {
                Recipents = { "*****@*****.**" }
            };
            await command.ExecuteAsync(CancellationToken.None);

            Assert.Equal(2, channel.Entries.Count);
            SmtpTestHelper.AssertResponse(channel.Entries[0], SmtpReplyCode.StartMail);
            SmtpTestHelper.AssertResponse(channel.Entries[1], SmtpReplyCode.ExceededQuota);
            Assert.Equal(1, queue.References.Count);
            MockMailReference mailReference = queue.References[0];

            Assert.False(mailReference.IsSaved);
            Assert.Throws <ObjectDisposedException>(() => mailReference.BodyStream.WriteByte(1));
            Assert.Null(builder.PendingMail);
        }