Rails 6 ActionMailbox with Mailgun returning 404

Viewed 364

I am developing an in-house expenses application on Rails 6 with ActionMailbox to replace Excel spreadsheets. As many of our receipts are now in email form (for example airline tickets), the idea is that users will be able to simply forward a receipt to the application and it will automatically be associated with the expense entry.

I am using ActionMailbox with Mailgun as the email receiver. As suggested by the Gorails Pro tutorial I have exposed my app using localtunnel to the general Internet. I have used Mailgun's facility to send a test email to my application.

My post address is:

https://xxxxxxxx.localtunnel.me/rails/action_mailbox/mailgun/inbound_emails/mime

However, I have run into an issue where the incoming email from Mailgun is not being processed correctly but is being returned with a 404 error. The Rails log shows the message being received as a POST. The last two entries in the log are:

2019-10-15T07:50:07.646Z 10260 TID-gn609ivg8 INFO: Filter chain halted as :ensure_configured rendered or redirected
2019-10-15T07:50:07.646Z 10260 TID-gn609ivg8 INFO: Completed 404 Not Found in 0ms (ActiveRecord: 0.0ms | Allocations: 144)

My configuration is: config/routes.rb

Rails.application.routes.draw do
  devise_for :users
  resources :categories

  resources :expense_claims do
    get 'export_excel', on: :member
    post 'barclay_csv_import', on: :collection
  end

  resources :expense_entries

  root 'expense_claims#index'

  # Enable the sidekiq console.
  require 'sidekiq/web'
  mount Sidekiq::Web => '/sidekiq'
end

config/application.rb

module Expenses
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    # Set the ActionMailbox ingress here for now.
    config.action_mailbox.ingress = :mail_gun
  end
end

config/environments/development.rb

Rails.application.configure do

  [... lot of stuff removed as not relevant]
  # Settings specified here will take precedence over those in config/application.rb.
  config.action_mailer.default_url_options = { host: '0.0.0.0', port: 3000 }
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = { address: '0.0.0.0', port: 1025 }

  # Set the active job queue adapter to Sidekiq/Redis
  # config.active_job.queue_adapter = :sidekiq
  # Alternatively, when debugging, you can set to in-line (or :async)
  config.active_job.queue_adapter = :inline

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false

  config.action_mailer.perform_caching = false


  # Set so we can test Devise self registration
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

  # Allow traffic from localtunnel
  config.hosts << 'xxxxxx.localtunnel.me'
end

app/mailboxes/application_mailbox.rb

class ApplicationMailbox < ActionMailbox::Base
  routing :all => :receipt
end

app/mailboxes/receipt_mailbox.rb

class ReceiptMailbox < ApplicationMailbox
  # mail => Mail object
  # inbound_email => ActionMailboxEmail record
  def process

  end
end
1 Answers

Well, turns out it was the most stupid of mistakes. In config/application.rb the final configuration was wrong. I needed to replace :mail_gun with :mailgun:

    # Set the ActionMailbox ingress here for now.
    config.action_mailbox.ingress = :mailgun

Unfortunately, the Rails error message was not very helpful here.

To give a little more info, ActionMailbox has a number of different routes defined for different email processors. Therefore, the URL to which the email processor posts the incoming email defines the controller to use. On receiving an email, Rails checks that the URL to which the email has been posted matches the ingress class that is set in the config. If not, you get the error I saw.

Related