Exemplo n.º 1
0
        public void ReadMessageTest()
        {
            var responses = new string[] {
                "From: \"Bob Example\" < *****@*****.** >",
                "To: \"Alice Example\" < *****@*****.** >",
                "Cc: theboss @example.com",
                "Date: Tue, 15 January 2008 16:02:43 - 0500",
                "Subject: Test message",
                "",
                "Hello Alice.",
                "This is a test message with 5 header fields and 4 lines in the message body.",
                "Your friend,",
                "Bob",
                "."
            };

            SetResponses(responses);

            var provider = new MailMessageReadProvider();

            var context = new SmtpSessionContext()
            {
                Transport = _transportMock.Object
            };

            var result = provider.RunAsync(context).Result as MessageProcessingResult;

            Assert.IsNotNull(result);
        }
Exemplo n.º 2
0
        public void Setup()
        {
            SmtpSessionContext context       = new SmtpSessionContext();
            Mock <ITransport>  transportMock = new Mock <ITransport>(MockBehavior.Loose);

            _handshakeProviderMock = CreateProvider(context, new Result {
                StatusCode = SmtpStatusCode.OK
            });
            _senderValidationProviderMock = CreateProvider(context, new Result {
                StatusCode = SmtpStatusCode.OK
            });
            _recipientValidationProviderMock = CreateProvider(context, new Result {
                StatusCode = SmtpStatusCode.OK
            });
            _messageHandlerMock = CreateProvider(context, new Result {
                StatusCode = SmtpStatusCode.OK
            });
            _authProviderMock = CreateProvider(context, new Result {
                StatusCode = SmtpStatusCode.OK
            });


            _session = new SmtpSession(transportMock.Object)
            {
                HandshakeProvider           = _handshakeProviderMock.Object,
                SenderValidationProvider    = _senderValidationProviderMock.Object,
                RecipientValidationProvider = _recipientValidationProviderMock.Object,
                MessageReaderProvider       = _messageHandlerMock.Object,
                AuthProvider = _authProviderMock.Object
            };

            _session.StartSession().Wait();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task which asynchronously performs the execution.</returns>
        internal override async Task ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            switch (Method)
            {
            case AuthenticationMethod.Plain:
                if (await TryPlainAsync(context, cancellationToken).ReturnOnAnyThread() == false)
                {
                    await context.Client.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ReturnOnAnyThread();

                    return;
                }
                break;

            case AuthenticationMethod.Login:
                if (await TryLoginAsync(context, cancellationToken).ReturnOnAnyThread() == false)
                {
                    await context.Client.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ReturnOnAnyThread();

                    return;
                }
                break;
            }

            if (await Options.UserAuthenticator.AuthenticateAsync(_user, _password).ReturnOnAnyThread() == false)
            {
                await context.Client.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ReturnOnAnyThread();

                return;
            }

            await context.Client.ReplyAsync(SmtpResponse.AuthenticationSuccessful, cancellationToken).ReturnOnAnyThread();

            context.RaiseSessionAuthenticated();
        }
