diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md
index 3a852ad7ef5ea..42662e61c694b 100644
--- a/actionmailbox/CHANGELOG.md
+++ b/actionmailbox/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Add way to deliver emails via source instead of filling out a form through the conductor interface.
+
+ *DHH*
+
* Mailgun ingress now passes through the envelope recipient as `X-Original-To`.
*Rikki Pitt*
diff --git a/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller.rb b/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller.rb
new file mode 100644
index 0000000000000..bfc013e9bcf10
--- /dev/null
+++ b/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Rails
+ class Conductor::ActionMailbox::InboundEmails::SourcesController < Rails::Conductor::BaseController
+ def new
+ end
+
+ def create
+ inbound_email = ActionMailbox::InboundEmail.create_and_extract_message_id! params[:source]
+ redirect_to main_app.rails_conductor_inbound_email_url(inbound_email)
+ end
+ end
+end
diff --git a/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/index.html.erb b/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/index.html.erb
index 19c53984e202e..dd501b398c527 100644
--- a/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/index.html.erb
+++ b/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/index.html.erb
@@ -12,4 +12,5 @@
<% end %>
-<%= link_to "Deliver new inbound email", main_app.new_rails_conductor_inbound_email_path %>
\ No newline at end of file
+<%= link_to "New inbound email by form", main_app.new_rails_conductor_inbound_email_path %> |
+<%= link_to "New inbound email by source", main_app.new_rails_conductor_inbound_email_source_path %>
diff --git a/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/sources/new.html.erb b/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/sources/new.html.erb
new file mode 100644
index 0000000000000..637efeda03155
--- /dev/null
+++ b/actionmailbox/app/views/rails/conductor/action_mailbox/inbound_emails/sources/new.html.erb
@@ -0,0 +1,12 @@
+<% provide :title, "Deliver new inbound email by source" %>
+
+
Deliver new inbound email by source
+
+<%= form_with(url: main_app.rails_conductor_inbound_email_sources_path, local: true) do |form| %>
+
+ <%= form.label :source, "Source" %>
+ <%= form.text_area :source, size: "80x60" %>
+
+
+ <%= form.submit "Deliver inbound email" %>
+<% end %>
diff --git a/actionmailbox/config/routes.rb b/actionmailbox/config/routes.rb
index 1496d6f0b3728..9a47f02c1b4cb 100644
--- a/actionmailbox/config/routes.rb
+++ b/actionmailbox/config/routes.rb
@@ -14,6 +14,9 @@
# TODO: Should these be mounted within the engine only?
scope "rails/conductor/action_mailbox/", module: "rails/conductor/action_mailbox" do
resources :inbound_emails, as: :rails_conductor_inbound_emails
+ get "inbound_emails/sources/new", to: "inbound_emails/sources#new", as: :new_rails_conductor_inbound_email_source
+ post "inbound_emails/sources", to: "inbound_emails/sources#create", as: :rails_conductor_inbound_email_sources
+
post ":inbound_email_id/reroute" => "reroutes#create", as: :rails_conductor_inbound_email_reroute
end
end
diff --git a/railties/test/application/rake/routes_test.rb b/railties/test/application/rake/routes_test.rb
index dffdae7bdec2d..70c2ea6b4990a 100644
--- a/railties/test/application/rake/routes_test.rb
+++ b/railties/test/application/rake/routes_test.rb
@@ -33,6 +33,8 @@ class RakeRoutesTest < ActiveSupport::TestCase
PATCH /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#update
PUT /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#update
DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#destroy
+ new_rails_conductor_inbound_email_source GET /rails/conductor/action_mailbox/inbound_emails/sources/new(.:format) rails/conductor/action_mailbox/inbound_emails/sources#new
+ rails_conductor_inbound_email_sources POST /rails/conductor/action_mailbox/inbound_emails/sources(.:format) rails/conductor/action_mailbox/inbound_emails/sources#create
rails_conductor_inbound_email_reroute POST /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) rails/conductor/action_mailbox/reroutes#create
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
diff --git a/railties/test/commands/routes_test.rb b/railties/test/commands/routes_test.rb
index 0ec4243de40bd..8155f5e615fdb 100644
--- a/railties/test/commands/routes_test.rb
+++ b/railties/test/commands/routes_test.rb
@@ -68,6 +68,7 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase
rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create
rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create
POST /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#create
+ rails_conductor_inbound_email_sources POST /rails/conductor/action_mailbox/inbound_emails/sources(.:format) rails/conductor/action_mailbox/inbound_emails/sources#create
rails_conductor_inbound_email_reroute POST /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) rails/conductor/action_mailbox/reroutes#create
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
MESSAGE
@@ -178,6 +179,8 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase
PATCH /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#update
PUT /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#update
DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#destroy
+ new_rails_conductor_inbound_email_source GET /rails/conductor/action_mailbox/inbound_emails/sources/new(.:format) rails/conductor/action_mailbox/inbound_emails/sources#new
+ rails_conductor_inbound_email_sources POST /rails/conductor/action_mailbox/inbound_emails/sources(.:format) rails/conductor/action_mailbox/inbound_emails/sources#create
rails_conductor_inbound_email_reroute POST /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) rails/conductor/action_mailbox/reroutes#create
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
@@ -271,31 +274,41 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase
URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format)
Controller#Action | rails/conductor/action_mailbox/inbound_emails#destroy
--[ Route 15 ]-------------
+ Prefix | new_rails_conductor_inbound_email_source
+ Verb | GET
+ URI | /rails/conductor/action_mailbox/inbound_emails/sources/new(.:format)
+ Controller#Action | rails/conductor/action_mailbox/inbound_emails/sources#new
+ --[ Route 16 ]-------------
+ Prefix | rails_conductor_inbound_email_sources
+ Verb | POST
+ URI | /rails/conductor/action_mailbox/inbound_emails/sources(.:format)
+ Controller#Action | rails/conductor/action_mailbox/inbound_emails/sources#create
+ --[ Route 17 ]-------------
Prefix | rails_conductor_inbound_email_reroute
Verb | POST
URI | /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)
Controller#Action | rails/conductor/action_mailbox/reroutes#create
- --[ Route 16 ]-------------
+ --[ Route 18 ]-------------
Prefix | rails_service_blob
Verb | GET
URI | /rails/active_storage/blobs/:signed_id/*filename(.:format)
Controller#Action | active_storage/blobs#show
- --[ Route 17 ]-------------
+ --[ Route 19 ]-------------
Prefix | rails_blob_representation
Verb | GET
URI | /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format)
Controller#Action | active_storage/representations#show
- --[ Route 18 ]-------------
+ --[ Route 20 ]-------------
Prefix | rails_disk_service
Verb | GET
URI | /rails/active_storage/disk/:encoded_key/*filename(.:format)
Controller#Action | active_storage/disk#show
- --[ Route 19 ]-------------
+ --[ Route 21 ]-------------
Prefix | update_rails_disk_service
Verb | PUT
URI | /rails/active_storage/disk/:encoded_token(.:format)
Controller#Action | active_storage/disk#update
- --[ Route 20 ]-------------
+ --[ Route 22 ]-------------
Prefix | rails_direct_uploads
Verb | POST
URI | /rails/active_storage/direct_uploads(.:format)