Пример #1
0
        /// <summary>
        /// Execute the command handler against the specified session context.
        /// </summary>
        /// <param name="context">The session context to execute the command handler against.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task which asynchronously performs the execution.</returns>
        public virtual async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            var retryCount = _maxRetries;

            while (retryCount-- > 0 && context.IsQuitRequested == false && cancellationToken.IsCancellationRequested == false)
            {
                var text = await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false);

                SmtpCommand  command;
                SmtpResponse errorResponse;
                if (TryAccept(context, text, out command, out errorResponse) == false)
                {
                    var response = new SmtpResponse(errorResponse.ReplyCode, $"{errorResponse.Message}, {retryCount} retry(ies) remaining.");

                    await context.Text.ReplyAsync(response, cancellationToken);

                    continue;
                }

                // the command was a normal command so we can reset the retry count
                retryCount = _maxRetries;

                await ExecuteAsync(command, context, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #2
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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            switch (_method)
            {
                case AuthenticationMethod.Plain:
                    if (await TryPlainAsync(context, cancellationToken) == false)
                    {
                        await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);
                        return;
                    }
                    break;

                case AuthenticationMethod.Login:
                    if (await TryLoginAsync(context, cancellationToken) == false)
                    {
                        await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);
                        return;
                    }
                    break;
            }

            if (await _userAuthenticator.AuthenticateAsync(_user, _password).ConfigureAwait(false) == false)
            {
                await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);
                return;
            }

            await context.Text.ReplyAsync(SmtpResponse.AuthenticationSuccessful, cancellationToken).ConfigureAwait(false);

            context.StateMachine.RemoveCommand(SmtpState.WaitingForMail, "AUTH");
            context.StateMachine.RemoveCommand(SmtpState.WaitingForMailSecure, "AUTH");
        }
Пример #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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            switch (Method)
            {
            case AuthenticationMethod.Plain:
                if (await TryPlainAsync(context, cancellationToken) == false)
                {
                    await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);

                    return;
                }
                break;

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

                    return;
                }
                break;
            }

            if (await _userAuthenticator.AuthenticateAsync(_user, _password).ConfigureAwait(false) == false)
            {
                await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);

                return;
            }

            await context.Text.ReplyAsync(SmtpResponse.AuthenticationSuccessful, cancellationToken).ConfigureAwait(false);

            context.StateMachine.RemoveCommand(SmtpState.WaitingForMail, "AUTH");
            context.StateMachine.RemoveCommand(SmtpState.WaitingForMailSecure, "AUTH");
        }
Пример #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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            if (context.Transaction.To.Count == 0)
            {
                await context.Text.ReplyAsync(SmtpResponse.NoValidRecipientsGiven, cancellationToken).ConfigureAwait(false);

                return;
            }

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

            await ReceiveContentAsync(context, cancellationToken);

            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.Text.ReplyAsync(response, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.TransactionFailed), cancellationToken).ConfigureAwait(false);
            }
        }
Пример #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>A task which asynchronously performs the execution.</returns>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            using (var container = new DisposableContainer <IMailboxFilter>(_mailboxFilterFactory.CreateInstance(context)))
            {
                switch (await container.Instance.CanDeliverToAsync(context, _address, context.Transaction.From))
                {
                case MailboxFilterResult.Yes:
                    context.Transaction.To.Add(_address);
                    await context.Text.ReplyAsync(SmtpResponse.Ok, cancellationToken);

                    return;

                case MailboxFilterResult.NoTemporarily:
                    await context.Text.ReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken);

                    return;

                case MailboxFilterResult.NoPermanently:
                    await context.Text.ReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken);

                    return;
                }
            }

            throw new NotSupportedException("The Acceptance state is not supported.");
        }
Пример #6
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(ISmtpSessionContext session)
        {
            if (_options.UserAuthenticator == null)
            {
                return false;
            }

            return session.Text.IsSecure || _options.AllowUnsecureAuthentication;
        }
Пример #7
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(ISmtpSessionContext session)
        {
            if (_options.UserAuthenticator == null)
            {
                return(false);
            }

            return(session.Text.IsSecure || _options.AllowUnsecureAuthentication);
        }
Пример #8
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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Text.ReplyAsync(SmtpResponse.ServiceReady, cancellationToken);

            var stream = new SslStream(context.Text.GetInnerStream(), true);

            await stream.AuthenticateAsServerAsync(_certificate, false, SslProtocols.Default, true);

            context.Text = new NetworkTextStream(stream);
        }
