예제 #1
0
        public void TestStartTLS()
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                var             args         = new CancelEventArgs();
                CancelEventArgs actualArgs   = null;
                object          actualSender = null;
                var             called       = false;

                transaction.OnStartTLS += (sender, eventArgs) =>
                {
                    called       = true;
                    actualSender = sender;
                    actualArgs   = eventArgs;
                };

                transaction.StartTLS(args);

                Assert.True(called);
                Assert.Same(transaction, actualSender);
                Assert.Same(args, actualArgs);
            }
        }
예제 #2
0
        public void TestSetAndGetProperty(bool permanent)
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                const int    value1 = 5;
                const string value2 = "foo";
                const bool   value3 = false;
                var          value4 = new object();

                transaction.SetProperty("foo", value1, permanent);
                var actualValue1 = transaction.GetProperty <int>("foo");
                Assert.Equal(value1, actualValue1);

                transaction.SetProperty("foo", value2, permanent);
                var actualValue2 = transaction.GetProperty <string>("foo");
                Assert.Equal(value2, actualValue2);

                transaction.SetProperty("foo", value3, permanent);
                var actualValue3 = transaction.GetProperty <bool>("foo");
                Assert.Equal(value3, actualValue3);

                transaction.SetProperty("foo", value4, permanent);
                var actualValue4 = transaction.GetProperty <object>("foo");
                Assert.Equal(value4, actualValue4);
            }
        }
예제 #3
0
        public override SMTPResponse DoExecute(SMTPTransaction transaction, string parameters)
        {
            if (!string.IsNullOrEmpty(parameters))
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            if (!transaction.Settings.EnableTLS)
            {
                return(new SMTPResponse(SMTPStatusCode.BadSequence)); // TODO: Check response code
            }

            if (transaction.TLSActive)
            {
                return(new SMTPResponse(SMTPStatusCode.BadSequence));
            }

            var args = new CancelEventArgs();

            transaction.StartTLS(args);

            if (args.Cancel)
            {
                return(new SMTPResponse(SMTPStatusCode.TLSNotAvailiable, "TLS not available due to temporary reason"));
            }

            return(new SMTPResponse(SMTPStatusCode.Ready, "Ready to start TLS"));
        }
예제 #4
0
        public void TestDataHandler(string line)
        {
            using (ShimsContext.Create())
            {
                SMTPTransaction actualTransaction = null;
                string          decodedReponse    = null;
                IAuthMethod     actualAuthMethod  = null;
                var             expectedResponse  = new SMTPResponse(SMTPStatusCode.Okay);

                ShimAUTHHandler.HandleResponseSMTPTransactionStringIAuthMethod = (transaction, data, authMethod) =>
                {
                    actualTransaction = transaction;
                    decodedReponse    = data;
                    actualAuthMethod  = authMethod;

                    return(expectedResponse);
                };

                var method  = new StubIAuthMethod();
                var encoded = Convert.ToBase64String(Encoding.ASCII.GetBytes(line));

                var response = AUTHHandler.DataHandler(Transaction, encoded, method);

                Assert.Same(method, actualAuthMethod);
                Assert.Same(expectedResponse, response);
                Assert.Equal(Transaction, actualTransaction);
                Assert.Equal(line, decodedReponse);
            }
        }
예제 #5
0
        public void TestHandleResponseFailure(string errorMessage)
        {
            const string expectedData = "Test Data";

            using (ShimsContext.Create())
            {
                SMTPTransaction actualTransaction = null;
                string          decodedReponse    = null;
                var             authMethod        = new StubIAuthMethod
                {
                    ProcessResponseSMTPTransactionStringStringOut =
                        (SMTPTransaction transaction, string data, out string c) =>
                    {
                        actualTransaction = transaction;
                        decodedReponse    = data;

                        c = errorMessage;
                        return(false);
                    }
                };
                var response = AUTHHandler.HandleResponse(Transaction, expectedData, authMethod);

                Assert.Equal(SMTPStatusCode.AuthFailed, response.Code);
                if (errorMessage != null)
                {
                    Assert.Equal(1, response.Args.Length);
                    Assert.Equal(errorMessage, response.Args[0]);
                }
                Assert.Equal(Transaction, actualTransaction);
                Assert.Equal(expectedData, decodedReponse);
            }
        }
