banner

Some years ago I wrote a nice gist to setup an local Unix email delivering environment, for testing purposes.

In case you’re using Windows, I have one for you too.

Based on this, we’ll create an multi-environment mailer in Rails, using ActionMailer, which will send local emails using postfix for development, and can use any other configuration for production (including email services like SendGrid, SendinBlue, Amazon SES, Mandrill, Mailgun, etc).

I.e., locally we can test our Rails emails without rely on external services.

Before Start

Really, I’m assuming you have your postfix working like described in my gist.

Setup

Let’s start with a initializer, config/initializers/email.rb with the following content:

# config/initializers/email.rb
email_config = Rails.application.config_for :email

ActionMailer::Base.default_options = {
    from: email_config[:from]
}
ActionMailer::Base.raise_delivery_errors = email_config[:raise_delivery_errors]
ActionMailer::Base.smtp_settings = {
    user_name: email_config[:user_name],
    password: email_config[:password],
    domain: email_config[:domain],
    address: email_config[:address],
    port: email_config[:port],
    authentication: email_config[:authentication],
    enable_starttls_auto: email_config[:enable_starttls_auto],
    perform_deliveries: email_config[:perform_deliveries],
    delivery_method: email_config[:delivery_method]
}
unless email_config[:perform_deliveries]
  ActionMailer::Base.perform_deliveries = false
end

Then values for these configurations in /config/email.yml:

production:
  # Some prod config here

development:
  raise_delivery_errors: true
  domain: localhost
  perform_deliveries: true

test:
  delivery_method: test

Testing in Rails Console

Assuming you have an email like activation_instructions for a user, you can test using the deliver_now method in rails console:

    UserMailer.activation_instructions(@user).deliver_now

Caveats

Rails.application.config_for has no support for common section in the yml file.

If you’re using any other initialization method that has support for common section, it’s better:

  • clear values for authentication, user_name and password
  • change enable_starttls_auto to false and
  • make sure port value is 25

Example:

common:
  # Common config here

production:
  # Some prod specific config here

development:
  perform_deliveries: true
  port: 25
  authentication:
  user_name:
  password:
  enable_starttls_auto: false
  domain: localhost
  address: localhost

test:
  delivery_method: test

Additional Configurations

If you want more emails options to include in your initializer, like a default value for reply_to, please check all options in Action Mailer Configuration doc.