Exemplo n.º 4
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task which asynchronously performs the execution.</returns>
        internal override async Task ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            if (context.Transaction.To.Count == 0)
            {
                await context.Client.ReplyAsync(SmtpResponse.NoValidRecipientsGiven, cancellationToken).ConfigureAwait(false);

                return;
            }

            await context.Client.ReplyAsync(new SmtpResponse(SmtpReplyCode.StartMailInput, "end with <CRLF>.<CRLF>"), cancellationToken).ConfigureAwait(false);

            context.Transaction.Message = await ReadMessageAsync(context, cancellationToken).ConfigureAwait(false);

            try
            {
                // store the transaction
                using (var container = new DisposableContainer <IMessageStore>(Options.MessageStoreFactory.CreateInstance(context)))
                {
                    var response = await container.Instance.SaveAsync(context, context.Transaction, cancellationToken).ConfigureAwait(false);

                    await context.Client.ReplyAsync(response, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                await context.Client.ReplyAsync(new SmtpResponse(SmtpReplyCode.TransactionFailed), cancellationToken).ConfigureAwait(false);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            using (var container = new DisposableContainer <IMailboxFilter>(Options.MailboxFilterFactory.CreateInstance(context)))
            {
                switch (await container.Instance.CanDeliverToAsync(context, Address, context.Transaction.From, cancellationToken).ConfigureAwait(false))
                {
                case MailboxFilterResult.Yes:
                    context.Transaction.To.Add(Address);
                    await context.NetworkClient.ReplyAsync(SmtpResponse.Ok, cancellationToken).ConfigureAwait(false);

                    return(true);

                case MailboxFilterResult.NoTemporarily:
                    await context.NetworkClient.ReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken).ConfigureAwait(false);

                    return(false);

                case MailboxFilterResult.NoPermanently:
                    await context.NetworkClient.ReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken).ConfigureAwait(false);

                    return(false);
                }
            }

            throw new NotSupportedException("The Acceptance state is not supported.");
        }
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            var mailboxFilter = context.ServiceProvider.GetService <IMailboxFilterFactory, IMailboxFilter>(context, MailboxFilter.Default);

            using var container = new DisposableContainer <IMailboxFilter>(mailboxFilter);

            switch (await container.Instance.CanDeliverToAsync(context, Address, context.Transaction.From, cancellationToken).ConfigureAwait(false))
            {
            case MailboxFilterResult.Yes:
                context.Transaction.To.Add(Address);
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.Ok, cancellationToken).ConfigureAwait(false);

                return(true);

            case MailboxFilterResult.NoTemporarily:
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken).ConfigureAwait(false);

                return(false);

            case MailboxFilterResult.NoPermanently:
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            throw new NotSupportedException("The Acceptance state is not supported.");
        }
Exemplo n.º 7
0
        public IResult Run(SmtpSessionContext context)
        {
            var transport = context.Transport;

            transport.SendFormat("220 {0} SMTP server ready.", context.ServerName);

            string response = transport.Read();

            if (!response.StartsWith("HELO") && !response.StartsWith("EHLO"))
            {
                var errorResult = new HandshakeResult
                {
                    StatusCode   = SmtpStatusCode.UNKNOWN_COMMAND,
                    StatusReason = "Unknow Command"
                };
                return(errorResult);
            }
            string client = response.Replace("HELO", string.Empty).Replace("EHLO", string.Empty).Trim();

            transport.Send("250-localhost");

            var result = new HandshakeResult
            {
                StatusCode   = SmtpStatusCode.OK,
                RemoteClient = client
            };

            return(result);
        }
        public void BadUsernameOrPassword()
        {
            var testUsername = "******";
            var testPassword = "******";

            SetResponses(testUsername, testPassword);

            ResetCounter();
            SetupTransport();
            SetupAuthProvider(false);

            SmtpSessionContext context = new SmtpSessionContext
            {
                AuthProvider = _authProvider.Object,
                Transport    = _transportMock.Object
            };

            PlainTextLoginProvider provider = new PlainTextLoginProvider();
            var result = provider.RunAsync(context).Result;

            var authresult = result as UserAuthenticationResult;

            Assert.IsNotNull(authresult);
            Assert.AreEqual(SmtpStatusCode.MAILBOX_NOT_FOUND, authresult.StatusCode);
            Assert.AreEqual(testUsername, authresult.Username);
        }
Exemplo n.º 9
0
        public IResult Run(SmtpSessionContext context)
        {
            var           transport = context.Transport;
            int           counter   = 0;
            StringBuilder message   = new StringBuilder();
            string        response;

            while ((response = transport.Read().Trim()) != ".")
            {
                message.AppendLine(response);
                counter++;

                if (counter == 1000000)
                {
                    transport.Send(SmtpStatusCode.INSUFFICIENT_STORAGE, "MESSAGE TO LARGE");
                    var errorResult = new MessageProcessingResult
                    {
                        StatusCode   = SmtpStatusCode.LOCAL_PROCESSING_ERROR,
                        StatusReason = "Message size exceeds limit"
                    };

                    return(errorResult);
                }
            }

            transport.Send(SmtpStatusCode.OK, "OK");

            var result = new MessageProcessingResult
            {
                StatusCode   = SmtpStatusCode.OK,
                StatusReason = "Message recieved"
            };

            return(result);
        }
