Previewing Mailers on non-development tiers
Asked Answered
B

3

8

I have several mailer previews under spec/mailer/previews. On development I can view all the previews under /rails/mailers/. However by default this functionality does not exist on other environments.

I wanted to enable it on the staging environment and took a queue from this post here.

I made the following changes -

config/routes.rb

# Add the routes manually
if Rails.env.staging?
  get "/rails/mailers" => "rails/mailers#index"
  get "/rails/mailers/*path" => "rails/mailers#preview"
end

config/environments/staging.rb

Rails.application.configure do
  # Define the mailer preview path
  config.action_mailer.preview_path = "spec/mailers/previews"

  # Specifically add that path and all files under it to the autoload paths
  config.autoload_paths = Dir["#{config.root}/#{config.action_mailer.preview_path}/**"]
end

class ::Rails::MailersController
  include Rails.application.routes.url_helpers

  # Override the method just for this controller so `MailersController` thinks
  # all requests are local.
  def local_request?
    true
  end
end

However on staging, I'm getting the following error when trying to load the /rails/mailers page -

LoadError (No such file to load -- spec/mailers/previews/admin_mailer_preview):

The odd thing is... that file definitely exists. And when I check the autoload paths on staging that file is definitely in the Array/list.

Any thoughts on what might be happening here, or how else I should go about exposing that endpoint?

Thanks!

Buenabuenaventura answered 28/8, 2016 at 3:35 Comment(2)
Did you try config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews"Callant
That did it! Such a silly thing - thanks :)Buenabuenaventura
B
10

Having consider_all_requests_local = true or patching local_request? can be security issue. Here is solution we use, it uses authentication to allow only admins to access previews:

# in any enviroment
config.action_mailer.show_previews = true

# in initializers/mailer_previews.rb
# (use your own authentication methods)

# Allow admins to see previews if show_previews enabled.
# It does not affect dev env, as this setting is nil there.
if Rails.application.config.action_mailer.show_previews
  Rails::MailersController.prepend_before_action do
    authenticate_user!
    head :forbidden unless current_user.admin?
  end
end

# If you use rspec-rails, it makes rails use spec/mailers/previews
# as previews path. Most likely you don't have rspec-rails on
# staging/production, so need to add this to application.rb:
#
# Make previews available in environments without rspec-rails.
config.action_mailer.preview_path = Rails.root.join('spec', 'mailers', 'previews')

# Bonus: specs. Update with your `sign_in` implementation
# and have `config.action_mailer.show_previews = true` in test.rb
RSpec.describe Rails::MailersController do
  shared_examples 'visible to admin only' do
    it { should redirect_to new_user_session_path }

    context 'for signed in user' do
      sign_in { create(:user) }
      it { should be_forbidden }

      context 'admin' do
        let(:current_user) { create(:user, admin: true) }
        it { should be_ok }
      end
    end
  end

  describe '#index' do
    subject { get('/rails/mailers') && response }
    include_examples 'visible to admin only'
  end

  describe '#preview' do
    subject { get('/rails/mailers/devise/mailer') && response }
    include_examples 'visible to admin only'
  end
end
Bernadine answered 5/7, 2017 at 10:7 Comment(4)
In my case i needed a concern that isn't in the same namespace but was able to do it with this gist.github.com/rromanchuk/486f6fbd4fec28c8fa69d36220795343Squalor
The before_action fails with undefined local variable or method 'current_user' for #<Rails::MailersController:0x00007f88eda2e8b0>. Same for my replacement of your authenticate_user! line. It appears to me that this code only works for normally controllers, not mailer controllers.Dispersoid
current_user is helper from devise gem that returns signed in user. Devise adds it to this controller. You need to use your own auth implementation and replace this check.Bernadine
Adapted the initializer for rails 7 also: "does not affect dev env" was not true for me at least # Allow staff to see previews if show_previews enabled. Rails.application.config.after_initialize do if Rails.application.config.action_mailer.show_previews Rails::MailersController.prepend_before_action do authenticate_user! head :forbidden unless current_user.admin? end end end Coypu
A
7

It depends on what Rails version are you running, but if you are on 4.2+ adding these lines to staging.rb should help:

config.action_mailer.show_previews = true
config.consider_all_requests_local = true
Apophysis answered 31/8, 2016 at 18:19 Comment(0)
J
1

Another option would be to use a service like https://mailtrap.io/ and also get some more interesting information about the email such as spam and responsiveness analysis - I find it to be the best option for my staging environment.

Jethro answered 4/9, 2016 at 9:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.