Go to NuGet.org

What is SmtpServer?

SmtpServer is a simple, but highly functional SMTP server implementation. Written entirely in C# it takes full advantage of the .NET TPL to achieve maximum performance.

SmtpServer is available via NuGet https://www.nuget.org/packages/SmtpServer/

SmtpServer is available via Github https://github.com/cosullivan/SmtpServer

What does it support?

SmtpServer currently supports the following ESMTP extensions

  • STARTTLS
  • SIZE
  • PIPELINING

How can it be used?

At its most basic, it only takes a few lines of code for the server to be listening to incoming requests.

var options = new OptionsBuilder()
    .WithServerName("localhost")
    .WithPort(25, 587)
    .Build();

var smtpServer = new SmtpServer.SmtpServer(options);
await smtpServer.StartAsync(CancellationToken.None);

220 localhost v1.0.0.1 ESMTP ready
EHLO client
250-client
250-PIPELINING
250 STARTTLS
MAIL FROM:<test1&test.com>
250 Ok
RCPT TO:<test2&test.com>
250 Ok
DATA
354 end with <CRLF>.<CRLF>
.
250 mail accepted (12345)
quit
221 bye


Connection to host lost.

What hooks are provided?

There are three hooks that can be implemented; IMessageStore, IMailboxFilter, and IUserAuthenticator.

var options = new OptionsBuilder()
    .WithServerName("localhost")
    .WithPort(25, 587)
    .WithMessageStore(new ConsoleMessageStore())
    .WithMailboxFilter(new MailboxFilter())
    .WithUserAuthenticator(new UserAuthenticator())
    .Build();

var smtpServer = new SmtpServer.SmtpServer(options);
await smtpServer.StartAsync(CancellationToken.None);

public class ConsoleMessageStore : IMessageStore
{
    public Task<string> SaveAsync(IMimeMessage message, CancellationToken cancellationToken)
    {
        Console.WriteLine(message.Mime);
        
        return Task.FromResult(String.Empty);
    }
}

public class MailboxFilter : IMailboxFilter
{
    public Task<MailboxFilterResult> CanAcceptFromAsync(IMailbox @from, int size = 0)
    {
        if (String.Equals(@from.Host, "test.com"))
        {
            return Task.FromResult(MailboxFilterResult.Yes);   
        }

        return Task.FromResult(MailboxFilterResult.NoPermanently);
    }

    public Task<MailboxFilterResult> CanDeliverToAsync(IMailbox to, IMailbox @from)
    {
        return Task.FromResult(MailboxFilterResult.Yes);
    }
}

public class UserAuthenticator : IUserAuthenticator
{
    public Task<bool> AuthenticateAsync(string user, string password)
    {
        Console.WriteLine("User={0} Password={1}", user, password);
 
        return Task.FromResult(user.Length > 4);
    }
}