Exemplo n.º 10
0
        public void RecipientValidationSucessTest()
        {
            var          provider         = new RecipientValidationProvider();
            var          transportMoq     = new Mock <ITransport>(MockBehavior.Loose);
            const string recipientAddress = "*****@*****.**";

            SetResponses(string.Format("RCPT TO: {0}", recipientAddress), "DATA");

            Mock <IMessageRecipientValidator> validatorMock = new Mock <IMessageRecipientValidator>();

            validatorMock.Setup(s => s.ValidateRecipient(It.IsAny <string>())).Returns(true);

            var context = new SmtpSessionContext()
            {
                Transport          = _transportMock.Object,
                RecipientValidator = validatorMock.Object
            };

            var result = provider.RunAsync(context).Result as RecipientValidationResult;

            Assert.IsNotNull(result);
            Assert.AreEqual(SmtpStatusCode.OK, result.StatusCode);
            Assert.IsNotNull(result.Recipients);
            List <string> reciientList = new List <string>(result.Recipients);

            Assert.IsTrue(reciientList.Count == 1);
            Assert.AreEqual(recipientAddress, reciientList[0]);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Transaction.Reset();

            await context.NetworkClient.ReplyAsync(SmtpResponse.Ok, cancellationToken).ConfigureAwait(false);

            return(true);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.NetworkClient.ReplyAsync(SmtpResponse.ServiceReady, cancellationToken).ConfigureAwait(false);

            await context.NetworkClient.Stream.UpgradeAsync(Options.ServerCertificate, Options.SupportedSslProtocols, cancellationToken).ConfigureAwait(false);

            return(true);
        }
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            var response = new SmtpResponse(SmtpReplyCode.Ok, GetGreeting(context));

            await context.Pipe.Output.WriteReplyAsync(response, cancellationToken).ConfigureAwait(false);

            return(true);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.IsQuitRequested = true;

            await context.NetworkClient.ReplyAsync(SmtpResponse.ServiceClosingTransmissionChannel, cancellationToken).ReturnOnAnyThread();

            return(true);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            var response = new SmtpResponse(SmtpReplyCode.Ok, $"Hello {DomainOrAddress}, haven't we met before?");

            await context.NetworkClient.ReplyAsync(response, cancellationToken).ReturnOnAnyThread();

            return(true);
        }
Exemplo n.º 16
0
        /// <inheritdoc />
        internal override Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Properties.Add(ProxySourceEndpointKey, SourceEndpoint);
            context.Properties.Add(ProxyDestinationEndpointKey, DestinationEndpoint);

            // Do not transition smtp protocol state for these commands.
            return(Task.FromResult(false));
        }
Exemplo n.º 17
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task which asynchronously performs the execution.</returns>
        internal override async Task ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Client.ReplyAsync(SmtpResponse.ServiceReady, cancellationToken);

            await context.Client.UpgradeAsync(Options.ServerCertificate, Options.SupportedSslProtocols, cancellationToken);

            context.IsSecure = true;
        }