Пример #9
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>
        public override async Task ExecuteAsync(ISmtpSessionContext 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.Text.WriteLineAsync($"250-{output[i]}", cancellationToken);
            }

            await context.Text.WriteLineAsync($"250 {output[output.Length - 1]}", cancellationToken);
            await context.Text.FlushAsync(cancellationToken);
        }
Пример #10
0
        /// <summary>
        /// Receive the message content.
        /// </summary>
        /// <param name="context">The SMTP session context to receive the message within.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task which asynchronously performs the operation.</returns>
        async Task ReceiveContentAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            if (context.TransferEncoding == ContentEncoding.EightBit || _options.DefaultContentEncoding == ContentEncoding.EightBit)
            {
                context.Text = new NetworkTextStream(context.Text.GetInnerStream(), Encoding.UTF8);
            }

            await ReceiveShortLineContentAsync(context, cancellationToken);

            if (context.TransferEncoding == ContentEncoding.EightBit || _options.DefaultContentEncoding == ContentEncoding.EightBit)
            {
                context.Text = new NetworkTextStream(context.Text.GetInnerStream(), Encoding.ASCII);
            }
        }
Пример #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>A task which asynchronously performs the execution.</returns>
        public override async Task ExecuteAsync(ISmtpSessionContext 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.Text.WriteLineAsync($"250-{output[i]}", cancellationToken);
            }

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

            await context.Text.FlushAsync(cancellationToken);
        }
Пример #12
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(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.ContinueWithAuth, "VXNlcm5hbWU6"), cancellationToken);

            _user = Encoding.UTF8.GetString(
                Convert.FromBase64String(
                    await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false)));

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

            _password = Encoding.UTF8.GetString(
                Convert.FromBase64String(
                    await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false)));

            return(true);
        }
Пример #13
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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Transaction.Reset();

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

            // check against the server supplied maximum
            if (_options.MaxMessageSize > 0 && size > _options.MaxMessageSize)
            {
                await context.Text.ReplyAsync(SmtpResponse.SizeLimitExceeded, cancellationToken);

                return;
            }

            using (var container = new DisposableContainer <IMailboxFilter>(_options.MailboxFilterFactory.CreateInstance(context)))
            {
                switch (await container.Instance.CanAcceptFromAsync(context, Address, size))
                {
                case MailboxFilterResult.Yes:
                    context.Transaction.From = Address;
                    context.TransferEncoding = GetTransferEncoding() ?? context.TransferEncoding;
                    await context.Text.ReplyAsync(SmtpResponse.Ok, cancellationToken);

                    return;

                case MailboxFilterResult.NoTemporarily:
                    await context.Text.ReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken);

                    return;

                case MailboxFilterResult.NoPermanently:
                    await context.Text.ReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken);

                    return;

                case MailboxFilterResult.SizeLimitExceeded:
                    await context.Text.ReplyAsync(SmtpResponse.SizeLimitExceeded, cancellationToken);

                    return;
                }
            }

            throw new NotSupportedException("The Acceptance state is not supported.");
        }
Пример #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>A task which asynchronously performs the execution.</returns>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            if (context.Transaction.To.Count == 0)
            {
                await context.Text.ReplyAsync(SmtpResponse.NoValidRecipientsGiven, cancellationToken).ConfigureAwait(false);

                return;
            }

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

            try
            {
                string text;
                while ((text = await context.Text.ReadLineAsync(TimeSpan.FromSeconds(60), cancellationToken).ConfigureAwait(false)) != ".")
                {
                    // need to trim the '.' at the start of the line if it
                    // exists as this would have been added for transparency
                    // http://tools.ietf.org/html/rfc5321#section-4.5.2
                    context.Transaction.Mime.AppendLine(text.TrimStart('.'));
                }
            }
            catch (TimeoutException)
            {
                // TODO: not sure what the best thing to do here is
                throw;
            }

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

                    await context.Text.ReplyAsync(response, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.TransactionFailed), cancellationToken).ConfigureAwait(false);
            }
        }
Пример #15
0
        /// <summary>
        /// Gets the list of extensions.
        /// </summary>
        /// <param name="session">The session the is currently operating.</param>
        /// <returns>The list of extensions that are allowed for the session.</returns>
        IEnumerable<string> GetExtensions(ISmtpSessionContext session)
        {
            yield return "PIPELINING";

            if (session.Text.IsSecure == false && _options.ServerCertificate != null)
            {
                yield return "STARTTLS";
            }

            if (_options.MaxMessageSize > 0)
            {
                yield return $"SIZE {_options.MaxMessageSize}";
            }

            if (IsPlainLoginAllowed(session))
            {
                yield return "AUTH PLAIN LOGIN";
            }
        }
