Email Management with .NET 9 and C# using MailKit

Introduction

Dealing with emails by code is a must in many apps. In .NET 9, the SmtpClient class is too old and not suggested anymore. Now, MailKit and MimeKit offer a new, fast, and bendy method for email talks. This piece looks at how to set up and use MailKit in C# to send emails well and safe.

Prerequisites

Before implementing email-sending functionality, ensure you have:

  • A .NET 9 application (Console, Web, or Windows Forms)
  • An SMTP server (e.g., Gmail, Outlook, or your own SMTP service)
  • Valid SMTP credentials (username and password) or an OAuth2 token
  • Secure storage for credentials (environment variables, Azure Key Vault, AWS Secrets Manager, etc.)

Setting Up MailKit in C#

To send an email using MailKit, follow these steps:

1. Install Required Package

Run the following command to install MailKit:

 dotnet add package MailKit

2. Securely Store SMTP Credentials

Avoid hardcoding credentials in your code. Instead, use environment variables:

Set Environment Variables

export SMTP_HOST=smtp.example.com
export SMTP_PORT=587
export SMTP_USER=your-email@example.com
export SMTP_PASSWORD=your-password

Read Environment Variables in C#

var smtpHost = Environment.GetEnvironmentVariable("SMTP_HOST");
var smtpPort = int.Parse(Environment.GetEnvironmentVariable("SMTP_PORT"));
var smtpUser = Environment.GetEnvironmentVariable("SMTP_USER");
var smtpPassword = Environment.GetEnvironmentVariable("SMTP_PASSWORD");

Sending an Email

using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using System;

class Program
{
    static void Main()
    {
        try
        {
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress("Your Name", smtpUser));
            message.To.Add(new MailboxAddress("Recipient", "recipient@example.com"));
            message.Subject = "Test Email";
            message.Body = new TextPart("plain") { Text = "This is a test email sent from Codú." };

            using var client = new SmtpClient();
            client.Connect(smtpHost, smtpPort, SecureSocketOptions.StartTls);
            client.Authenticate(smtpUser, smtpPassword);
            client.Send(message);
            client.Disconnect(true);
            
            Console.WriteLine("Email sent successfully!");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

Understanding SecureSocketOptions

  • None: No encryption.
  • SslOnConnect: Uses SSL/TLS immediately upon connection.
  • StartTls: Starts with an unencrypted connection and upgrades to TLS (Recommended).
  • Auto: Automatically selects the best option.

Sending Emails with Attachments

var message = new MimeMessage();
message.From.Add(new MailboxAddress("Your Name", smtpUser));
message.To.Add(new MailboxAddress("Recipient", "recipient@example.com"));
message.Subject = "Email with Attachment";

var body = new TextPart("plain") { Text = "Please find the attached file." };
var attachment = new MimePart("application", "pdf")
{
    Content = new MimeContent(File.OpenRead("document.pdf"), ContentEncoding.Default),
    ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
    ContentTransferEncoding = ContentEncoding.Base64,
    FileName = "document.pdf"
};

var multipart = new Multipart("mixed") { body, attachment };
message.Body = multipart;

Sending HTML Emails

message.Body = new TextPart("html")
{
    Text = "<h1>Welcome!</h1><p>This is a <strong>test email from Codú</strong> with HTML formatting.</p>"
};

Sending Emails to Multiple Recipients

message.To.Add(new MailboxAddress("Recipient1", "recipient1@example.com"));
message.To.Add(new MailboxAddress("Recipient2", "recipient2@example.com"));
message.Bcc.Add(new MailboxAddress("Hidden Recipient", "bcc@example.com"));

Using OAuth2 Authentication (Gmail, Outlook)

using MailKit.Security;
client.Authenticate(new SaslMechanismOAuth2(smtpUser, "your-access-token"));

Implementing Logging with Serilog

using Serilog;
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/email.log", rollingInterval: RollingInterval.Day)
    .CreateLogger();

Log.Information("Email sent successfully to {Recipient}", "recipient@example.com");

Enhancing Resilience with Retry Policies

Using Polly to implement retries on transient errors:

var retryPolicy = Policy.Handle<SmtpCommandException>()
    .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt));

Sending Emails Asynchronously

For better performance in web applications:

await client.SendAsync(message);
await client.DisconnectAsync(true);

Background Email Processing

For large-scale applications, consider:

  • Hangfire (Task scheduling)
  • Quartz.NET (Job scheduling)
  • RabbitMQ / Azure Queue Storage (Message queuing)

Testing Email Sending with Smtp4Dev or Mailtrap

To avoid sending real emails during development, use:

Option 1: Smtp4Dev (Local SMTP Server)

dotnet tool install -g Rnwood.Smtp4dev
smtp4dev

Use localhost as your SMTP server in testing.

Option 2: Mailtrap (Online Testing)

  • Sign up at mailtrap.io
  • Use the provided SMTP credentials in your appsettings.json or environment variables.

Conclusion

MailKit is now the top choice for sending emails in .NET 9. It takes the place of the old SmtpClient. This tool gives a new and safe way to handle emails. Keep key info like login details safe using things like environment variables, Azure Key Vault, or AWS Secrets Manager.

If you stick to good steps like using OAuth2 for login, keeping logs, trying again with Polly, and testing with Smtp4Dev or Mailtrap, you can build a strong system for sending emails in your .NET apps.

DotnetDevelopmentProgrammingEmailCsharp
Avatar for Adrián Bailador

Written by Adrián Bailador

🚀 Full-Stack Dev 👨🏻‍💻 .NET Engineer 👾 Geek & Friki 💡 Talks about #dotnet, #csharp, #azure, #visualstudio and a little bit of #nextjs.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.