Remove the Amazon SES ingress

It's unusable and not ready to ship in Rails 6.0. We'll rewrite it for 6.1.
This commit is contained in:
George Claghorn 2019-04-14 12:15:54 -04:00 committed by GitHub
parent 00b0c84a9b
commit f480cfabcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 30 additions and 149 deletions

View File

@ -1,6 +1,6 @@
# Action Mailbox # Action Mailbox
Action Mailbox routes incoming emails to controller-like mailboxes for processing in Rails. It ships with ingresses for Amazon SES, Mailgun, Mandrill, Postmark, and SendGrid. You can also handle inbound mails directly via the built-in Exim, Postfix, and Qmail ingresses. Action Mailbox routes incoming emails to controller-like mailboxes for processing in Rails. It ships with ingresses for Mailgun, Mandrill, Postmark, and SendGrid. You can also handle inbound mails directly via the built-in Exim, Postfix, and Qmail ingresses.
The inbound emails are turned into `InboundEmail` records using Active Record and feature lifecycle tracking, storage of the original email on cloud storage via Active Storage, and responsible data handling with on-by-default incineration. The inbound emails are turned into `InboundEmail` records using Active Record and feature lifecycle tracking, storage of the original email on cloud storage via Active Storage, and responsible data handling with on-by-default incineration.

View File

@ -7,10 +7,6 @@ module ActionMailbox
before_action :ensure_configured before_action :ensure_configured
def self.prepare
# Override in concrete controllers to run code on load.
end
private private
def ensure_configured def ensure_configured
unless ActionMailbox.ingress == ingress_name unless ActionMailbox.ingress == ingress_name

View File

@ -1,54 +0,0 @@
# frozen_string_literal: true
module ActionMailbox
# Ingests inbound emails from Amazon's Simple Email Service (SES).
#
# Requires the full RFC 822 message in the +content+ parameter. Authenticates requests by validating their signatures.
#
# Returns:
#
# - <tt>204 No Content</tt> if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox
# - <tt>401 Unauthorized</tt> if the request's signature could not be validated
# - <tt>404 Not Found</tt> if Action Mailbox is not configured to accept inbound emails from SES
# - <tt>422 Unprocessable Entity</tt> if the request is missing the required +content+ parameter
# - <tt>500 Server Error</tt> if one of the Active Record database, the Active Storage service, or
# the Active Job backend is misconfigured or unavailable
#
# == Usage
#
# 1. Install the {aws-sdk-sns}[https://rubygems.org/gems/aws-sdk-sns] gem:
#
# # Gemfile
# gem "aws-sdk-sns", ">= 1.9.0", require: false
#
# 2. Tell Action Mailbox to accept emails from SES:
#
# # config/environments/production.rb
# config.action_mailbox.ingress = :amazon
#
# 3. {Configure SES}[https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-notifications.html]
# to deliver emails to your application via POST requests to +/rails/action_mailbox/amazon/inbound_emails+.
# If your application lived at <tt>https://example.com</tt>, you would specify the fully-qualified URL
# <tt>https://example.com/rails/action_mailbox/amazon/inbound_emails</tt>.
class Ingresses::Amazon::InboundEmailsController < BaseController
before_action :authenticate
cattr_accessor :verifier
def self.prepare
self.verifier ||= begin
require "aws-sdk-sns"
Aws::SNS::MessageVerifier.new
end
end
def create
ActionMailbox::InboundEmail.create_and_extract_message_id! params.require(:content)
end
private
def authenticate
head :unauthorized unless verifier.authentic?(request.body)
end
end
end

View File

@ -2,7 +2,6 @@
Rails.application.routes.draw do Rails.application.routes.draw do
scope "/rails/action_mailbox", module: "action_mailbox/ingresses" do scope "/rails/action_mailbox", module: "action_mailbox/ingresses" do
post "/amazon/inbound_emails" => "amazon/inbound_emails#create", as: :rails_amazon_inbound_emails
post "/mandrill/inbound_emails" => "mandrill/inbound_emails#create", as: :rails_mandrill_inbound_emails post "/mandrill/inbound_emails" => "mandrill/inbound_emails#create", as: :rails_mandrill_inbound_emails
post "/postmark/inbound_emails" => "postmark/inbound_emails#create", as: :rails_postmark_inbound_emails post "/postmark/inbound_emails" => "postmark/inbound_emails#create", as: :rails_postmark_inbound_emails
post "/relay/inbound_emails" => "relay/inbound_emails#create", as: :rails_relay_inbound_emails post "/relay/inbound_emails" => "relay/inbound_emails#create", as: :rails_relay_inbound_emails

View File

