ActionMailBox とは
Rails6で入るframeworkの一つです。
今までメールの送信機能として ActionMailer ではありましたが、
メール受信に関する機能がなく、そこで入ったのが ActionMailbox です。
ドキュメントなど
- RailsGuide
- edge api rails
- GitHub
- この記事書く上で参考にしたもの
機能を3行で
- SendGrid などのメールサービスでメールを受信したときに、Railsの専用エンドポイントに転送する
- ApplicationController と似た ApplicationMailbox でroutingを書く
- ApplicationMailbox を継承したクラスでメール受信時の処理を行う
ActionMailbox を使うとできそうなこと
- GitHubにある、コメントのメールに返信したらGitHub上でもコメントできる、的な機能
- 参考にした動画( https://gorails.com/episodes/action-mailbox-rails-6 )では、これを作っています。
- メールサポートシステム(メールディラーなどの代わり)
- ActionMailer, ActionMailbox を使って、ユーザー情報とも紐づけてサポート対応をより簡単にできるかも。
処理の流れのイメージ
例えば、『Aさんが書いたブログにコメントをされ、その通知をAさんにメールで送信、Aさんがメールに返信したらコメントを返せる』という機能を考えてみます。
- ブログにコメントがされる
- ActionMailer でコメントされた通知をAさんにメールで送る
- to はAさんのメールアドレス(
a-san@example.com
とします) - from には、ブログ・コメントのIDを埋め込んでおきます。
reply-blog_1-comment-2@someapp.example.com
という感じ。
- to はAさんのメールアドレス(
- Aさんはは送られてきたメールに返信する
- メールサービスがメールを受信し、railsのアプリケーションに転送
- 受信・転送がされるように設定しておく必要があります。
- ドメインの設定と受信時に転送する設定が必要です。
- 詳しくは、RailsGuide や各メールサービスのドキュメントを見てください。
- 受信・転送がされるように設定しておく必要があります。
-
ApplicationMailbox
の routing でどのmailboxで処理をするか振り分ける- 基本的には、メールを受信したときの
to
で振り分けをします- ここでは
reply-blog_1-comment-2@someapp.example.com
というメールアドレスです。
- ここでは
- 基本的には、メールを受信したときの
-
FooMailbox#process
でメール受信時の処理をします。-
to
(a-sann@example.com
)メールアドレスで、ユーザー情報を検索 -
from
(reply-blog_1-comment-2@someapp.example.com
)メールアドレスで、コメントすべきblog, commentを特定 -
body
にある文章でコメントを追加
-
実装する上で知っておくと理解が早いこと
RailsGuide には、ActionMailbox の最低限の情報が載っているだけです。
全体像理解してからなら十分読めると思いますが、それまではエスパーするのはなかなか難しいです。
ApplicationMailbox
のroutingで、受信したメールの to
で処理を振り分ける
# app/mailboxes/application_mailbox.rb
class ApplicationMailbox < ActionMailbox::Base
routing /^save@/i => :forwards
routing /@replies\./i => :replies
# routing :all => :foos
end
# app/mailboxes/forwards_mailbox.rb
class ForwardsMailbox < ApplicationMailbox
def process
# ...
end
end
# app/mailboxes/replies_mailbox.rb
class RepliesMailbox < ApplicationMailbox
def process
# ...
end
end
RailsGuideに書かれてるコードを参考に見てみます。
ActionMailbox::Base
を継承した ApplicationMailbox
に routing
を書きます。
受信したメールの to
が、routingに書いた正規表現にマッチしたら指定のmailboxに振り分けします。
例えば、 topic+1@replies.example.com
というメールアドレスでメールを受信した場合、
routing /@replies\./i => :replies
の正規表現にマッチするので、 RepliesMailbox
クラスに振り分けられます。
Mailboxの実装のサンプル
https://gorails.com/episodes/action-mailbox-rails-6 で実装するものがこのような感じです。
class RepliesMailbox < ApplicationMailbox
MATCHER = /\Areply-(.+)@reply.example.com/i # domain部分は例で書いてあるだけです。
before_processing :require_user
def process
discussion.comments.create(
user: user,
body: mail.decoded,
)
end
private
def user
# ユーザーは事前に同じメールアドレスでサイトに登録されてる必要があります。
@user ||= User.find_by(email: mail.from)
end
def require_user
unless user
# bounce_with でbounceの処理をする。ここで#processの処理は停止します
# ユーザーが見つからない場合、bounceのメールを送信する
bounce_with UserMailer.missing(inboud_email)
end
end
def discussion
@discussion ||= Discussion.find(discussion_id)
end
# メールアドレスからdiscussion_idを取り出す
def discussion_id
recipient = mail.recipients.find { |r| MATCHER.match?(r) }
recipient[MATCHER, 1]
end
end
- mailbox は controller と似た感じで実装できます
- まず
#process
が呼ばれる -
before_action
->before_processing
-
request
->mail
,inbound_email
-
mail
: https://github.com/mikel/mail のクラスのオブジェクト -
inbound_email
:ActionMailbox::InboundEmail
のレコード
-
-
ActionMailbox::InboundEmail
-
rails action_mailbox:install
で作られる、ActiveRecordのクラス - 受信したメールはここに溜まっていく
- 一定期間したら消えていく
-
- まず
- 上記のサンプルコードでは、受信時のメールアドレス(
to
,recipients
)から duscussion_id を取り出しています。- このような実装をする場合、メールアドレスが重要なので、まずアプリ側からそういうメールアドレスを作ってユーザーにメールを送信する必要があるでしょう。
- サイト側からメールを送るときの
from
のアドレスが重要ということです。それに返信してもらったら、受信時のto
になるので。 - もっと賢い方法をもしご存知でしたらぜひ教えていただけるとありがたいです
- サイト側からメールを送るときの
- このような実装をする場合、メールアドレスが重要なので、まずアプリ側からそういうメールアドレスを作ってユーザーにメールを送信する必要があるでしょう。
-
User
,Discussion
,Comment
,UserMailer
などは当然自前で実装が必要です。- RailsGuide のサンプルコードの
Person
,Forward
,Forwards::RoutingMailer
あたりも自前実装のはずです。
- RailsGuide のサンプルコードの
development環境で試す
https://railsguides.jp/action_mailbox_basics.html#action-mailboxをdevelopment環境で使う
/rails/conductor/action_mailbox/inbound_emails
に ActionMailbox::InboundEmail
のcontrollerが用意されています。
/rails/conductor/action_mailbox/inbound_emails/new
でメール入力フォームが表示され、メール受信時の挙動を再現できます。
ローカル環境で実際のメールの受信を試してみる
Mailgun や SendGrid のようなメール送受信サービスを使う場合、
外部からのリクエストを受け付けられるようにする必要があります。
https://ngrok.com/
ngrokを使うと良いでしょう。
ngrokを使うと、外部からアクセスできるURLが発行できます。
いくつか手順があります。
Mailgunを例にします。
-
Mailgunのアカウント登録を済ませる
-
ngrokを
ngrok http 3000
起動してURLを発行する -
Mailgun で、メールを受信したときに Rails にメールを転送するように設定する
- RailsGuide に書くメールサービスごとに設定の仕方が書いてあります。
- Mailgun の場合、 https://railsguides.jp/action_mailbox_basics.html#mailgun
- 設定するURLは
https://<ngrokで発行されたドメイン>/rails/action_mailbox/mailgun/inbound_emails/mime
になります。 - pathは、メールサービスごとに違うので注意してください。
-
Mailgun から発行された API key を Rails の Credentials に設定する
-
Rails が Mailgun を使用するように設定する
config.action_mailbox.ingress = :mailgun
- https://railsguides.jp/action_mailbox_basics.html#mailgun
-
Rails を起動する
-
Mailgun で発行されたドメインに対してメールを送る
これで基本的には動くはずです。
動かない場合、以下を確認してみると原因特定につながるかと思います。
- Mailgunのダッシュボード
- ngrokのダッシュボード
- InboundEmails
おわりに
ActionMailbox の触りの紹介の記事でした。
まだこの記事を書いている段階では Rails6 はリリースされていませんし、ネットには情報がとても少ないです。
ですので、実際運用しようと実装してみると、もっと知らないといけないことはあるかもしれないですし、
ハマりどころもあるかもしれません。
ですが、この記事がとりあえず触ってみるきっかけになれば幸いです