13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails6が出る前のActionMailbox入門

Last updated at Posted at 2019-07-14

ActionMailBox とは

Rails6で入るframeworkの一つです。
今までメールの送信機能として ActionMailer ではありましたが、
メール受信に関する機能がなく、そこで入ったのが ActionMailbox です。

ドキュメントなど

機能を3行で

  • SendGrid などのメールサービスでメールを受信したときに、Railsの専用エンドポイントに転送する
  • ApplicationController と似た ApplicationMailbox でroutingを書く
  • ApplicationMailbox を継承したクラスでメール受信時の処理を行う

ActionMailbox を使うとできそうなこと

  • GitHubにある、コメントのメールに返信したらGitHub上でもコメントできる、的な機能
  • メールサポートシステム(メールディラーなどの代わり)
    • ActionMailer, ActionMailbox を使って、ユーザー情報とも紐づけてサポート対応をより簡単にできるかも。

処理の流れのイメージ

例えば、『Aさんが書いたブログにコメントをされ、その通知をAさんにメールで送信、Aさんがメールに返信したらコメントを返せる』という機能を考えてみます。

  • ブログにコメントがされる
  • ActionMailer でコメントされた通知をAさんにメールで送る
    • to はAさんのメールアドレス(a-san@example.comとします)
    • from には、ブログ・コメントのIDを埋め込んでおきます。 reply-blog_1-comment-2@someapp.example.com という感じ。
  • 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を継承した ApplicationMailboxroutingを書きます。
受信したメールの 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 と似た感じで実装できます
  • 上記のサンプルコードでは、受信時のメールアドレス(to, recipients)から duscussion_id を取り出しています。
    • このような実装をする場合、メールアドレスが重要なので、まずアプリ側からそういうメールアドレスを作ってユーザーにメールを送信する必要があるでしょう。
      • サイト側からメールを送るときの from のアドレスが重要ということです。それに返信してもらったら、受信時のtoになるので。
      • もっと賢い方法をもしご存知でしたらぜひ教えていただけるとありがたいです :bow:
  • User, Discussion, Comment, UserMailer などは当然自前で実装が必要です。
    • RailsGuide のサンプルコードの Person, Forward, Forwards::RoutingMailer あたりも自前実装のはずです。

development環境で試す

https://railsguides.jp/action_mailbox_basics.html#action-mailboxをdevelopment環境で使う

/rails/conductor/action_mailbox/inbound_emailsActionMailbox::InboundEmailのcontrollerが用意されています。
/rails/conductor/action_mailbox/inbound_emails/new でメール入力フォームが表示され、メール受信時の挙動を再現できます。

ローカル環境で実際のメールの受信を試してみる

Mailgun や SendGrid のようなメール送受信サービスを使う場合、
外部からのリクエストを受け付けられるようにする必要があります。

https://ngrok.com/
ngrokを使うと良いでしょう。
ngrokを使うと、外部からアクセスできるURLが発行できます。

いくつか手順があります。
Mailgunを例にします。

  • Mailgunのアカウント登録を済ませる

  • ngrokを ngrok http 3000 起動してURLを発行する

    • railsを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 を使用するように設定する

  • Rails を起動する

  • Mailgun で発行されたドメインに対してメールを送る

これで基本的には動くはずです。
動かない場合、以下を確認してみると原因特定につながるかと思います。

おわりに

ActionMailbox の触りの紹介の記事でした。
まだこの記事を書いている段階では Rails6 はリリースされていませんし、ネットには情報がとても少ないです。
ですので、実際運用しようと実装してみると、もっと知らないといけないことはあるかもしれないですし、
ハマりどころもあるかもしれません。

ですが、この記事がとりあえず触ってみるきっかけになれば幸いです :smile:

13
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?