Such a simple use case - send email by connecting to SMTP server.

I was pleased to find that in .NET there is a class SmtpClient with a very simple interface:

namespace System.Net.Mail 
{
    public class SmtpClient : IDisposable 
    {
        public void Send(string from, string recipients, string? subject, string? body)
        
        public void Send(MailMessage message)

        public Task SendMailAsync(MailMessage message)
    } 
}

Easy, right?

Turns out this small class is not very usable now. According to the dotnet docs:

We don’t recommend that you use the SmtpClient class for new development because SmtpClient doesn’t support many modern protocols. Use MailKit or other libraries instead.

So, using MailKit everything is still quite easy:

public async Task<ServiceResult> Send(string toEmail, string topic, string body)
{
    var message = new MimeMessage();
    message.From.Add(new MailboxAddress(FromName, from));
    message.To.Add(new MailboxAddress(toName, toEmail));
    message.Subject = topic;

    var builder = new BodyBuilder();
    builder.HtmlBody = body;
    message.Body = builder.ToMessageBody();

    try
    {
        using (var client = new SmtpClient())
        {
            await client.ConnectAsync(smtpHost, smtpPort, SecureSocketOptions.SslOnConnect);
            await client.AuthenticateAsync(smtpUser, smtpPass);
            await client.SendAsync(message);
            await client.DisconnectAsync(true);
        }

        return ServiceResult.Success;
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed to send email via SMTP: " + ex.ToString());
        return ServiceResult.Failed(ex);
    }
}

The important part here is:

await client.ConnectAsync(smtpHost, smtpPort, SecureSocketOptions.SslOnConnect);

If the SMTP server supports SSL connections, SockerOptions parameter needs to be set.

Also if you’re using this code example, make sure you’re setting the correct port.

In my setup, I was using Mailu TLS 465 port.