Storing SMTP credentials in secrets.yml in a Ruby on Rails Application

Rails 4.1 introduced the concept of secrets.yml, a file in which you store all the credentials for your app, separated by environment, so for example, development can talk to Test Stripe and production to Live Stripe. Furthermore, this file is capable of picking up environment variables which allows you to divorce credentials from code. Not properly separating credentials from code recently cost Uber the leakage of 50,000 driver names and license numbers.

At Qredo we are very strict about handling credentials, including the ones for SMTP, which in Rails projects are normally stored in config/environments/development.rbconfig/environments/production.rb, etc. Trying to read Rails.application.secrets from those files doesn’t work, because they are loaded before the secrets, so, we came up with this alternative solution.

The environment files that need to use SMTP for delivering email have this common configuration:

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
    address: "smtp.example.com",
    port: 587,
    authentication: "plain",
    enable_starttls_auto: true
}

and then, on config/initializers/email.rb we finish configuring our SMTP credentials by reading it from secrets.yml:

if ActionMailer::Base.delivery_method == :smtp
  ActionMailer::Base.smtp_settings[:domain] = Rails.application.secrets.smtp_domain
  ActionMailer::Base.smtp_settings[:user_name] = Rails.application.secrets.smtp_user_name
  ActionMailer::Base.smtp_settings[:password] = Rails.application.secrets.smtp_password
end

In config/secrets.yml you need set those credentials:

development:
  secret_key_base: 123...
  smtp_domain: example.org
  smtp_user_name: postmaster@oderq.com
  smtp_password: <%= ENV["SMTP_PASSWORD"] %>

test:
  secret_key_base: c7f3f62597b14c7287d75c239168fd3a89d3a6cb51beb909679c2609e912aaa3ca0a0aa5df2e191648baed6fe49698527a75dd265d222697576405971f478c98

staging:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  smtp_domain: example.net
  smtp_user_name: staging_user@example.net
  password: <%= ENV["SMTP_PASSWORD"] %>

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  smtp_domain: example.com
  smtp_user_name: user@example.com
  smtp_password: <%= ENV["SMTP_PASSWORD"] %>

And that’s it! Enjoy bringing SMTP credentials into Rails >4.0 secrets management.

Advertisements