예제 #6
0
        public void TestLineCallback()
        {
            const string greet        = "Test Greet";
            const string expectedLine = "fubar";

            var handler = new EHLOHandler();

            SMTPTransaction actualTransaction = null;

            AddCoreListProperty("EHLOLines", () => new List <Func <SMTPTransaction, string> >
            {
                t =>
                {
                    actualTransaction = t;
                    return(expectedLine);
                }
            });

            Transaction.InitializeString = s => { };
            Transaction.Reset            = () => { };
            Transaction.SettingsGet      = () => new StubIReceiveSettings
            {
                GreetGet = () => greet
            };

            handler.Initialize(Core);

            var response = handler.Execute(Transaction, "test");

            Assert.Equal(SMTPStatusCode.Okay, response.Code);
            Assert.Equal(2, response.Args.Length);
            Assert.Equal(greet, response.Args[0]);
            Assert.Equal(expectedLine, response.Args[1]);
            Assert.Equal(Transaction, actualTransaction);
        }
예제 #7
0
        public void TestGetListProperty(bool permanent)
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                var list = transaction.GetListProperty <string>("foo", permanent);

                Assert.NotNull(list);
                Assert.Empty(list);

                list.Add("fubar");

                list = transaction.GetListProperty <string>("foo", permanent);

                Assert.NotNull(list);
                Assert.Contains("fubar", list);

                transaction.SetProperty("foo", null, permanent);

                list = transaction.GetListProperty <string>("foo", permanent);

                Assert.NotNull(list);
                Assert.Empty(list);
            }
        }
예제 #8
0
        public void TestTriggerNewMessage()
        {
            var core     = new SMTPServer(DefaultLoader());
            var settings = new StubIReceiveSettings();

            var expectedTransaction = new StubSMTPTransaction(core, settings);
            var expectedSender      = new MailPath("tester", "test.de");
            var expectedRecipients  = new[] { new MailPath("fubar", "fu.com") };
            var expectedBody        = "Test";

            SMTPTransaction actualTransaction = null;
            Mail            actualMail        = null;
            var             triggered         = false;

            core.OnNewMessage += (transaction, mail) =>
            {
                triggered         = true;
                actualTransaction = transaction;
                actualMail        = mail;
            };

            core.TriggerNewMessage(expectedTransaction, expectedSender, expectedRecipients, expectedBody);

            // TODO: Remove dependencies of test

            Assert.True(triggered);
            Assert.Equal(expectedTransaction, actualTransaction);
            Assert.Equal(expectedSender.ToMailAdress(), actualMail.From);
            Assert.Equal(expectedRecipients.Select(r => r.ToMailAdress().ToString()).ToArray(),
                         actualMail.Recipients.Select(r => r.ToString()).ToArray());
            Assert.Equal(expectedBody, actualMail.Body);
        }
예제 #9
0
        public void TestStartTransactionValidationSuccess()
        {
            var core = new SMTPServer(DefaultLoader());

            var ip = IPAddress.Parse("127.0.0.1");

            SMTPTransaction actualTransaction = null;
            IPAddress       actualIP          = null;

            core.OnConnect += (transaction, args) =>
            {
                actualTransaction = transaction;
                actualIP          = args.IP;
            };

            SMTPTransaction expectedTransaction;
            SMTPResponse    reponse;

            using (ShimsContext.Create())
            {
                var settings = new StubIReceiveSettings();

                expectedTransaction = core.StartTransaction(ip, settings, out reponse);
            }

            Assert.Equal(SMTPStatusCode.Ready, reponse.Code);
            Assert.Same(expectedTransaction, actualTransaction);
            Assert.Same(ip, actualIP);
        }
예제 #10
0
        public static SMTPResponse DataHandler(SMTPTransaction transaction, string reponse, IAuthMethod method)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException();
            }
            if (reponse == null)
            {
                throw new ArgumentNullException();
            }
            if (method == null)
            {
                throw new ArgumentNullException();
            }

            if (reponse.Equals("*"))
            {
                method.Abort(transaction);
                return(new SMTPResponse(SMTPStatusCode.ParamError));
            }

            string decoded;

            try
            {
                decoded = Base64Decode(reponse);
            }
            catch (FormatException)
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            return(HandleResponse(transaction, decoded, method));
        }
