DEV Community

Alex
Alex

Posted on

.NET Learning Notes: Using MailHog with .NET for Email Testing

MailHog is a simple and powerful tool for capturing and viewing emails sent from your application during development or testing. It acts as a local SMTP server and provides a web interface for viewing the captured messages. This blog explains how to use MailHog with a .NET project for email sending and testing, and how to integrate it into CI pipelines.


Why Use MailHog?

  • Captures emails sent from development apps.
  • Web UI for viewing emails at http://localhost:8025.
  • Excellent for integration testing.
  • No real emails sent — safe for all environments.
  • Free!!

Running MailHog with Docker

The easiest way to start MailHog is with Docker:

docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog
Enter fullscreen mode Exit fullscreen mode
  • SMTP Server: localhost:1025
  • Web UI: http://localhost:8025

Or with a docker-compose.mailhog.yml file:

version: '3.8'
services:
  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"
      - "8025:8025"
Enter fullscreen mode Exit fullscreen mode

Then run:

docker-compose -f docker-compose.mailhog.yml up -d
Enter fullscreen mode Exit fullscreen mode

Sending Email with .NET and MailHog

Here’s how you can configure and use MailHog to send test emails in a .NET service.

1. SMTP Options

You can configure MailHog with no credentials and unencrypted SMTP:

// appsettings.Development.json
{
  "Smtp": {
    "Host": "localhost",
    "Port": 1025,
    "User": "",
    "Password": ""
  }
}
Enter fullscreen mode Exit fullscreen mode

2. The Email Service Class

This service uses MailKit and MimeKit to send email messages:

public class SmtpEmailService : IEmailService
{
    private readonly SmtpOptions _smtpOptions;

    public SmtpEmailService(IOptions<SmtpOptions> smtpOptions, ILogger<SmtpEmailService> logger)
    {
        _smtpOptions = smtpOptions.Value;
    }

    public async Task SendEmailAsync(EmailSendRequestedEvent emailEvent)
    {
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress("FinTrack", "no-reply@fintrack.com"));
        message.To.Add(new MailboxAddress(emailEvent.ToName ?? emailEvent.To, emailEvent.To));
        message.Subject = emailEvent.Subject;
        message.Body = emailEvent.IsHtml
            ? new TextPart("html") { Text = emailEvent.Body }
            : new TextPart("plain") { Text = emailEvent.Body };

        using var client = new SmtpClient();
        await client.ConnectAsync(_smtpOptions.Host, _smtpOptions.Port, SecureSocketOptions.None);
        await client.AuthenticateAsync(_smtpOptions.User, _smtpOptions.Password);
        await client.SendAsync(message);
        await client.DisconnectAsync(true);
    }
}
Enter fullscreen mode Exit fullscreen mode

Use SecureSocketOptions.None because MailHog does not support SSL or STARTTLS.

3. Unit Test Example

Use mock IOptions and ILogger, then run a real test that talks to MailHog:

[Fact]
public async Task SendAsync_WithValidInput_SendsEmailWithoutException()
{
    var smtpOptions = new SmtpOptions
    {
        Host = "localhost",
        Port = 1025,
        User = "",
        Password = ""
    };

    var optionsMock = new Mock<IOptions<SmtpOptions>>();
    optionsMock.Setup(o => o.Value).Returns(smtpOptions);

    var loggerMock = new Mock<ILogger<SmtpEmailService>>();
    var emailService = new SmtpEmailService(optionsMock.Object, loggerMock.Object);

    var emailEvent = new EmailSendRequestedEvent
    {
        From = "from@test.com",
        To = "to@test.com",
        ToName = "Receiver",
        Subject = "Test Subject",
        Body = "Test Body",
        IsHtml = false
    };

    await emailService.SendEmailAsync(emailEvent);
}
Enter fullscreen mode Exit fullscreen mode

Once this test runs, visit http://localhost:8025 and you’ll see the message inside MailHog's web UI. No real emails will be sent — perfect for development and CI.


Can You Set Password for MailHog?

MailHog does not support SMTP authentication or TLS encryption. It’s intentionally insecure for local use only.


CI Integration

You can easily run MailHog inside GitHub Actions with this snippet:

services:
  mailhog:
    image: mailhog/mailhog
    ports:
      - 1025:1025
      - 8025:8025
Enter fullscreen mode Exit fullscreen mode

Then point your tests to localhost:1025, and run them just like local.


MailHog is a powerful and easy-to-use tool for safely testing email logic without sending real emails. It's perfect for local development, integration testing, and even CI environments.

Top comments (0)