공식 웹사이트 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:

1 Introduction

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.

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.

2 Setup

Install migrations needed for InboundEmail and ensure Active Storage is set up:

$ rails action_mailbox:install
$ rails db:migrate

3 Configuration

3.1 Exim

Tell Action Mailbox to accept emails from an SMTP relay:

# config/environments/production.rb
config.action_mailbox.ingress = :relay

Generate a strong password that Action Mailbox can use to authenticate requests to the relay 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:

action_mailbox:
  ingress_password: ...

Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

Configure Exim to pipe inbound emails to bin/rails action_mailbox:ingress:exim, providing the URL of the relay ingress and the INGRESS_PASSWORD you previously generated. If your application lived at https://example.com, the full command would look like this:

bin/rails action_mailbox:ingress:exim URL=https://example.com/rails/action_mailbox/relay/inbound_emails INGRESS_PASSWORD=...

3.2 Mailgun

Give Action Mailbox your 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:

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:

# config/environments/production.rb
config.action_mailbox.ingress = :mailgun

Configure Mailgun 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.

3.3 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:

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:

# config/environments/production.rb
config.action_mailbox.ingress = :mandrill

Configure Mandrill 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.

3.4 Postfix

Tell Action Mailbox to accept emails from an SMTP relay:

# config/environments/production.rb
config.action_mailbox.ingress = :relay

Generate a strong password that Action Mailbox can use to authenticate requests to the relay 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:

action_mailbox:
  ingress_password: ...

Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

Configure Postfix 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:

$ bin/rails action_mailbox:ingress:postfix URL=https://example.com/rails/action_mailbox/relay/inbound_emails INGRESS_PASSWORD=...

3.5 Postmark

Tell Action Mailbox to accept emails from Postmark:

# config/environments/production.rb
config.action_mailbox.ingress = :postmark

Generate a strong password that Action Mailbox can use to authenticate requests to the Postmark 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:

action_mailbox:
  ingress_password: ...

Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

Configure Postmark inbound webhook to forward inbound emails to /rails/action_mailbox/postmark/inbound_emails with the username actionmailbox and the password you previously generated. If your application lived at https://example.com, you would configure Postmark with the following fully-qualified URL:

https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/postmark/inbound_emails

When configuring your Postmark inbound webhook, be sure to check the box labeled "Include raw email content in JSON payload". Action Mailbox needs the raw email content to work.

3.6 Qmail

Tell Action Mailbox to accept emails from an SMTP relay:

# config/environments/production.rb
config.action_mailbox.ingress = :relay

Generate a strong password that Action Mailbox can use to authenticate requests to the relay 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:

action_mailbox:
  ingress_password: ...

Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

Configure Qmail to pipe inbound emails to bin/rails action_mailbox:ingress:qmail, providing the URL of the relay ingress and the INGRESS_PASSWORD you previously generated. If your application lived at https://example.com, the full command would look like this:

bin/rails action_mailbox:ingress:qmail URL=https://example.com/rails/action_mailbox/relay/inbound_emails INGRESS_PASSWORD=...

3.7 SendGrid

Tell Action Mailbox to accept emails from SendGrid:

# 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:

action_mailbox:
  ingress_password: ...

Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

Configure SendGrid Inbound Parse 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

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.

4 Examples

Configure basic routing:

# app/mailboxes/application_mailbox.rb
class ApplicationMailbox < ActionMailbox::Base
  routing /^save@/i     => :forwards
  routing /@replies\./i => :replies
end

Then set up a mailbox:

# Generate new mailbox
$ bin/rails generate mailbox forwards

# 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

5 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.)

6 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.

7 Testing mailboxes

Example:

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

피드백

이 가이드의 품질을 향상시키기 위해 여러분의 도움이 필요하다.

오타나 실제 오류를 발견시 여러분의 기여를 권고한다. 시작하려면 본 가이드의 기여 섹션을 읽어보기 바란다.

미완성된 컨텐츠나 업데이트되지 않은 내용을 발견할 수도 있다. 누락된 문서는 master 브랜치에 추가한다. 제시된 이슈들이 master 브랜치 상에서 이미 해결되었는지 여부를 확인하려면 먼저 Edge Guides를 확인한다. 스타일과 규칙에 대해서는 Ruby on Rails Guides Guidelines을 확인한다.

어떤 이유로든 고칠 수 있지만 직접 패치 할 수 없는 경우 이슈를 새로 오픈하면 된다.

그리고 마지막으로, 루비온레일스 문서에 관한 모든 논의는 rubyonrails-docs 메일링 리스트 상에서 언제든지 가능하다.