예제 #11
0
        public bool ProcessResponse(SMTPTransaction transaction, string response, out string challenge)
        {
            if (string.IsNullOrEmpty(response))
            {
                challenge = null;
                return(false);
            }

            var parts = response.Split('\0');

            if (parts.Length != 3)
            {
                challenge = null;
                return(false);
            }

            var username = parts[1];
            var password = parts[2];

            transaction.SetProperty("Username", username, true);
            transaction.SetProperty("Password", password, true);

            challenge = null;

            // TODO
            // var password = response;
            // var username = transaction.GetProperty<string>("Username");

            return(true);
        }
예제 #12
0
        public static SMTPResponse DataHandler(SMTPTransaction transaction, string data)
        {
            transaction.Server.TriggerNewMessage(transaction, transaction.GetProperty <MailPath>("ReversePath"),
                                                 transaction.GetListProperty <MailPath>("ForwardPath").ToArray(), data);

            transaction.Reset();

            return(new SMTPResponse(SMTPStatusCode.Okay));
        }
예제 #13
0
        public void TestOnExecuteTrigger(bool overwriteReponse)
        {
            const string    expectedParams    = "fu bar";
            SMTPTransaction actualTransaction = null;
            string          actualParams      = null;
            var             responseA         = new SMTPResponse(SMTPStatusCode.Okay);
            var             responseB         = new SMTPResponse(SMTPStatusCode.TransactionFailed);
            var             expectedResponse  = overwriteReponse ? responseB : responseA;

            var handler = new StubCommandHandlerBase
            {
                DoExecuteSMTPTransactionString = (transaction, s) =>
                {
                    actualTransaction = transaction;
                    actualParams      = s;

                    return(responseA);
                }
            };

            object          actualSender     = null;
            string          eventParams      = null;
            SMTPTransaction eventTransaction = null;
            ICommandHandler eventHandler     = null;
            SMTPResponse    eventResponse    = null;

            handler.OnExecute += (sender, args) =>
            {
                actualSender     = sender;
                eventParams      = args.Parameters;
                eventTransaction = args.Transaction;
                eventHandler     = args.Handler;
                eventResponse    = args.Response;

                if (overwriteReponse)
                {
                    args.Response = responseB;
                }
            };

            var response = handler.Execute(Transaction, expectedParams);

            if (!overwriteReponse)
            {
                Assert.Equal(expectedParams, actualParams);
                Assert.Equal(Transaction, actualTransaction);
            }


            Assert.Same(expectedResponse, response);

            Assert.Same(handler, actualSender);
            Assert.Equal(Transaction, eventTransaction);
            Assert.Equal(expectedParams, eventParams);
            Assert.Equal(handler, eventHandler);
            Assert.Null(eventResponse);
        }
예제 #14
0
        public override SMTPResponse DoExecute(SMTPTransaction transaction, string parameters)
        {
            if (!string.IsNullOrWhiteSpace(parameters))
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            transaction.Reset();
            return(new SMTPResponse(SMTPStatusCode.Okay));
        }
예제 #15
0
        private void RefreshTransaction()
        {
            SMTPResponse response;

            _transaction.OnClose -= OnCloseHandler;
            _transaction.Close();
            _transaction = _smtpServer.SMTPServer.StartTransaction(_remoteEndpoint.Address, _smtpServer.Settings,
                                                                   out response);
            _transaction.TLSActive = true;
            _transaction.OnClose  += OnCloseHandler;
        }
예제 #16
0
        public override SMTPResponse DoExecute(SMTPTransaction transaction, string parameters)
        {
            if (string.IsNullOrWhiteSpace(parameters))
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            transaction.Reset();
            transaction.Initialize(parameters);

            return(new SMTPResponse(SMTPStatusCode.Okay, transaction.Settings.Greet));
        }
