mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #34812 from bogdanvlviv/action_mailbox-guides-docs
Add Action Mailbox to guides
This commit is contained in:
commit
a1be11fcbf
5 changed files with 324 additions and 314 deletions
|
@ -6,273 +6,7 @@ The inbound emails are turned into `InboundEmail` records using Active Record an
|
||||||
|
|
||||||
These inbound emails are routed asynchronously using Active Job to one or several dedicated mailboxes, which are capable of interacting directly with the rest of your domain model.
|
These inbound emails are routed asynchronously using Active Job to one or several dedicated mailboxes, which are capable of interacting directly with the rest of your domain model.
|
||||||
|
|
||||||
|
You can read more about Action Mailbox in the [Action Mailbox Basics](https://edgeguides.rubyonrails.org/action_mailbox_basics.html) guide.
|
||||||
## How does this compare to Action Mailer's inbound processing?
|
|
||||||
|
|
||||||
Rails has long had an anemic way of [receiving emails using Action Mailer](https://guides.rubyonrails.org/action_mailer_basics.html#receiving-emails), but it was poorly fleshed out, lacked cohesion with the task of sending emails, and offered no help on integrating with popular inbound email processing platforms. Action Mailbox supersedes the receiving part of Action Mailer, which will be deprecated in due course.
|
|
||||||
|
|
||||||
|
|
||||||
## Installing
|
|
||||||
|
|
||||||
Assumes a Rails 5.2+ application:
|
|
||||||
|
|
||||||
1. Install the gem:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# Gemfile
|
|
||||||
gem "actionmailbox", github: "rails/actionmailbox", require: "action_mailbox"
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Install migrations needed for InboundEmail (and ensure Active Storage is setup)
|
|
||||||
|
|
||||||
```
|
|
||||||
./bin/rails action_mailbox:install
|
|
||||||
./bin/rails db:migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuring
|
|
||||||
|
|
||||||
### Amazon SES
|
|
||||||
|
|
||||||
1. Install the [`aws-sdk-sns`](https://rubygems.org/gems/aws-sdk-sns) gem:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# Gemfile
|
|
||||||
gem "aws-sdk-sns", ">= 1.9.0", require: false
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Tell Action Mailbox to accept emails from SES:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# config/environments/production.rb
|
|
||||||
config.action_mailbox.ingress = :amazon
|
|
||||||
```
|
|
||||||
|
|
||||||
3. [Configure SES][ses-docs] 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`.
|
|
||||||
|
|
||||||
[ses-docs]: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-notifications.html
|
|
||||||
|
|
||||||
### Mailgun
|
|
||||||
|
|
||||||
1. Give Action Mailbox your [Mailgun API key][mailgun-api-key] so it can authenticate requests to the Mailgun ingress.
|
|
||||||
|
|
||||||
Use `rails credentials:edit` to add your API key to your application's encrypted credentials under
|
|
||||||
`action_mailbox.mailgun_api_key`, where Action Mailbox will automatically find it:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
action_mailbox:
|
|
||||||
mailgun_api_key: ...
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, provide your API key in the `MAILGUN_INGRESS_API_KEY` environment variable.
|
|
||||||
|
|
||||||
2. Tell Action Mailbox to accept emails from Mailgun:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# config/environments/production.rb
|
|
||||||
config.action_mailbox.ingress = :mailgun
|
|
||||||
```
|
|
||||||
|
|
||||||
3. [Configure Mailgun][mailgun-forwarding] to forward inbound emails to `/rails/action_mailbox/mailgun/inbound_emails/mime`.
|
|
||||||
If your application lived at `https://example.com`, you would specify the fully-qualified URL
|
|
||||||
`https://example.com/rails/action_mailbox/mailgun/inbound_emails/mime`.
|
|
||||||
|
|
||||||
[mailgun-api-key]: https://help.mailgun.com/hc/en-us/articles/203380100-Where-can-I-find-my-API-key-and-SMTP-credentials-
|
|
||||||
[mailgun-forwarding]: https://documentation.mailgun.com/en/latest/user_manual.html#receiving-forwarding-and-storing-messages
|
|
||||||
|
|
||||||
### Mandrill
|
|
||||||
|
|
||||||
1. Give Action Mailbox your Mandrill API key so it can authenticate requests to the Mandrill ingress.
|
|
||||||
|
|
||||||
Use `rails credentials:edit` to add your API key to your application's encrypted credentials under
|
|
||||||
`action_mailbox.mandrill_api_key`, where Action Mailbox will automatically find it:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
action_mailbox:
|
|
||||||
mandrill_api_key: ...
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, provide your API key in the `MANDRILL_INGRESS_API_KEY` environment variable.
|
|
||||||
|
|
||||||
2. Tell Action Mailbox to accept emails from Mandrill:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# config/environments/production.rb
|
|
||||||
config.action_mailbox.ingress = :mandrill
|
|
||||||
```
|
|
||||||
|
|
||||||
3. [Configure Mandrill][mandrill-routing] to route inbound emails to `/rails/action_mailbox/mandrill/inbound_emails`.
|
|
||||||
If your application lived at `https://example.com`, you would specify the fully-qualified URL
|
|
||||||
`https://example.com/rails/action_mailbox/mandrill/inbound_emails`.
|
|
||||||
|
|
||||||
[mandrill-routing]: https://mandrill.zendesk.com/hc/en-us/articles/205583197-Inbound-Email-Processing-Overview
|
|
||||||
|
|
||||||
### Postfix
|
|
||||||
|
|
||||||
1. Tell Action Mailbox to accept emails from Postfix:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# config/environments/production.rb
|
|
||||||
config.action_mailbox.ingress = :postfix
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Generate a strong password that Action Mailbox can use to authenticate requests to the Postfix ingress.
|
|
||||||
|
|
||||||
Use `rails credentials:edit` to add the password to your application's encrypted credentials under
|
|
||||||
`action_mailbox.ingress_password`, where Action Mailbox will automatically find it:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
action_mailbox:
|
|
||||||
ingress_password: ...
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` environment variable.
|
|
||||||
|
|
||||||
3. [Configure Postfix][postfix-config] to pipe inbound emails to `bin/rails action_mailbox:ingress:postfix`, providing
|
|
||||||
the `URL` of the Postfix ingress and the `INGRESS_PASSWORD` you previously generated. If your application lived at
|
|
||||||
`https://example.com`, the full command would look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
URL=https://example.com/rails/action_mailbox/postfix/inbound_emails INGRESS_PASSWORD=... bin/rails action_mailbox:ingress:postfix
|
|
||||||
```
|
|
||||||
|
|
||||||
[postfix-config]: https://serverfault.com/questions/258469/how-to-configure-postfix-to-pipe-all-incoming-email-to-a-script
|
|
||||||
|
|
||||||
### SendGrid
|
|
||||||
|
|
||||||
1. Tell Action Mailbox to accept emails from SendGrid:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# config/environments/production.rb
|
|
||||||
config.action_mailbox.ingress = :sendgrid
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Generate a strong password that Action Mailbox can use to authenticate requests to the SendGrid ingress.
|
|
||||||
|
|
||||||
Use `rails credentials:edit` to add the password to your application's encrypted credentials under
|
|
||||||
`action_mailbox.ingress_password`, where Action Mailbox will automatically find it:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
action_mailbox:
|
|
||||||
ingress_password: ...
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` environment variable.
|
|
||||||
|
|
||||||
3. [Configure SendGrid Inbound Parse][sendgrid-config] to forward inbound emails to
|
|
||||||
`/rails/action_mailbox/sendgrid/inbound_emails` with the username `actionmailbox` and the password you previously
|
|
||||||
generated. If your application lived at `https://example.com`, you would configure SendGrid with the following URL:
|
|
||||||
|
|
||||||
```
|
|
||||||
https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/sendgrid/inbound_emails
|
|
||||||
```
|
|
||||||
|
|
||||||
**⚠️ Note:** When configuring your SendGrid Inbound Parse webhook, be sure to check the box labeled **“Post the raw,
|
|
||||||
full MIME message.”** Action Mailbox needs the raw MIME message to work.
|
|
||||||
|
|
||||||
[sendgrid-config]: https://sendgrid.com/docs/for-developers/parsing-email/setting-up-the-inbound-parse-webhook/
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Configure basic routing:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# app/mailboxes/application_mailbox.rb
|
|
||||||
class ApplicationMailbox < ActionMailbox::Base
|
|
||||||
routing /^save@/i => :forwards
|
|
||||||
routing /@replies\./i => :replies
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Then setup a mailbox:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# Generate new mailbox
|
|
||||||
bin/rails generate mailbox forwards
|
|
||||||
```
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
# app/mailboxes/forwards_mailbox.rb
|
|
||||||
class ForwardsMailbox < ApplicationMailbox
|
|
||||||
# Callbacks specify prerequisites to processing
|
|
||||||
before_processing :require_forward
|
|
||||||
|
|
||||||
def process
|
|
||||||
if forwarder.buckets.one?
|
|
||||||
record_forward
|
|
||||||
else
|
|
||||||
stage_forward_and_request_more_details
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def require_forward
|
|
||||||
unless message.forward?
|
|
||||||
# Use Action Mailers to bounce incoming emails back to sender – this halts processing
|
|
||||||
bounce_with Forwards::BounceMailer.missing_forward(
|
|
||||||
inbound_email, forwarder: forwarder
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def forwarder
|
|
||||||
@forwarder ||= Person.where(email_address: mail.from)
|
|
||||||
end
|
|
||||||
|
|
||||||
def record_forward
|
|
||||||
forwarder.buckets.first.record \
|
|
||||||
Forward.new forwarder: forwarder, subject: message.subject, content: mail.content
|
|
||||||
end
|
|
||||||
|
|
||||||
def stage_forward_and_request_more_details
|
|
||||||
Forwards::RoutingMailer.choose_project(mail).deliver_now
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
## Incineration of InboundEmails
|
|
||||||
|
|
||||||
By default, an InboundEmail that has been successfully processed will be incinerated after 30 days. This ensures you're not holding on to people's data willy-nilly after they may have canceled their accounts or deleted their content. The intention is that after you've processed an email, you should have extracted all the data you needed and turned it into domain models and content on your side of the application. The InboundEmail simply stays in the system for the extra time to provide debugging and forensics options.
|
|
||||||
|
|
||||||
The actual incineration is done via the `IncinerationJob` that's scheduled to run after `config.action_mailbox.incinerate_after` time. This value is by default set to `30.days`, but you can change it in your production.rb configuration. (Note that this far-future incineration scheduling relies on your job queue being able to hold jobs for that long.)
|
|
||||||
|
|
||||||
|
|
||||||
## Working with Action Mailbox in development
|
|
||||||
|
|
||||||
It's helpful to be able to test incoming emails in development without actually sending and receiving real emails. To accomplish this, there's a conductor controller mounted at `/rails/conductor/action_mailbox/inbound_emails`, which gives you an index of all the InboundEmails in the system, their state of processing, and a form to create a new InboundEmail as well.
|
|
||||||
|
|
||||||
|
|
||||||
## Testing mailboxes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
class ForwardsMailboxTest < ActionMailbox::TestCase
|
|
||||||
test "directly recording a client forward for a forwarder and forwardee corresponding to one project" do
|
|
||||||
assert_difference -> { people(:david).buckets.first.recordings.count } do
|
|
||||||
receive_inbound_email_from_mail \
|
|
||||||
to: 'save@example.com',
|
|
||||||
from: people(:david).email_address,
|
|
||||||
subject: "Fwd: Status update?",
|
|
||||||
body: <<~BODY
|
|
||||||
--- Begin forwarded message ---
|
|
||||||
From: Frank Holland <frank@microsoft.com>
|
|
||||||
|
|
||||||
What's the status?
|
|
||||||
BODY
|
|
||||||
end
|
|
||||||
|
|
||||||
recording = people(:david).buckets.first.recordings.last
|
|
||||||
assert_equal people(:david), recording.creator
|
|
||||||
assert_equal "Status update?", recording.forward.subject
|
|
||||||
assert_match "What's the status?", recording.forward.content.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ Ruby on Rails 6.0 Release Notes
|
||||||
|
|
||||||
Highlights in Rails 6.0:
|
Highlights in Rails 6.0:
|
||||||
|
|
||||||
|
* Action Mailbox
|
||||||
* Parallel Testing
|
* Parallel Testing
|
||||||
|
|
||||||
These release notes cover only the major changes. To learn about various bug
|
These release notes cover only the major changes. To learn about various bug
|
||||||
|
@ -28,6 +29,14 @@ guide.
|
||||||
Major Features
|
Major Features
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
### Action Mailbox
|
||||||
|
|
||||||
|
[Pull Request](https://github.com/rails/rails/pull/34786)
|
||||||
|
|
||||||
|
[Action Mailbox](https://github.com/rails/rails/tree/6-0-stable/actionmailbox) allows you
|
||||||
|
to route incoming emails to controller-like mailboxes.
|
||||||
|
You can read more about Action Mailbox in the [Action Mailbox Basics](action_mailbox_basics.html) guide.
|
||||||
|
|
||||||
### Parallel Testing
|
### Parallel Testing
|
||||||
|
|
||||||
[Pull Request](https://github.com/rails/rails/pull/31900)
|
[Pull Request](https://github.com/rails/rails/pull/31900)
|
||||||
|
|
302
guides/source/action_mailbox_basics.md
Normal file
302
guides/source/action_mailbox_basics.md
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
**DO NOT READ THIS FILE ON GITHUB, GUIDES ARE PUBLISHED ON https://guides.rubyonrails.org.**
|
||||||
|
|
||||||
|
Action Mailbox Basics
|
||||||
|
=====================
|
||||||
|
|
||||||
|
This guide provides you with all you need to get started in receiving
|
||||||
|
emails to your application.
|
||||||
|
|
||||||
|
After reading this guide, you will know:
|
||||||
|
|
||||||
|
* How to receive email within a Rails application.
|
||||||
|
* How to configure Action Mailbox.
|
||||||
|
* How to generate and route emails to a mailbox.
|
||||||
|
* How to test incoming emails.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
Action Mailbox routes incoming emails to controller-like mailboxes for
|
||||||
|
processing in Rails. It ships with ingresses for Amazon SES, Mailgun, Mandrill,
|
||||||
|
and SendGrid. You can also handle inbound mails directly via the built-in
|
||||||
|
Postfix ingress.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
These inbound emails are routed asynchronously using Active Job to one or
|
||||||
|
several dedicated mailboxes, which are capable of interacting directly
|
||||||
|
with the rest of your domain model.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Install migrations needed for `InboundEmail` and ensure Active Storage is set up:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ rails action_mailbox:install
|
||||||
|
$ rails db:migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
|
||||||
|
### Mailgun
|
||||||
|
|
||||||
|
Give Action Mailbox your
|
||||||
|
[Mailgun API key](https://help.mailgun.com/hc/en-us/articles/203380100-Where-can-I-find-my-API-key-and-SMTP-credentials)
|
||||||
|
so it can authenticate requests to the Mailgun ingress.
|
||||||
|
|
||||||
|
Use `rails credentials:edit` to add your API key to your application's
|
||||||
|
encrypted credentials under `action_mailbox.mailgun_api_key`,
|
||||||
|
where Action Mailbox will automatically find it:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
action_mailbox:
|
||||||
|
mailgun_api_key: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, provide your API key in the `MAILGUN_INGRESS_API_KEY` environment
|
||||||
|
variable.
|
||||||
|
|
||||||
|
Tell Action Mailbox to accept emails from Mailgun:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# config/environments/production.rb
|
||||||
|
config.action_mailbox.ingress = :mailgun
|
||||||
|
```
|
||||||
|
|
||||||
|
[Configure Mailgun](https://documentation.mailgun.com/en/latest/user_manual.html#receiving-forwarding-and-storing-messages)
|
||||||
|
to forward inbound emails to `/rails/action_mailbox/mailgun/inbound_emails/mime`.
|
||||||
|
If your application lived at `https://example.com`, you would specify the
|
||||||
|
fully-qualified URL `https://example.com/rails/action_mailbox/mailgun/inbound_emails/mime`.
|
||||||
|
|
||||||
|
### Mandrill
|
||||||
|
|
||||||
|
Give Action Mailbox your Mandrill API key so it can authenticate requests to
|
||||||
|
the Mandrill ingress.
|
||||||
|
|
||||||
|
Use `rails credentials:edit` to add your API key to your application's
|
||||||
|
encrypted credentials under `action_mailbox.mandrill_api_key`,
|
||||||
|
where Action Mailbox will automatically find it:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
action_mailbox:
|
||||||
|
mandrill_api_key: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, provide your API key in the `MANDRILL_INGRESS_API_KEY`
|
||||||
|
environment variable.
|
||||||
|
|
||||||
|
Tell Action Mailbox to accept emails from Mandrill:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# config/environments/production.rb
|
||||||
|
config.action_mailbox.ingress = :mandrill
|
||||||
|
```
|
||||||
|
|
||||||
|
[Configure Mandrill](https://mandrill.zendesk.com/hc/en-us/articles/205583197-Inbound-Email-Processing-Overview)
|
||||||
|
to route inbound emails to `/rails/action_mailbox/mandrill/inbound_emails`.
|
||||||
|
If your application lived at `https://example.com`, you would specify
|
||||||
|
the fully-qualified URL `https://example.com/rails/action_mailbox/mandrill/inbound_emails`.
|
||||||
|
|
||||||
|
### Postfix
|
||||||
|
|
||||||
|
Tell Action Mailbox to accept emails from Postfix:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# config/environments/production.rb
|
||||||
|
config.action_mailbox.ingress = :postfix
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate a strong password that Action Mailbox can use to authenticate requests to the Postfix ingress.
|
||||||
|
|
||||||
|
Use `rails credentials:edit` to add the password to your application's encrypted credentials under
|
||||||
|
`action_mailbox.ingress_password`, where Action Mailbox will automatically find it:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
action_mailbox:
|
||||||
|
ingress_password: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` environment variable.
|
||||||
|
|
||||||
|
[Configure Postfix](https://serverfault.com/questions/258469/how-to-configure-postfix-to-pipe-all-incoming-email-to-a-script)
|
||||||
|
to pipe inbound emails to `bin/rails action_mailbox:ingress:postfix`, providing
|
||||||
|
the `URL` of the Postfix ingress and the `INGRESS_PASSWORD` you previously
|
||||||
|
generated. If your application lived at `https://example.com`, the full command
|
||||||
|
would look like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ URL=https://example.com/rails/action_mailbox/postfix/inbound_emails INGRESS_PASSWORD=... rails action_mailbox:ingress:postfix
|
||||||
|
```
|
||||||
|
|
||||||
|
### SendGrid
|
||||||
|
|
||||||
|
Tell Action Mailbox to accept emails from SendGrid:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# config/environments/production.rb
|
||||||
|
config.action_mailbox.ingress = :sendgrid
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate a strong password that Action Mailbox can use to authenticate
|
||||||
|
requests to the SendGrid ingress.
|
||||||
|
|
||||||
|
Use `rails credentials:edit` to add the password to your application's
|
||||||
|
encrypted credentials under `action_mailbox.ingress_password`,
|
||||||
|
where Action Mailbox will automatically find it:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
action_mailbox:
|
||||||
|
ingress_password: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD`
|
||||||
|
environment variable.
|
||||||
|
|
||||||
|
[Configure SendGrid Inbound Parse](https://sendgrid.com/docs/for-developers/parsing-email/setting-up-the-inbound-parse-webhook/)
|
||||||
|
to forward inbound emails to
|
||||||
|
`/rails/action_mailbox/sendgrid/inbound_emails` with the username `actionmailbox`
|
||||||
|
and the password you previously generated. If your application lived at `https://example.com`,
|
||||||
|
you would configure SendGrid with the following URL:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/sendgrid/inbound_emails
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: When configuring your SendGrid Inbound Parse webhook, be sure to check the box labeled **“Post the raw, full MIME message.”** Action Mailbox needs the raw MIME message to work.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Configure basic routing:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# app/mailboxes/application_mailbox.rb
|
||||||
|
class ApplicationMailbox < ActionMailbox::Base
|
||||||
|
routing /^save@/i => :forwards
|
||||||
|
routing /@replies\./i => :replies
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Then set up a mailbox:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# Generate new mailbox
|
||||||
|
$ bin/rails generate mailbox forwards
|
||||||
|
```
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# app/mailboxes/forwards_mailbox.rb
|
||||||
|
class ForwardsMailbox < ApplicationMailbox
|
||||||
|
# Callbacks specify prerequisites to processing
|
||||||
|
before_processing :require_forward
|
||||||
|
|
||||||
|
def process
|
||||||
|
if forwarder.buckets.one?
|
||||||
|
record_forward
|
||||||
|
else
|
||||||
|
stage_forward_and_request_more_details
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def require_forward
|
||||||
|
unless message.forward?
|
||||||
|
# Use Action Mailers to bounce incoming emails back to sender – this halts processing
|
||||||
|
bounce_with Forwards::BounceMailer.missing_forward(
|
||||||
|
inbound_email, forwarder: forwarder
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def forwarder
|
||||||
|
@forwarder ||= Person.where(email_address: mail.from)
|
||||||
|
end
|
||||||
|
|
||||||
|
def record_forward
|
||||||
|
forwarder.buckets.first.record \
|
||||||
|
Forward.new forwarder: forwarder, subject: message.subject, content: mail.content
|
||||||
|
end
|
||||||
|
|
||||||
|
def stage_forward_and_request_more_details
|
||||||
|
Forwards::RoutingMailer.choose_project(mail).deliver_now
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Incineration of InboundEmails
|
||||||
|
|
||||||
|
By default, an InboundEmail that has been successfully processed will be
|
||||||
|
incinerated after 30 days. This ensures you're not holding on to people's data
|
||||||
|
willy-nilly after they may have canceled their accounts or deleted their
|
||||||
|
content. The intention is that after you've processed an email, you should have
|
||||||
|
extracted all the data you needed and turned it into domain models and content
|
||||||
|
on your side of the application. The InboundEmail simply stays in the system
|
||||||
|
for the extra time to provide debugging and forensics options.
|
||||||
|
|
||||||
|
The actual incineration is done via the `IncinerationJob` that's scheduled
|
||||||
|
to run after `config.action_mailbox.incinerate_after` time. This value is
|
||||||
|
by default set to `30.days`, but you can change it in your production.rb
|
||||||
|
configuration. (Note that this far-future incineration scheduling relies on
|
||||||
|
your job queue being able to hold jobs for that long.)
|
||||||
|
|
||||||
|
## Working with Action Mailbox in development
|
||||||
|
|
||||||
|
It's helpful to be able to test incoming emails in development without actually
|
||||||
|
sending and receiving real emails. To accomplish this, there's a conductor
|
||||||
|
controller mounted at `/rails/conductor/action_mailbox/inbound_emails`,
|
||||||
|
which gives you an index of all the InboundEmails in the system, their
|
||||||
|
state of processing, and a form to create a new InboundEmail as well.
|
||||||
|
|
||||||
|
## Testing mailboxes
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class ForwardsMailboxTest < ActionMailbox::TestCase
|
||||||
|
test "directly recording a client forward for a forwarder and forwardee corresponding to one project" do
|
||||||
|
assert_difference -> { people(:david).buckets.first.recordings.count } do
|
||||||
|
receive_inbound_email_from_mail \
|
||||||
|
to: 'save@example.com',
|
||||||
|
from: people(:david).email_address,
|
||||||
|
subject: "Fwd: Status update?",
|
||||||
|
body: <<~BODY
|
||||||
|
--- Begin forwarded message ---
|
||||||
|
From: Frank Holland <frank@microsoft.com>
|
||||||
|
|
||||||
|
What's the status?
|
||||||
|
BODY
|
||||||
|
end
|
||||||
|
|
||||||
|
recording = people(:david).buckets.first.recordings.last
|
||||||
|
assert_equal people(:david), recording.creator
|
||||||
|
assert_equal "Status update?", recording.forward.subject
|
||||||
|
assert_match "What's the status?", recording.forward.content.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
|
@ -3,13 +3,13 @@
|
||||||
Action Mailer Basics
|
Action Mailer Basics
|
||||||
====================
|
====================
|
||||||
|
|
||||||
This guide provides you with all you need to get started in sending and
|
This guide provides you with all you need to get started in sending
|
||||||
receiving emails from and to your application, and many internals of Action
|
emails from and to your application, and many internals of Action
|
||||||
Mailer. It also covers how to test your mailers.
|
Mailer. It also covers how to test your mailers.
|
||||||
|
|
||||||
After reading this guide, you will know:
|
After reading this guide, you will know:
|
||||||
|
|
||||||
* How to send and receive email within a Rails application.
|
* How to send email within a Rails application.
|
||||||
* How to generate and edit an Action Mailer class and mailer view.
|
* How to generate and edit an Action Mailer class and mailer view.
|
||||||
* How to configure Action Mailer for your environment.
|
* How to configure Action Mailer for your environment.
|
||||||
* How to test your Action Mailer classes.
|
* How to test your Action Mailer classes.
|
||||||
|
@ -427,7 +427,7 @@ If you would like to render a template located outside of the default `app/views
|
||||||
```ruby
|
```ruby
|
||||||
class UserMailer < ApplicationMailer
|
class UserMailer < ApplicationMailer
|
||||||
prepend_view_path "custom/path/to/mailer/view"
|
prepend_view_path "custom/path/to/mailer/view"
|
||||||
|
|
||||||
# This will try to load "custom/path/to/mailer/view/welcome_email" template
|
# This will try to load "custom/path/to/mailer/view/welcome_email" template
|
||||||
def welcome_email
|
def welcome_email
|
||||||
# ...
|
# ...
|
||||||
|
@ -651,48 +651,8 @@ class UserMailer < ApplicationMailer
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Receiving Emails
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Receiving and parsing emails with Action Mailer can be a rather complex
|
|
||||||
endeavor. Before your email reaches your Rails app, you would have had to
|
|
||||||
configure your system to somehow forward emails to your app, which needs to be
|
|
||||||
listening for that. So, to receive emails in your Rails app you'll need to:
|
|
||||||
|
|
||||||
* Implement a `receive` method in your mailer.
|
|
||||||
|
|
||||||
* Configure your email server to forward emails from the address(es) you would
|
|
||||||
like your app to receive to `/path/to/app/bin/rails runner
|
|
||||||
'UserMailer.receive(STDIN.read)'`.
|
|
||||||
|
|
||||||
Once a method called `receive` is defined in any mailer, Action Mailer will
|
|
||||||
parse the raw incoming email into an email object, decode it, instantiate a new
|
|
||||||
mailer, and pass the email object to the mailer `receive` instance
|
|
||||||
method. Here's an example:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
class UserMailer < ApplicationMailer
|
|
||||||
def receive(email)
|
|
||||||
page = Page.find_by(address: email.to.first)
|
|
||||||
page.emails.create(
|
|
||||||
subject: email.subject,
|
|
||||||
body: email.body
|
|
||||||
)
|
|
||||||
|
|
||||||
if email.has_attachments?
|
|
||||||
email.attachments.each do |attachment|
|
|
||||||
page.attachments.create({
|
|
||||||
file: attachment,
|
|
||||||
description: email.subject
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Action Mailer Callbacks
|
Action Mailer Callbacks
|
||||||
---------------------------
|
-----------------------
|
||||||
|
|
||||||
Action Mailer allows for you to specify a `before_action`, `after_action` and
|
Action Mailer allows for you to specify a `before_action`, `after_action` and
|
||||||
`around_action`.
|
`around_action`.
|
||||||
|
@ -882,7 +842,7 @@ class EmailDeliveryObserver
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Like interceptors, you need to register observers with the Action Mailer framework. You can do this in an initializer file
|
Like interceptors, you need to register observers with the Action Mailer framework. You can do this in an initializer file
|
||||||
`config/initializers/email_delivery_observer.rb`
|
`config/initializers/email_delivery_observer.rb`
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
|
|
@ -74,7 +74,12 @@
|
||||||
-
|
-
|
||||||
name: Action Mailer Basics
|
name: Action Mailer Basics
|
||||||
url: action_mailer_basics.html
|
url: action_mailer_basics.html
|
||||||
description: This guide describes how to use Action Mailer to send and receive emails.
|
description: This guide describes how to use Action Mailer to send emails.
|
||||||
|
-
|
||||||
|
name: Action Mailbox Basics
|
||||||
|
work_in_progress: true
|
||||||
|
url: action_mailbox_basics.html
|
||||||
|
description: This guide describes how to use Action Mailbox to receive emails.
|
||||||
-
|
-
|
||||||
name: Active Job Basics
|
name: Active Job Basics
|
||||||
url: active_job_basics.html
|
url: active_job_basics.html
|
||||||
|
|
Loading…
Reference in a new issue