---
title: Catch your emails in Rails development with Mailhog
author: Daniel Schoppmann
tags: Action Mailer
published_at: '2024-01-03T13:28:00+01:00'
updated_at: '2024-01-09T08:17:53+01:00'
canonical_url: https://www.dotruby.com/articles/catch-your-emails-in-rails-development-with-mailhog
---

# Catch your emails in Rails development with Mailhog

Almost every non-trivial Rails application needs to handle email. While in development mode, the setup for actually viewing the raw email in HTML or Text is very tedious. It's even dangrous with the current Rails defaults. So follow this guide to use the tool `Mailhog` to catch all mails locally.

## The thing about emails in Rails development mode

Almost every non-trivial Rails application needs to handle email. You may need to send email verification messages, password reset emails, or even notify your users of internal events within your application. Email notifications are ubiquitous.

With [ActionMailer](https://github.com/rails/rails/tree/main/actionmailer) being a part of the Rails framework, Rails has our back on this. It's easy to configure and offers a wide range of features, so there's nothing to complain about.

But one thing that bothers us, and probably many other Rails developers, is the lack of a proper interface for testing emails in development. What does the email actually look like with the user I just signed up with? And did it actually send the email? While we should have tests for that, nothing compares to a real manual click-through experience. How do we actually configure ActionMailer in development to not accidentely send mails to the wrong person?

Even though Rails ships with [Mailer Previews](https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails), those previews are a one time snapshot of your template. This is great for designing and coding your template, but it’s completely decoupled from the underlying business process. And you better check that as a developer!

ActionMailer uses `sendmail` as the default for sending emails. However, using this method on a misconfigured development machine can be highly dangerous. It is also not recommended to use a well-known private SMTP server (such as Gmail or Outlook) in this case. 

Instead, developers have long been using mail catchers for development purposes. There are various gems available, such as [LetterOpener](https://github.com/ryanb/letter_opener), [Mailcatcher](https://mailcatcher.me/), and even commercial solutions like [Mailtrap](https://mailtrap.io/). These solutions address the long-standing pain point for developers of checking emails in Rails development. Typically, you define an outgoing `smtp_settings` hash for the development environment and point the mailer to these services.

## Mailhog to the rescue

Another approach that we highly recommend is using [Mailhog](https://github.com/mailhog/MailHog). It offers several benefits over other solutions:

- It runs locally
- It operates as a separate process independent of the application, allowing for easy usage
- It does not store any emails as it uses an in-memory store
- It is fast
- It runs on every platform
- No need for an additional gem

On a Mac, you can easily install Mailhog by following these steps:

```bash
brew install mailhog
```

and then be started with `mailhog` which opens the SMTP server on port `1025` and the http server with its nice UI on port `8025`.

## A quick example

To quickly define an example email for testing purposes, let's configure ActionMailer to use Mailhog in the development environment. We can accomplish this by creating an initializer file called smtp_settings.rb.

```ruby
if Rails.env.development?
	ActionMailer::Base.smtp_settings = {
	  address: "localhost",
	  port: 1025
	}
	ActionMailer::Base.delivery_method = :smtp
end
```

Create a mailer class with a mailer action of your choice.

```ruby
class UserMailer < ApplicationMailer
  def welcome
    mail(to: "user@example.com", from: "info@the-next-big-thing.com", subject: "Welcome Mail") do |format|
      format.html
      format.text
    end
  end
end
```

Let's define a simple html template for the action in app/user_mailer/welcome.html.erb:

```html
<h1>Welcome to The Next Big Thing</h1>
```

And a corresponding text template in app/user_mailer/welcome.text.erb:

```text
Welcome to The Next Big Thing
```

Make sure Mailhog is running, and then open the Rails console (rails console) to send a test email.

```ruby
UserMailer.welcome.deliver
```

Now open your browser and navigate to http://0.0.0.0:8025/. Here, you can view the actual email that was sent from your development environment and exclusively captured by Mailhog.

![Mailhog in action](https://github.com/dotruby/dotruby-content/assets/3856862/7ee732df-4694-48ed-bad9-0723259d2a2d)

## Why is there no default in Rails?

While we really love Mailhog for its ease of setup, there is still one question: *Wouldn't it be great to have something like this by default in Rails?*.

With Rails 8 finally moving towards more sensible defaults to make development easier ([see the milestone list for Rails 8](https://github.com/rails/rails/milestone/87)), we think it would be very useful to have a standard way to catch mails in development. This would be especially helpful for beginners who might struggle with the initial configuration.

Dreaming should be allowed, so let's add it to the wish list for the coming and promising years of Rails!