Пример #16
0
        /// <summary>
        /// Gets the list of extensions.
        /// </summary>
        /// <param name="session">The session the is currently operating.</param>
        /// <returns>The list of extensions that are allowed for the session.</returns>
        IEnumerable <string> GetExtensions(ISmtpSessionContext session)
        {
            yield return("PIPELINING");

            if (session.Text.IsSecure == false && _options.ServerCertificate != null)
            {
                yield return("STARTTLS");
            }

            if (_options.MaxMessageSize > 0)
            {
                yield return($"SIZE {_options.MaxMessageSize}");
            }

            if (IsPlainLoginAllowed(session))
            {
                yield return("AUTH PLAIN LOGIN");
            }
        }
Пример #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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            if (context.Transaction.To.Count == 0)
            {
                await context.Text.ReplyAsync(SmtpResponse.NoValidRecipientsGiven, cancellationToken).ConfigureAwait(false);
                return;
            }

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

            try
            {
                string text;
                while ((text = await context.Text.ReadLineAsync(TimeSpan.FromSeconds(60), cancellationToken).ConfigureAwait(false)) != ".")
                {
                    // need to trim the '.' at the start of the line if it 
                    // exists as this would have been added for transparency
                    // http://tools.ietf.org/html/rfc5321#section-4.5.2
                    context.Transaction.Mime.AppendLine(text.TrimStart('.'));
                }
            }
            catch (TimeoutException)
            {
                // TODO: not sure what the best thing to do here is
                throw;
            }

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

                    await context.Text.ReplyAsync(response, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.TransactionFailed), cancellationToken).ConfigureAwait(false);
            }
        }
Пример #18
0
 /// <summary>
 /// Receive the message content in short line format.
 /// </summary>
 /// <param name="context">The SMTP session context to receive the message within.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <returns>A task which asynchronously performs the operation.</returns>
 async Task ReceiveShortLineContentAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
 {
     try
     {
         string text;
         while ((text = await context.Text.ReadLineAsync(TimeSpan.FromSeconds(60), cancellationToken).ConfigureAwait(false)) != ".")
         {
             // need to trim the '.' at the start of the line if it
             // exists as this would have been added for transparency
             // http://tools.ietf.org/html/rfc5321#section-4.5.2
             var line = (!string.IsNullOrWhiteSpace(text) && text.Length > 1 && text.Substring(0, 1) == ".") ? text.Substring(1) : text;
             context.Transaction.Mime.AppendLine(line);
         }
     }
     catch (TimeoutException)
     {
         // TODO: not sure what the best thing to do here is
         throw;
     }
 }
Пример #19
0
        /// <summary>
        /// Attempt a PLAIN login sequence.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>true if the PLAIN login sequence worked, false if not.</returns>
        async Task<bool> TryPlainAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.ContinueWithAuth, " "), cancellationToken).ConfigureAwait(false);

            var authentication = Encoding.UTF8.GetString(
                Convert.FromBase64String(
                    await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false)));

            var match = Regex.Match(authentication, "\x0000(?<user>.*)\x0000(?<password>.*)");

            if (match.Success == false)
            {
                await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);
                return false;
            }

            _user = match.Groups["user"].Value;
            _password = match.Groups["password"].Value;

            return true;
        }
Пример #20
0
        /// <summary>
        /// Attempt a PLAIN login sequence.
        /// </summary>
        /// <param name="context">The execution context to operate on.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>true if the PLAIN login sequence worked, false if not.</returns>
        async Task <bool> TryPlainAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.ContinueWithAuth, " "), cancellationToken).ConfigureAwait(false);

            var authentication = Encoding.UTF8.GetString(
                Convert.FromBase64String(
                    await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false)));

            var match = Regex.Match(authentication, "\x0000(?<user>.*)\x0000(?<password>.*)");

            if (match.Success == false)
            {
                await context.Text.ReplyAsync(SmtpResponse.AuthenticationFailed, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            _user     = match.Groups["user"].Value;
            _password = match.Groups["password"].Value;

            return(true);
        }
Пример #21
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>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Transaction.Reset();

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

            // check against the server supplied maximum
            if (_maxMessageSize > 0 && size > _maxMessageSize)
            {
                await context.Text.ReplyAsync(SmtpResponse.SizeLimitExceeded, cancellationToken);
                return;
            }

            using (var container = new DisposableContainer<IMailboxFilter>(_mailboxFilterFactory.CreateInstance(context)))
            {
                switch (await container.Instance.CanAcceptFromAsync(context, Address, size))
                {
                    case MailboxFilterResult.Yes:
                        context.Transaction.From = _address;
                        await context.Text.ReplyAsync(SmtpResponse.Ok, cancellationToken);
                        return;

                    case MailboxFilterResult.NoTemporarily:
                        await context.Text.ReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken);
                        return;

                    case MailboxFilterResult.NoPermanently:
                        await context.Text.ReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken);
                        return;

                    case MailboxFilterResult.SizeLimitExceeded:
                        await context.Text.ReplyAsync(SmtpResponse.SizeLimitExceeded, cancellationToken);
                        return;
                }
            }

            throw new NotSupportedException("The Acceptance state is not supported.");
        }