예제 #17
0
        private void SMTPServerOnOnConnect(SMTPTransaction transaction, SMTPServer.ConnectEventArgs connect)
        {
            if (Connector.RemoteIPRanges.Any() && !Connector.RemoteIPRanges.Any(range => range.Contains(connect.IP)))
            {
                connect.Cancel = true;
            }

            if (_greylistingManager.IsGreylisted(connect.IP))
            {
                connect.Cancel       = true;
                connect.ResponseCode = SMTPStatusCode.NotAvailiable;
            }
        }
예제 #18
0
        public void TestNonDataModeError()
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                Assert.False(transaction.InDataMode);
                Assert.Throws <InvalidOperationException>(() => transaction.HandleData(""));
                Assert.Throws <InvalidOperationException>(() => transaction.HandleDataLine("", new StringBuilder()));
            }
        }
예제 #19
0
        public void TestGetNonExistantProperty()
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                Assert.Equal(default(int), transaction.GetProperty <int>("nonExistant"));
                Assert.Equal(default(bool), transaction.GetProperty <bool>("nonExistant"));
                Assert.Equal(default(string), transaction.GetProperty <string>("nonExistant"));
            }
        }
예제 #20
0
        public override SMTPResponse DoExecute(SMTPTransaction transaction, string parameters)
        {
            if (string.IsNullOrEmpty(parameters))
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            var parts = parameters.Split(' ');

            if (parts.Length > 2)
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            if (transaction.GetProperty <bool>("Authenticated"))
            {
                return(new SMTPResponse(SMTPStatusCode.BadSequence));
            }

            IAuthMethod method;

            if (!_authMethods.TryGetValue(parts[0].ToUpperInvariant(), out method))
            {
                return(new SMTPResponse(SMTPStatusCode.ParamNotImplemented));
            }

            string initialResponse = null;

            if (parts.Length > 1)
            {
                if (parts[1].Equals("="))
                {
                    initialResponse = string.Empty;
                }
                else
                {
                    try
                    {
                        initialResponse = Base64Decode(parts[1]);
                    }
                    catch (FormatException)
                    {
                        return(new SMTPResponse(SMTPStatusCode.SyntaxError));
                    }
                }
            }

            return(HandleResponse(transaction, initialResponse, method));
        }
예제 #21
0
        public void TestExecuteFail()
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                server.GetHandlerString = s => null;

                var response = transaction.ExecuteCommand(new SMTPCommand("NonExistentCommand", "Params"));

                Assert.Equal(SMTPStatusCode.SyntaxError, response.Code);
            }
        }
예제 #22
0
        public void TestConstructor()
        {
            using (ShimsContext.Create())
            {
                var server   = new ShimSMTPServer();
                var settings = new StubIReceiveSettings();

                var transaction = new SMTPTransaction(server, settings);

                Assert.Same(server.Instance, transaction.Server);
                Assert.Same(settings, transaction.Settings);
                Assert.False(transaction.InDataMode);
                Assert.False(transaction.Initialized);
            }
        }
예제 #23
0
        public SMTPResponse Execute(SMTPTransaction transaction, string parameters)
        {
            var args = new CommandExecuteEventArgs(transaction, this, parameters);

            if (OnExecute != null)
            {
                OnExecute(this, args);
            }

            if (args.Response != null)
            {
                return(args.Response);
            }

            return(DoExecute(transaction, parameters));
        }
예제 #24
0
        public void TestHandleResponseSuccess()
        {
            const string    expectedData      = "Test Data";
            SMTPTransaction actualTransaction = null;
            string          decodedReponse    = null;
            var             authenticated     = false;
            var             permanent         = false;

            using (ShimsContext.Create())
            {
                Transaction.SetPropertyStringObjectBoolean = (name, value, p) =>
                {
                    switch (name)
                    {
                    case "Authenticated":
                        authenticated = (bool)value;
                        permanent     = p;
                        break;

                    default:
                        throw new InvalidOperationException("The name is invalid.");
                    }
                };

                var authMethod = new StubIAuthMethod
                {
                    ProcessResponseSMTPTransactionStringStringOut =
                        (SMTPTransaction transaction, string data, out string challenge) =>
                    {
                        actualTransaction = transaction;
                        decodedReponse    = data;

                        challenge = null;
                        return(true);
                    }
                };

                var response = AUTHHandler.HandleResponse(Transaction, expectedData, authMethod);

                Assert.Equal(SMTPStatusCode.AuthSuccess, response.Code);
                Assert.Equal(Transaction, actualTransaction);
                Assert.Equal(expectedData, decodedReponse);
                Assert.True(authenticated);
                Assert.True(permanent);
            }
        }
