letter_opener: Preview Rails Emails in the Browser During Development
Preview mail in the browser instead of sending.
At a glance
- What is it?
- letter_opener is a Ruby gem that intercepts ActionMailer email in a Rails development environment and opens it in the default browser instead of sending it, with no mail server required. Messages are stored as HTML files in tmp/letter_opener, eliminating both the setup burden of a local mail server and the risk of sending test messages to real addresses.
- Who is it for?
- letter_opener suits Rails developers who want zero-configuration email preview during development. Set the delivery method, add the gem, and outbound mail appears in a browser tab.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 158 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Development Email Problem letter_opener Solves
Testing email delivery in a Rails application requires either a real mail server, a third-party staging inbox, or a way to intercept mail before it leaves the application. A real mail server in development risks sending test messages to real recipients when a developer uses production-like data. A third-party inbox requires an account and a network connection. letter_opener takes a different approach: it overrides Rails ActionMailer's delivery mechanism at the framework level so that mail is never handed to a transport at all. Instead, the gem writes the email to a local HTML file and opens that file in the browser. The README states this explicitly: 'you do not need to set up email delivery in your development environment, and you no longer need to worry about accidentally sending a test email to someone else's address.'
How letter_opener Intercepts Mail
letter_opener works as a custom ActionMailer delivery method. When Rails calls the delivery method for an outbound message, letter_opener's delivery class intercepts the mail object, writes an HTML representation to a temporary directory, and then calls Launchy, a Ruby library that opens files and URLs in the system's default browser. The messages are stored in tmp/letter_opener by default, as HTML files that include the email subject, headers, and body. This means the messages persist across server restarts and can be revisited without resending. The README notes that the gem was inspired by the mail_view gem from 37signals, and thanks Vasiliy Ermolovich for helping manage the project. The underlying mechanism is Rails-level, not network-level, so it works with any mailer class that uses ActionMailer's delivery infrastructure.
Setting Up letter_opener in a Rails Application
The Rails setup requires two steps. First, add the gem to the development group:
gem "letter_opener", group: :developmentThen configure the delivery method in config/environments/development.rb:
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.perform_deliveries = trueAfter that, any call to deliver or deliver_now on a mailer will open a browser tab with the email content instead of attempting delivery. The storage location can be changed from the default tmp/letter_opener:
LetterOpener.configure do |config|
config.location = Rails.root.join('tmp', 'my_mails')The message_template option changes the rendering style. The default value is :default, which renders a styled message with metadata visible. Setting it to :light renders only the message body with no styling or metadata containers. A file_uri_scheme option is also available for environments such as WSL where the default URI scheme does not open files correctly.
Non-Rails Setup: Mail gem and Pony
letter_opener is not limited to Rails. The README shows how to configure it with the standalone Mail gem:
require "letter_opener"
Mail.defaults do
delivery_method LetterOpener::DeliveryMethod, location: File.expand_path('../tmp/letter_opener', __FILE__)
endFor applications using the Pony gem:
require "letter_opener"
Pony.options = {
via: LetterOpener::DeliveryMethod,
via_options: {location: File.expand_path('../tmp/letter_opener', __FILE__)}
}For ActionMailer used directly without Rails, the delivery method is registered explicitly:
require "letter_opener"
ActionMailer::Base.add_delivery_method :letter_opener, LetterOpener::DeliveryMethod, :location => File.expand_path('../tmp/letter_opener', __FILE__)
ActionMailer::Base.delivery_method = :letter_openerIn each case, the location parameter specifies where the HTML files are written.
Docker, VMs, and the Launchy Limitation
letter_opener uses Launchy to open the mail file in a browser. This works when the Ruby process and the browser run on the same machine. It does not work in a Docker container, a headless VM, or on a remote staging server where there is no browser to open. When Launchy cannot find a browser, it raises a Launchy::CommandNotFoundError. The README documents this exact error message and gives a workaround: set two environment variables to suppress the error and discard the open attempt:
LAUNCHY_DRY_RUN=true
BROWSER=/dev/nullWith these variables set, the mail file is still written to tmp/letter_opener, but no browser launch is attempted. The README explicitly recommends Mailtrap or MailCatcher for staging servers and VM environments. These tools capture outbound mail at the SMTP level rather than the Rails delivery method level, so they work regardless of where the Ruby process runs.
Storage Location and the letter_opener_web Alternative
letter_opener stores every intercepted message as an HTML file in the configured location. This is straightforward for a single developer who opens and reads messages as they arrive. It does not provide an interface for browsing, searching, or deleting accumulated messages. The README acknowledges this trade-off directly: 'In order to keep this project simple, I don't have plans to turn it into a Rails engine with an interface for browsing the sent mail.' The README then points to letter_opener_web (by fgrehm) as a separate gem that adds exactly that browsing interface as a Rails engine, mounted at a configurable route. Teams that need to review a history of test messages, or whose QA process involves examining many emails over time, are pointed toward letter_opener_web rather than letter_opener itself.
letter_opener vs Mailtrap and MailCatcher
Mailtrap and MailCatcher both work at the SMTP protocol level: they run a fake SMTP server that accepts messages from any application and stores them in a web interface. This makes them work in Docker containers, VMs, and staging environments where Launchy cannot open a browser. The trade-off is setup: both require a running process on the network, and Mailtrap is a hosted service. letter_opener requires nothing outside the Ruby process and Rails configuration. For a solo developer running Rails locally, letter_opener is the simplest option: one gem, two config lines, and emails appear in a tab. For a team sharing a staging environment, Mailtrap or MailCatcher is the better fit since they work across network boundaries and expose a shared inbox.
Editorial conclusion
letter_opener suits Rails developers who want zero-configuration email preview during development. Set the delivery method, add the gem, and outbound mail appears in a browser tab. The constraint is local execution: the gem uses Launchy to open a file URI in a browser, which requires the Ruby process to run on the same machine as the browser. For Docker containers, VMs, and staging servers, the README recommends Mailtrap or MailCatcher. The gem's last push was on 2026-04-25.
Frequently asked questions
What is the letter_opener app?
letter_opener is a Ruby gem for Rails development that intercepts outbound ActionMailer messages and opens them in the default browser as HTML files, stored in tmp/letter_opener. It requires no mail server or external service.
What is letter_opener on macOS?
On macOS, letter_opener uses Launchy to open intercepted mail files in the system's default browser. No special macOS configuration is needed beyond the standard Gemfile and config/environments/development.rb changes documented in the README.
How do I change where letter_opener stores messages?
The storage location is configurable via LetterOpener.configure. Set config.location to any path, such as Rails.root.join('tmp', 'my_mails'), in an initializer or in config/environments/development.rb.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ryanb-letter-opener)