Пример #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>A task which asynchronously performs the execution.</returns>
        public override async Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            using (var container = new DisposableContainer<IMailboxFilter>(_mailboxFilterFactory.CreateInstance(context)))
            {
                switch (await container.Instance.CanDeliverToAsync(context, _address, context.Transaction.From))
                {
                    case MailboxFilterResult.Yes:
                        context.Transaction.To.Add(_address);
                        await context.Text.ReplyAsync(SmtpResponse.Ok, cancellationToken);
                        return;

                    case MailboxFilterResult.NoTemporarily:
                        await context.Text.ReplyAsync(SmtpResponse.MailboxUnavailable, cancellationToken);
                        return;

                    case MailboxFilterResult.NoPermanently:
                        await context.Text.ReplyAsync(SmtpResponse.MailboxNameNotAllowed, cancellationToken);
                        return;
                }
            }

            throw new NotSupportedException("The Acceptance state is not supported.");
        }
Пример #23
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>
        public override Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            var response = new SmtpResponse(SmtpReplyCode.Ok, $"Hello {Domain}, haven't we met before?");

            return context.Text.ReplyAsync(response, cancellationToken);
        }
Пример #24
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(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            await context.Text.ReplyAsync(new SmtpResponse(SmtpReplyCode.ContinueWithAuth, "VXNlcm5hbWU6"), cancellationToken);

            _user = Encoding.UTF8.GetString(
                Convert.FromBase64String(
                    await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false)));

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

            _password = Encoding.UTF8.GetString(
                Convert.FromBase64String(
                    await context.Text.ReadLineAsync(cancellationToken).ConfigureAwait(false)));

            return true;
        }
Пример #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>A task which asynchronously performs the execution.</returns>
 public override Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
 {
     return context.Text.ReplyAsync(SmtpResponse.Ok, cancellationToken);
 }
Пример #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>
        public override Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            var response = new SmtpResponse(SmtpReplyCode.Ok, $"Hello {Domain}, haven't we met before?");

            return(context.Text.ReplyAsync(response, cancellationToken));
        }
        /// <summary>
        /// Execute the command.
        /// </summary>
        /// <param name="command">The command to execute.</param>
        /// <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>
        protected override Task ExecuteAsync(SmtpCommand command, ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            _visitor.Visit(command);

            return(command.ExecuteAsync(context, cancellationToken));
        }
Пример #28
0
 /// <summary>
 /// Execute the command.
 /// </summary>
 /// <param name="command">The command to execute.</param>
 /// <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>
 protected virtual Task ExecuteAsync(SmtpCommand command, ISmtpSessionContext context, CancellationToken cancellationToken)
 {
     return(command.ExecuteAsync(context, cancellationToken));
 }
Пример #29
0
 /// <summary>
 /// Advances the enumerator to the next command in the stream.
 /// </summary>
 /// <param name="context">The session context to execute the command handler against.</param>
 /// <param name="text">The text to return the commands from.</param>
 /// <param name="command">The command that was found.</param>
 /// <param name="errorResponse">The error response that indicates why a command could not be accepted.</param>
 /// <returns>true if a valid command was found, false if not.</returns>
 protected virtual bool TryAccept(ISmtpSessionContext context, string text, out SmtpCommand command, out SmtpResponse errorResponse)
 {
     return(context.StateMachine.TryAccept(new TokenEnumerator(new StringTokenReader(text)), out command, out errorResponse));
 }
Пример #30
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>
        public override Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Quit();

            return(context.Text.ReplyAsync(SmtpResponse.ServiceClosingTransmissionChannel, cancellationToken));
        }
Пример #31
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>
 public abstract Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken);
Пример #32
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>
 public abstract Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken);
Пример #33
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>
        public override Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Transaction.Reset();

            return(context.Text.ReplyAsync(SmtpResponse.Ok, cancellationToken));
        }
Пример #34
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>
        public override Task ExecuteAsync(ISmtpSessionContext context, CancellationToken cancellationToken)
        {
            context.Quit();

            return context.Text.ReplyAsync(SmtpResponse.ServiceClosingTransmissionChannel, cancellationToken);
        }