예제 #25
0
        public void TestResetDataMode()
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                Assert.False(transaction.InDataMode);

                transaction.StartDataMode((s, builder) => false, s => new SMTPResponse(SMTPStatusCode.Okay));
                Assert.True(transaction.InDataMode);

                transaction.Reset();
                Assert.False(transaction.InDataMode);
            }
        }
예제 #26
0
        public void TestInitialize()
        {
            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                const string clientId = "ClientID";

                Assert.False(transaction.Initialized);

                transaction.Initialize(clientId);

                Assert.True(transaction.Initialized);
                Assert.Equal(clientId, transaction.ClientIdentifier);
            }
        }
예제 #27
0
        public override SMTPResponse DoExecute(SMTPTransaction transaction, string parameters)
        {
            if (!string.IsNullOrEmpty(parameters))
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            var forwardPath = transaction.GetListProperty <MailPath>("ForwardPath");

            if (!transaction.GetProperty <bool>("MailInProgress") || forwardPath == null || !forwardPath.Any())
            {
                return(new SMTPResponse(SMTPStatusCode.BadSequence));
            }

            transaction.StartDataMode(DataLineHandler, data => DataHandler(transaction, data));

            return(new SMTPResponse(SMTPStatusCode.StartMailInput));
        }
예제 #28
0
        public override SMTPResponse DoExecute(SMTPTransaction transaction, string parameters)
        {
            if (string.IsNullOrWhiteSpace(parameters))
            {
                return(new SMTPResponse(SMTPStatusCode.SyntaxError));
            }

            transaction.Reset();
            transaction.Initialize(parameters);

            var ehlos = Server.GetListProperty <Func <SMTPTransaction, string> >("EHLOLines");
            var l     = new List <string> {
                transaction.Settings.Greet
            };

            l.AddRange(ehlos.Select(e => e(transaction)).Where(e => !string.IsNullOrEmpty(e)));

            return(new SMTPResponse(SMTPStatusCode.Okay, l.ToArray()));
        }
예제 #29
0
        public void TestExecuteSuccess()
        {
            const string command          = "Test";
            var          expectedResponse = new SMTPResponse(SMTPStatusCode.NotAvailiable, "Fu", "bar");
            const string expectedParams   = "Fubar blubb";

            using (ShimsContext.Create())
            {
                var server      = new ShimSMTPServer();
                var settings    = new StubIReceiveSettings();
                var transaction = new SMTPTransaction(server, settings);

                SMTPTransaction actualTransaction = null;
                string          actualParams      = null;

                var handler = new StubICommandHandler
                {
                    ExecuteSMTPTransactionString = (smtpTransaction, s) =>
                    {
                        actualTransaction = smtpTransaction;
                        actualParams      = s;

                        return(expectedResponse);
                    }
                };

                server.GetHandlerString = s =>
                {
                    if (s.Equals(command, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return(handler);
                    }
                    throw new InvalidOperationException("Invalid name.");
                };

                var response = transaction.ExecuteCommand(new SMTPCommand(command, expectedParams));

                Assert.Same(expectedResponse, response);
                Assert.Equal(expectedParams, actualParams);
                Assert.Same(transaction, actualTransaction);
            }
        }
예제 #30
0
        public static SMTPResponse HandleResponse(SMTPTransaction transaction, string decodedReponse, IAuthMethod method)
        {
            string challenge;

            if (!method.ProcessResponse(transaction, decodedReponse, out challenge))
            {
                return(new SMTPResponse(SMTPStatusCode.AuthFailed, challenge != null ? new[] { challenge } : new string[0]));
            }

            if (challenge != null)
            {
                transaction.StartDataMode(DataLineHandler, s => DataHandler(transaction, s, method));

                return(new SMTPResponse(SMTPStatusCode.AuthContinue, Base64Encode(challenge)));
            }

            transaction.SetProperty("Authenticated", true, true);

            return(new SMTPResponse(SMTPStatusCode.AuthSuccess));
        }