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
将您的Mailgun签名密钥(可以在Mailgun的设置->安全性和用户->API安全性下找到)提供给Action Mailbox,以便它可以对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
将您的Mandrill API密钥提供给Action Mailbox,以便它可以对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
# 回调指定处理的先决条件
before_processing :require_projects
def process
# 在一个项目上记录转发,或者…
if forwarder.projects.one?
record_forward
else
# …涉及第二个Action Mailer,询问要转发到哪个项目。
request_forwarding_project
end
end
private
def require_projects
if forwarder.projects.none?
# 使用Action Mailers将传入的电子邮件反弹回发件人 - 这会停止处理
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 "直接为一个项目对应的转发者和被转发者记录客户端转发" 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 文档的任何问题。