edge
更多資訊請參考 rubyonrails.org: 更多 Ruby on Rails

Action Mailbox基礎知識

本指南提供了一切您需要開始接收應用程式郵件的資訊。

閱讀本指南後,您將了解:

1 什麼是Action Mailbox?

Action Mailbox將傳入的郵件路由到類似控制器的郵箱中,以在Rails中進行處理。它內置了用於Mailgun、Mandrill、Postmark和SendGrid的入口。您還可以通過內置的Exim、Postfix和Qmail入口直接處理傳入郵件。

傳入的郵件使用Active Record轉換為"InboundEmail"記錄,並具有生命週期追踪功能,通過Active Storage將原始郵件存儲在雲存儲中,並具有默認啟用的負責任的數據處理。

這些傳入的郵件使用Active Job異步路由到一個或多個專用郵箱,這些郵箱能夠直接與您的域模型的其餘部分進行交互。

2 設置

安裝所需的"InboundEmail"遷移並確保Active Storage已設置:

$ bin/rails action_mailbox:install
$ bin/rails db:migrate

3 配置

3.1 Exim

告訴Action Mailbox接受來自SMTP中繼的郵件:

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

生成一個強密碼,Action Mailbox可以使用它來驗證對中繼入口的請求。

使用bin/rails credentials:edit將密碼添加到應用程式的加密憑證中,位置在action_mailbox.ingress_password下,Action Mailbox將自動找到它:

action_mailbox:
  ingress_password: ...

或者,將密碼提供給RAILS_INBOUND_EMAIL_PASSWORD環境變量。

配置Exim將傳入的郵件導向到bin/rails action_mailbox:ingress:exim,並提供中繼入口的URL和之前生成的INGRESS_PASSWORD。如果您的應用程式位於https://example.com,完整的命令如下所示:

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

3.2 Mailgun

提供Action Mailbox您的Mailgun簽名密鑰(您可以在Mailgun的"Settings -> Security & Users -> API security"下找到)以便它可以驗證對Mailgun入口的請求。

使用bin/rails credentials:edit將您的簽名密鑰添加到應用程式的加密憑證中,位置在action_mailbox.mailgun_signing_key下,Action Mailbox將自動找到它:

action_mailbox:
  mailgun_signing_key: ...

或者,將您的簽名密鑰提供給MAILGUN_INGRESS_SIGNING_KEY環境變量。

告訴Action Mailbox接受來自Mailgun的郵件:

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

配置Mailgun將傳入的郵件轉發到/rails/action_mailbox/mailgun/inbound_emails/mime。如果您的應用程式位於https://example.com,您將指定完整的URLhttps://example.com/rails/action_mailbox/mailgun/inbound_emails/mime

3.3 Mandrill

提供Action Mailbox您的Mandrill API金鑰,以便它可以驗證對Mandrill入口的請求。

使用bin/rails credentials:edit將您的API金鑰添加到應用程式的加密憑證中,位置在action_mailbox.mandrill_api_key下,Action Mailbox將自動找到它:

action_mailbox:
  mandrill_api_key: ...

或者,將您的API金鑰提供給MANDRILL_INGRESS_API_KEY環境變量。

告訴Action Mailbox接受來自Mandrill的郵件:

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

配置Mandrill將傳入的郵件路由到/rails/action_mailbox/mandrill/inbound_emails。如果您的應用程式位於https://example.com,您將指定完整的URLhttps://example.com/rails/action_mailbox/mandrill/inbound_emails

3.4 Postfix

告訴Action Mailbox接受來自SMTP中繼的郵件:

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

生成一個強密碼,Action Mailbox可以使用它來驗證對中繼入口的請求。

使用bin/rails credentials:edit將密碼添加到應用程式的加密憑證中,位置在action_mailbox.ingress_password下,Action Mailbox將自動找到它:

action_mailbox:
  ingress_password: ...

或者,將密碼提供給RAILS_INBOUND_EMAIL_PASSWORD環境變量。

配置Postfix將傳入的郵件導向到bin/rails action_mailbox:ingress:postfix,並提供Postfix入口的URL和之前生成的INGRESS_PASSWORD。如果您的應用程式位於https://example.com,完整的命令如下所示:

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

3.5 Postmark

告訴Action Mailbox接受來自Postmark的郵件:

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

生成一個強密碼,Action Mailbox可以使用它來驗證對Postmark入口的請求。

使用bin/rails credentials:edit將密碼添加到應用程式的加密憑證中,位置在action_mailbox.ingress_password下,Action Mailbox將自動找到它:

action_mailbox:
  ingress_password: ...

或者,將密碼提供給RAILS_INBOUND_EMAIL_PASSWORD環境變量。

配置Postmark入站webhook將傳入的郵件轉發到/rails/action_mailbox/postmark/inbound_emails,並使用用戶名actionmailbox和之前生成的密碼。如果您的應用程式位於https://example.com,您將使用以下完整的URL配置Postmark: https://actionmailbox:[email protected]/rails/action_mailbox/postmark/inbound_emails