@ -26,16 +26,7 @@ module ActionMailbox
ActionMailbox.incinerate = app.config.action_mailbox.incinerate.nil? ? true : app.config.action_mailbox.incinerate ActionMailbox.incinerate = app.config.action_mailbox.incinerate.nil? ? true : app.config.action_mailbox.incinerate
ActionMailbox.incinerate_after = app.config.action_mailbox.incinerate_after || 30.days ActionMailbox.incinerate_after = app.config.action_mailbox.incinerate_after || 30.days
ActionMailbox.queues = app.config.action_mailbox.queues || {} ActionMailbox.queues = app.config.action_mailbox.queues || {}
end ActionMailbox.ingress = app.config.action_mailbox.ingress
end
initializer "action_mailbox.ingress" do |app|
config.to_prepare do
if ActionMailbox.ingress = app.config.action_mailbox.ingress.presence
if ingress_controller_class = "ActionMailbox::Ingresses::#{ActionMailbox.ingress.to_s.classify}::InboundEmailsController".safe_constantize
ingress_controller_class.prepare
end
end
end end
end end
end end

View File

@ -5,6 +5,6 @@ copy_file "#{__dir__}/mailbox/templates/application_mailbox.rb", "app/mailboxes/
environment <<~end_of_config, env: "production" environment <<~end_of_config, env: "production"
# Prepare the ingress controller used to receive mail # Prepare the ingress controller used to receive mail
# config.action_mailbox.ingress = :amazon # config.action_mailbox.ingress = :postfix
end_of_config end_of_config

View File

@ -1,22 +0,0 @@
# frozen_string_literal: true
require "test_helper"
ActionMailbox::Ingresses::Amazon::InboundEmailsController.verifier =
Module.new { def self.authentic?(message); true; end }
class ActionMailbox::Ingresses::Amazon::InboundEmailsControllerTest < ActionDispatch::IntegrationTest
setup { ActionMailbox.ingress = :amazon }
test "receiving an inbound email from Amazon" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
post rails_amazon_inbound_emails_url, params: { content: file_fixture("../files/welcome.eml").read }, as: :json
end
assert_response :no_content
inbound_email = ActionMailbox::InboundEmail.last
assert_equal file_fixture("../files/welcome.eml").read, inbound_email.raw_email.download
assert_equal "0CB459E0-0336-41DA-BC88-E6E28C697DDB@37signals.com", inbound_email.message_id
end
end

View File

@ -1,9 +1,4 @@
Rails.application.configure do Rails.application.configure do
# Prepare the ingress controller used to receive mail
# config.action_mailbox.ingress = :amazon
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = false
# Settings specified here will take precedence over those in config/application.rb. # Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests. # Code is not reloaded between requests.
@ -96,4 +91,10 @@ Rails.application.configure do
# Do not dump schema after migrations. # Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false config.active_record.dump_schema_after_migration = false
# Prepare the ingress controller used to receive mail
# config.action_mailbox.ingress = :postfix
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = false
end end

View File