Exemplo n.º 18
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.IsQuitRequested = true;

            await context.Pipe.Output.WriteReplyAsync(SmtpResponse.ServiceClosingTransmissionChannel, cancellationToken).ConfigureAwait(false);

            return(true);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Returns a value indicating whether or not plain login is allowed.
        /// </summary>
        /// <param name="session">The current session.</param>
        /// <returns>true if plain login is allowed for the session, false if not.</returns>
        bool IsPlainLoginAllowed(SmtpSessionContext session)
        {
            if (Options.UserAuthenticatorFactory == null)
            {
                return(false);
            }

            return(session.IsSecure || Options.AllowUnsecureAuthentication);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Returns a value indicating whether or not plain login is allowed.
        /// </summary>
        /// <param name="session">The current session.</param>
        /// <returns>true if plain login is allowed for the session, false if not.</returns>
        bool IsPlainLoginAllowed(SmtpSessionContext session)
        {
            if (Options.UserAuthenticatorFactory == null)
            {
                return(false);
            }

            return(session.NetworkClient.IsSecure || session.EndpointDefinition.AllowUnsecureAuthentication);
        }
Exemplo n.º 21
0
        private static Mock <ISmtpSessionProvider> CreateProvider(SmtpSessionContext ItAny, IResult result)
        {
            Mock <ISmtpSessionProvider> providerMock = new Mock <ISmtpSessionProvider>();

            providerMock.Setup(s => s.RunAsync(It.IsAny <SmtpSessionContext>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult <IResult>(result))
            .Verifiable("Was not called");

            return(providerMock);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Pipe.Output.WriteReplyAsync(SmtpResponse.ServiceReady, cancellationToken).ConfigureAwait(false);

            var certificate = context.EndpointDefinition.ServerCertificate;
            var protocols   = context.EndpointDefinition.SupportedSslProtocols;

            await context.Pipe.UpgradeAsync(certificate, protocols, cancellationToken).ConfigureAwait(false);

            return(true);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Attempt a LOGIN login sequence.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>true if the LOGIN login sequence worked, false if not.</returns>
        async Task <bool> TryLoginAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Client.ReplyAsync(new SmtpResponse(SmtpReplyCode.ContinueWithAuth, "VXNlcm5hbWU6"), cancellationToken);

            _user = await ReadBase64EncodedLineAsync(context.Client, cancellationToken).ReturnOnAnyThread();

            await context.Client.ReplyAsync(new SmtpResponse(SmtpReplyCode.ContinueWithAuth, "UGFzc3dvcmQ6"), cancellationToken);

            _password = await ReadBase64EncodedLineAsync(context.Client, cancellationToken).ReturnOnAnyThread();

            return(true);
        }
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            if (context.EndpointDefinition.AuthenticationRequired && context.Authentication.IsAuthenticated == false)
            {
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.AuthenticationRequired, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            context.Transaction.Reset();
            context.Transaction.Parameters = Parameters;

            // check if a size has been defined
            var size = GetMessageSize();

            // check against the server supplied maximum
            if (context.ServerOptions.MaxMessageSize > 0 && size > context.ServerOptions.MaxMessageSize)
            {
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.SizeLimitExceeded, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            var mailboxFilter = context.ServiceProvider.GetService <IMailboxFilterFactory, IMailboxFilter>(context, MailboxFilter.Default);

            using var container = new DisposableContainer <IMailboxFilter>(mailboxFilter);

            switch (await container.Instance.CanAcceptFromAsync(context, Address, size, cancellationToken).ConfigureAwait(false))
            {
            case MailboxFilterResult.Yes:
                context.Transaction.From = Address;
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.Ok, cancellationToken).ConfigureAwait(false);

                return(true);

            case MailboxFilterResult.NoTemporarily:
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken).ConfigureAwait(false);

                return(false);

            case MailboxFilterResult.NoPermanently:
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken).ConfigureAwait(false);

                return(false);

            case MailboxFilterResult.SizeLimitExceeded:
                await context.Pipe.Output.WriteReplyAsync(SmtpResponse.SizeLimitExceeded, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            throw new SmtpResponseException(SmtpResponse.TransactionFailed);
        }
Exemplo n.º 25
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occur, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Authentication = AuthenticationContext.Unauthenticated;

            switch (Method)
            {
            case AuthenticationMethod.Plain:
                if (await TryPlainAsync(context, cancellationToken).ConfigureAwait(false) == false)
                {
                    await context.Pipe.Output.WriteReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);

                    return(false);
                }
                break;

            case AuthenticationMethod.Login:
                if (await TryLoginAsync(context, cancellationToken).ConfigureAwait(false) == false)
                {
                    await context.Pipe.Output.WriteReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);

                    return(false);
                }
                break;
            }

            var userAuthenticator = context.ServiceProvider.GetService <IUserAuthenticatorFactory, IUserAuthenticator>(context, UserAuthenticator.Default);

            using (var container = new DisposableContainer <IUserAuthenticator>(userAuthenticator))
            {
                if (await container.Instance.AuthenticateAsync(context, _user, _password, cancellationToken).ConfigureAwait(false) == false)
                {
                    var remaining = context.ServerOptions.MaxAuthenticationAttempts - ++context.AuthenticationAttempts;
                    var response  = new SmtpResponse(SmtpReplyCode.AuthenticationFailed, $"authentication failed, {remaining} attempt(s) remaining.");

                    await context.Pipe.Output.WriteReplyAsync(response, cancellationToken).ConfigureAwait(false);

                    if (remaining <= 0)
                    {
                        throw new SmtpResponseException(SmtpResponse.ServiceClosingTransmissionChannel, true);
                    }

                    return(false);
                }
            }

            await context.Pipe.Output.WriteReplyAsync(SmtpResponse.AuthenticationSuccessful, cancellationToken).ConfigureAwait(false);

            context.Authentication = new AuthenticationContext(_user);
            context.RaiseSessionAuthenticated();

            return(true);
        }