注意:在配置Postmark入站Webhook時,請務必勾選標記為“在JSON有效載荷中包含原始電子郵件內容”。 Action Mailbox需要原始電子郵件內容才能正常運作。

3.6 Qmail

告訴Action Mailbox接受來自SMTP中繼的電子郵件:

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

生成一個強密碼,Action Mailbox可以用來驗證對中繼入口的請求。

使用bin/rails credentials:edit將密碼添加到應用程序的加密憑據中, 位置為action_mailbox.ingress_password,Action Mailbox會自動找到它:

action_mailbox:
  ingress_password: ...

或者,將密碼提供給RAILS_INBOUND_EMAIL_PASSWORD環境變量。

配置Qmail將入站電子郵件導向到bin/rails action_mailbox:ingress:qmail, 提供中繼入口的URL和之前生成的INGRESS_PASSWORD。 如果您的應用程序位於https://example.com,完整的命令如下所示:

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

3.7 SendGrid

告訴Action Mailbox接受來自SendGrid的電子郵件:

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

生成一個強密碼,Action Mailbox可以用來驗證對SendGrid入口的請求。

使用bin/rails credentials:edit將密碼添加到應用程序的加密憑據中, 位置為action_mailbox.ingress_password,Action Mailbox會自動找到它:

action_mailbox:
  ingress_password: ...

或者,將密碼提供給RAILS_INBOUND_EMAIL_PASSWORD環境變量。

配置SendGrid Inbound Parse 將入站電子郵件轉發到/rails/action_mailbox/sendgrid/inbound_emails, 使用用戶名actionmailbox和之前生成的密碼。如果您的應用程序位於https://example.com, 您將使用以下URL配置SendGrid:

https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/inbound_emails

注意:在配置SendGrid Inbound Parse webhook時,請務必勾選標記為“發布原始的完整MIME郵件。” Action Mailbox需要原始MIME郵件才能正常運作。

4 示例

配置基本路由:

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

然後設置一個郵箱:

# 生成新的郵箱
$ bin/rails generate mailbox forwards
# app/mailboxes/forwards_mailbox.rb
class ForwardsMailbox < ApplicationMailbox
  # Callbacks specify prerequisites to processing
  before_processing :require_projects

  def process
    # Record the forward on the one project, or…
    if forwarder.projects.one?
      record_forward
    else
      # …involve a second Action Mailer to ask which project to forward into.
      request_forwarding_project
    end
  end

  private
    def require_projects
      if forwarder.projects.none?
        # Use Action Mailers to bounce incoming emails back to sender – this halts processing
        bounce_with Forwards::BounceMailer.no_projects(inbound_email, forwarder: forwarder)
      end
    end

    def record_forward
      forwarder.forwards.create subject: mail.subject, content: mail.content
    end

    def request_forwarding_project
      Forwards::RoutingMailer.choose_project(inbound_email, forwarder: forwarder).deliver_now
    end

    def forwarder
      @forwarder ||= User.find_by(email_address: mail.from)
    end
end

5 InboundEmail的銷毀

默認情況下,成功處理的InboundEmail將在30天後被銷毀。 這樣可以確保在用戶可能取消帳戶或刪除內容後,您不會隨意保留他們的數據。 這意味著在處理電子郵件後,您應該提取所有所需的數據並將其轉換為應用程序端的域模型和內容。 InboundEmail只是在系統中保留額外的時間以提供調試和取證選項。

實際的銷毀是通過IncinerationJob完成的,該作業在config.action_mailbox.incinerate_after時間後運行。 默認情況下,此值設置為30.days,但您可以在production.rb配置文件中更改它。 (請注意,這種遠期銷毀排程依賴於您的作業隊列能夠保留作業那麼長的時間。)

6 在開發中使用Action Mailbox

在開發中,測試傳入的電子郵件而不實際發送和接收真實的電子郵件是很有幫助的。 為此,有一個控制器掛載在/rails/conductor/action_mailbox/inbound_emails, 它提供了系統中所有InboundEmail的索引,它們的處理狀態以及創建新InboundEmail的表單。

7 測試郵箱

示例:

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: '[email protected]',
        from: people(:david).email_address,
        subject: "Fwd: Status update?",
        body: <<~BODY
          --- Begin forwarded message ---
          From: Frank Holland <[email protected]>

          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

請參考ActionMailbox::TestHelper API以獲取更多測試輔助方法。 ```

回饋

歡迎協助提升本指南的品質。

如果您發現任何錯別字或事實錯誤,請貢獻您的力量。 開始之前,您可以閱讀我們的 文件貢獻 部分。

您也可能會發現不完整的內容或過時的資訊。 請為主要的文件補充任何遺漏的內容。請先檢查 Edge 指南,以確認問題是否已經修復或尚未在主分支上修復。 請參考 Ruby on Rails 指南指引 以了解風格和慣例。

如果您發現需要修復但無法自行修補的問題,請 開啟一個問題

最後但同樣重要的是,關於 Ruby on Rails 文件的任何討論都非常歡迎在 官方 Ruby on Rails 論壇 上進行。