@ -19,9 +19,9 @@ Introduction
------------ ------------
Action Mailbox routes incoming emails to controller-like mailboxes for Action Mailbox routes incoming emails to controller-like mailboxes for
processing in Rails. It ships with ingresses for Amazon SES, Mailgun, Mandrill, processing in Rails. It ships with ingresses for Mailgun, Mandrill, Postmark,
Postmark, and SendGrid. You can also handle inbound mails directly via the and SendGrid. You can also handle inbound mails directly via the built-in Exim,
built-in Exim, Postfix, and Qmail ingresses. Postfix, and Qmail ingresses.
The inbound emails are turned into `InboundEmail` records using Active Record The inbound emails are turned into `InboundEmail` records using Active Record
and feature lifecycle tracking, storage of the original email on cloud storage and feature lifecycle tracking, storage of the original email on cloud storage
@ -43,28 +43,6 @@ $ rails db:migrate
## Configuration ## Configuration
### Amazon SES
Install the [`aws-sdk-sns`](https://rubygems.org/gems/aws-sdk-sns) gem:
```ruby
# Gemfile
gem "aws-sdk-sns", ">= 1.9.0", require: false
```
Tell Action Mailbox to accept emails from SES:
```ruby
# config/environments/production.rb
config.action_mailbox.ingress = :amazon
```
[Configure SES](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-notifications.html)
to deliver emails to your application via POST requests to
`/rails/action_mailbox/amazon/inbound_emails`. If your application lived at
`https://example.com`, you would specify the fully-qualified URL
`https://example.com/rails/action_mailbox/amazon/inbound_emails`.
### Exim ### Exim
Tell Action Mailbox to accept emails from an SMTP relay: Tell Action Mailbox to accept emails from an SMTP relay:

View File

@ -20,7 +20,6 @@ module ApplicationTests
assert_equal <<~MESSAGE, run_rake_routes assert_equal <<~MESSAGE, run_rake_routes
Prefix Verb URI Pattern Controller#Action Prefix Verb URI Pattern Controller#Action
cart GET /cart(.:format) cart#show cart GET /cart(.:format) cart#show
rails_amazon_inbound_emails POST /rails/action_mailbox/amazon/inbound_emails(.:format) action_mailbox/ingresses/amazon/inbound_emails#create
rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create
rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create
rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create

View File

@ -62,7 +62,6 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase
assert_equal <<~MESSAGE, run_routes_command([ "-g", "POST" ]) assert_equal <<~MESSAGE, run_routes_command([ "-g", "POST" ])
Prefix Verb URI Pattern Controller#Action Prefix Verb URI Pattern Controller#Action
POST /cart(.:format) cart#create POST /cart(.:format) cart#create
rails_amazon_inbound_emails POST /rails/action_mailbox/amazon/inbound_emails(.:format) action_mailbox/ingresses/amazon/inbound_emails#create
rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create
rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create
rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create
@ -166,7 +165,6 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase
assert_equal <<~MESSAGE, run_routes_command assert_equal <<~MESSAGE, run_routes_command
Prefix Verb URI Pattern Controller#Action Prefix Verb URI Pattern Controller#Action
rails_amazon_inbound_emails POST /rails/action_mailbox/amazon/inbound_emails(.:format) action_mailbox/ingresses/amazon/inbound_emails#create
rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create
rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create
rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create
@ -207,101 +205,96 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase
URI | /cart(.:format) URI | /cart(.:format)
Controller#Action | cart#show Controller#Action | cart#show
--[ Route 2 ]-------------- --[ Route 2 ]--------------
Prefix | rails_amazon_inbound_emails
Verb | POST
URI | /rails/action_mailbox/amazon/inbound_emails(.:format)
Controller#Action | action_mailbox/ingresses/amazon/inbound_emails#create
--[ Route 3 ]--------------
Prefix | rails_mandrill_inbound_emails Prefix | rails_mandrill_inbound_emails
Verb | POST Verb | POST
URI | /rails/action_mailbox/mandrill/inbound_emails(.:format) URI | /rails/action_mailbox/mandrill/inbound_emails(.:format)
Controller#Action | action_mailbox/ingresses/mandrill/inbound_emails#create Controller#Action | action_mailbox/ingresses/mandrill/inbound_emails#create
--[ Route 4 ]-------------- --[ Route 3 ]--------------
Prefix | rails_postmark_inbound_emails Prefix | rails_postmark_inbound_emails
Verb | POST Verb | POST
URI | /rails/action_mailbox/postmark/inbound_emails(.:format) URI | /rails/action_mailbox/postmark/inbound_emails(.:format)
Controller#Action | action_mailbox/ingresses/postmark/inbound_emails#create Controller#Action | action_mailbox/ingresses/postmark/inbound_emails#create
--[ Route 5 ]-------------- --[ Route 4 ]--------------
Prefix | rails_relay_inbound_emails Prefix | rails_relay_inbound_emails
Verb | POST Verb | POST
URI | /rails/action_mailbox/relay/inbound_emails(.:format) URI | /rails/action_mailbox/relay/inbound_emails(.:format)
Controller#Action | action_mailbox/ingresses/relay/inbound_emails#create Controller#Action | action_mailbox/ingresses/relay/inbound_emails#create
--[ Route 6 ]-------------- --[ Route 5 ]--------------
Prefix | rails_sendgrid_inbound_emails Prefix | rails_sendgrid_inbound_emails
Verb | POST Verb | POST
URI | /rails/action_mailbox/sendgrid/inbound_emails(.:format) URI | /rails/action_mailbox/sendgrid/inbound_emails(.:format)
Controller#Action | action_mailbox/ingresses/sendgrid/inbound_emails#create Controller#Action | action_mailbox/ingresses/sendgrid/inbound_emails#create
--[ Route 7 ]-------------- --[ Route 6 ]--------------
Prefix | rails_mailgun_inbound_emails Prefix | rails_mailgun_inbound_emails
Verb | POST Verb | POST
URI | /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) URI | /rails/action_mailbox/mailgun/inbound_emails/mime(.:format)
Controller#Action | action_mailbox/ingresses/mailgun/inbound_emails#create Controller#Action | action_mailbox/ingresses/mailgun/inbound_emails#create
--[ Route 8 ]-------------- --[ Route 7 ]--------------
Prefix | rails_conductor_inbound_emails Prefix | rails_conductor_inbound_emails
Verb | GET Verb | GET
URI | /rails/conductor/action_mailbox/inbound_emails(.:format) URI | /rails/conductor/action_mailbox/inbound_emails(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#index Controller#Action | rails/conductor/action_mailbox/inbound_emails#index
--[ Route 9 ]-------------- --[ Route 8 ]--------------
Prefix | Prefix |
Verb | POST Verb | POST
URI | /rails/conductor/action_mailbox/inbound_emails(.:format) URI | /rails/conductor/action_mailbox/inbound_emails(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#create Controller#Action | rails/conductor/action_mailbox/inbound_emails#create
--[ Route 10 ]------------- --[ Route 9 ]--------------
Prefix | new_rails_conductor_inbound_email Prefix | new_rails_conductor_inbound_email
Verb | GET Verb | GET
URI | /rails/conductor/action_mailbox/inbound_emails/new(.:format) URI | /rails/conductor/action_mailbox/inbound_emails/new(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#new Controller#Action | rails/conductor/action_mailbox/inbound_emails#new
--[ Route 11 ]------------- --[ Route 10 ]-------------
Prefix | edit_rails_conductor_inbound_email Prefix | edit_rails_conductor_inbound_email
Verb | GET Verb | GET
URI | /rails/conductor/action_mailbox/inbound_emails/:id/edit(.:format) URI | /rails/conductor/action_mailbox/inbound_emails/:id/edit(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#edit Controller#Action | rails/conductor/action_mailbox/inbound_emails#edit
--[ Route 12 ]------------- --[ Route 11 ]-------------
Prefix | rails_conductor_inbound_email Prefix | rails_conductor_inbound_email
Verb | GET Verb | GET
URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#show Controller#Action | rails/conductor/action_mailbox/inbound_emails#show
--[ Route 13 ]------------- --[ Route 12 ]-------------
Prefix | Prefix |
Verb | PATCH Verb | PATCH
URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#update Controller#Action | rails/conductor/action_mailbox/inbound_emails#update
--[ Route 14 ]------------- --[ Route 13 ]-------------
Prefix | Prefix |
Verb | PUT Verb | PUT
URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#update Controller#Action | rails/conductor/action_mailbox/inbound_emails#update
--[ Route 15 ]------------- --[ Route 14 ]-------------
Prefix | Prefix |
Verb | DELETE Verb | DELETE
URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#destroy Controller#Action | rails/conductor/action_mailbox/inbound_emails#destroy
--[ Route 16 ]------------- --[ Route 15 ]-------------
Prefix | rails_conductor_inbound_email_reroute Prefix | rails_conductor_inbound_email_reroute
Verb | POST Verb | POST
URI | /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) URI | /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)
Controller#Action | rails/conductor/action_mailbox/reroutes#create Controller#Action | rails/conductor/action_mailbox/reroutes#create
--[ Route 17 ]------------- --[ Route 16 ]-------------
Prefix | rails_service_blob Prefix | rails_service_blob
Verb | GET Verb | GET
URI | /rails/active_storage/blobs/:signed_id/*filename(.:format) URI | /rails/active_storage/blobs/:signed_id/*filename(.:format)
Controller#Action | active_storage/blobs#show Controller#Action | active_storage/blobs#show
--[ Route 18 ]------------- --[ Route 17 ]-------------
Prefix | rails_blob_representation Prefix | rails_blob_representation
Verb | GET Verb | GET
URI | /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) URI | /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format)
Controller#Action | active_storage/representations#show Controller#Action | active_storage/representations#show
--[ Route 19 ]------------- --[ Route 18 ]-------------
Prefix | rails_disk_service Prefix | rails_disk_service
Verb | GET Verb | GET
URI | /rails/active_storage/disk/:encoded_key/*filename(.:format) URI | /rails/active_storage/disk/:encoded_key/*filename(.:format)
Controller#Action | active_storage/disk#show Controller#Action | active_storage/disk#show
--[ Route 20 ]------------- --[ Route 19 ]-------------
Prefix | update_rails_disk_service Prefix | update_rails_disk_service
Verb | PUT Verb | PUT
URI | /rails/active_storage/disk/:encoded_token(.:format) URI | /rails/active_storage/disk/:encoded_token(.:format)
Controller#Action | active_storage/disk#update Controller#Action | active_storage/disk#update
--[ Route 21 ]------------- --[ Route 20 ]-------------
Prefix | rails_direct_uploads Prefix | rails_direct_uploads
Verb | POST Verb | POST
URI | /rails/active_storage/direct_uploads(.:format) URI | /rails/active_storage/direct_uploads(.:format)