Exemplo n.º 26
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task which asynchronously performs the execution.</returns>
        internal override async Task ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            var greeting = $"{Options.ServerName} Hello {DomainOrAddress}, haven't we met before?";
            var output = new[] { greeting }.Union(GetExtensions(context)).ToArray();

            for (var i = 0; i < output.Length - 1; i++)
            {
                await context.Client.WriteLineAsync($"250-{output[i]}", cancellationToken);
            }

            await context.Client.WriteLineAsync($"250 {output[output.Length - 1]}", cancellationToken);

            await context.Client.FlushAsync(cancellationToken);
        }
Exemplo n.º 27
0
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Returns true if the command executed successfully such that the transition to the next state should occurr, false
        /// if the current state is to be maintained.</returns>
        internal override async Task <bool> ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
        {
            var output = new[] { GetGreeting(context) }.Union(GetExtensions(context)).ToArray();

            for (var i = 0; i < output.Length - 1; i++)
            {
                context.Pipe.Output.WriteLine($"250-{output[i]}");
            }

            context.Pipe.Output.WriteLine($"250 {output[output.Length - 1]}");

            await context.Pipe.Output.FlushAsync(cancellationToken).ConfigureAwait(false);

            return(true);
        }
Exemplo n.º 28
0
        public void SenderValidationBadRequest()
        {
            var provider = new SenderValidationProvider();

            var transportMoq = new Mock <ITransport>(MockBehavior.Loose);
            var context      = new SmtpSessionContext()
            {
                Transport = transportMoq.Object
            };

            transportMoq.Setup(m => m.Read()).Returns("BAD COMMAND");

            var result = provider.RunAsync(context).Result as SenderValidationResult;

            Assert.IsNotNull(result, "Response is of the incorrect type");
            Assert.AreEqual(SmtpStatusCode.UNKNOWN_COMMAND, result.StatusCode);
        }
Exemplo n.º 29
0
        public void BasicHandshakeBadResponse()
        {
            var provider = new HandshakeProvider();

            var transportMoq = new Mock <ITransport>();
            var context      = new SmtpSessionContext()
            {
                ServerName = "localhost",
                Transport  = transportMoq.Object
            };

            transportMoq.Setup(m => m.Read()).Returns("HELLO");

            var result = provider.RunAsync(context).Result;

            Assert.AreEqual(SmtpStatusCode.UNKNOWN_COMMAND, result.StatusCode);
        }
Exemplo n.º 30
0
        public async Task <IResult> RunAsync(SmtpSessionContext context,
                                             CancellationToken cancellationToken = new CancellationToken())
        {
            var transport     = context.Transport;
            var senderMessage = transport.Read();

            if (!senderMessage.StartsWith("MAIL FROM:"))
            {
                transport.Send(SmtpStatusCode.UNKNOWN_COMMAND, "UNKNOW COMMAND");
                var errorResult = new SenderValidationResult
                {
                    StatusCode   = SmtpStatusCode.UNKNOWN_COMMAND,
                    StatusReason = "Unknown Command"
                };
                return(errorResult);
            }
            else
            {
                var sender           = senderMessage.Replace("MAIL FROM:", string.Empty).Trim();
                var validationResult = context.SenderValidator.IsAuthorizedSender(sender);

                if (validationResult)
                {
                    transport.Send(SmtpStatusCode.OK, "GO AHEAD");
                    var result = new SenderValidationResult
                    {
                        StatusCode   = SmtpStatusCode.OK,
                        StatusReason = "Sender Accepted",
                        Sender       = sender
                    };
                    return(result);
                }
                else
                {
                    transport.Send(SmtpStatusCode.MAILBOX_NOT_FOUND, "UNAUTHORIZED SENDER");
                    var result = new SenderValidationResult
                    {
                        StatusCode   = SmtpStatusCode.MAILBOX_NOT_FOUND,
                        StatusReason = "Sender Not Authorized",
                        Sender       = sender
                    };
                    return(result);
                }
            }
        }