SMTP Server with C#

It took a while to find a library which provides a smtp server. There are a lot of smtp clients out there, but the number of smtp servers seems very limited.

Finally I found a library SmtpServer which provides a stmp server and several hooks to extend the functionality.

Open port 25

The documentation is straight forward and well documented.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var options = new SmtpServerOptionsBuilder()
    .ServerName("localhost")
    .Port(25, 587)
    .Port(465, isSecure: true)
    .Certificate(CreateX509Certificate2())
    .Build();

// this is used to intercept the processing and inject hooks
var serviceProvider = new ServiceProvider();
serviceProvider.Add(new SampleMessageStore());
serviceProvider.Add(new SampleMailboxFilter());
serviceProvider.Add(new SampleUserAuthenticator());

// lets start the server and wait
var smtpServer = new SmtpServer.SmtpServer(options, serviceProvider);
await smtpServer.StartAsync(CancellationToken.None);

This example reads the MimePart of the attachment and shows the attachments filename

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class SampleMessageStore : MessageStore
{
    public override async Task<SmtpResponse> SaveAsync(
        ISessionContext context,
        IMessageTransaction transaction, 
        ReadOnlySequence<byte> buffer, 
        CancellationToken cancellationToken)
    {
        await using var stream = new MemoryStream();

        var position = buffer.GetPosition(0);
        while (buffer.TryGet(ref position, out var memory))
        {
            await stream.WriteAsync(memory, cancellationToken);
        }

        stream.Position = 0;

        var message = await MimeKit.MimeMessage.LoadAsync(stream, cancellationToken);
        Console.WriteLine("Mail received: " + message.Subject);
        foreach (var attachment in message.Attachments)
        {
            Console.WriteLine("...Attachment found: " + (attachment as MimePart)?.FileName);
        }
        return SmtpResponse.Ok;
    }
}

For sending am email, a PowerShell commandlet can be used.

1
Send-MailMessage -To foo@bar.de -Subject "Hello User" -Body "This is the message" -SmtpServer "localhost" -From "bar@foo.de" -Attachments .\Documents\IMG-20220425-WA0058.jpg