ITエンジニアによるITエンジニアのためのブログ

RailsとSendGrid Inbound ParseでEメール受信

自社システムをサードパーティシステムと連携させたい場合、APIやウェブフックを使用することが一般的です。しかし、サードパーティシステムにそのような仕組みが存在しない場合はどうすれば良いでしょうか。

もしサードパーティシステムにEメール送信機能があり、そのEメール本文に連携したい内容が含まれる場合、APIやウェブフックがなくても自社システムに取り込むことが可能です。

この記事では、SendGridが提供しているInbound ParseというEメール受信機能を使い、EメールをRuby on Railsアプリケーションで受け取る方法を解説します。

全体像

詳細なセットアップ方法を解説する前に、システム全体像とデータの流れを把握しておきましょう。

  1. 送信者がEメールを送信します。
  2. Eメールの送信先アドレスのドメインのMXレコードにSendGridが指定されているため、SendGridがそのEメールを受信します。
  3. SendGridがEメールの内容をRailsアプリケーションのURLにPOSTします。
  4. Railsアプリで受け取ったEメール内容を解析します。

図にすると以下のような形になります。

SendGrid Inbound Parseの設定

SendGridが提供しているInbound Parseは、SendGridが受信したEメールの内容を任意のURLに送信してくれる機能です。

この機能を使うには、SendGridにログインし、左メニューのSettings配下のInbound Parseをクリックします。

Add Host & URLボタンをクリックし、1)Receiving Domainにメールを受信したいドメイン名を、2)Destination URLにメール内容をPOSTで受け取るためのRailsアプリケーションのURLを入力します。Additional Optionsのチェックボックスはチェックしなくても結構です。

なお、セキュリティー強化のため、Destination URLにベーシック認証を設定することをお勧めします。

設定例としては以下のようになります。

# 受信ドメイン
mail.example.com

# Destination URL (ベーシック認証付き)
https://username:password@example.com/inbound_mail	

DNSでMXレコードの設定

ご自身が使っているDNSサービスプロバイダーにて、Inbound Parseで受信ドメインとして設定したドメインのMXレコードを作成し、メールがSendGridに届くようにSendGridから指定された値(記事執筆時点ではmx.sendgrid.net)と設定します。

MXレコードとは、メールの送信先サーバーを定義するDNSレコードの一種です。MXレコードを設定することで、特定のドメイン宛のメールをどのメールサーバーで受信するかを指定できます。

設定例としては以下のようになります。

# MXレコード設定例
mail.example.com in MX 1 mx.sendgrid.net.

これで、EメールがSendGridに届くと、Inbound ParseによってDestination URLにPOSTリクエストが送られるようになります。

Railsで内容を解析

次に、Railsでメール受信用のコントローラーメソッドを作成します。

class ExampleController < ApplicationController
  def inbound_mail
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV.fetch('SENDGRID_BASIC_USER') && password == ENV.fetch('SENDGRID_BASIC_PASSWORD')
    end

    if valid_sender?
      # バリデーションが通ったら独自ロジック実行
      my_logic
    end

    render status: :ok, body: nil
  end

  private

  def valid_sender?
    params[:from] == ENV.fetch('HTTP_MAIL_FROM') && params[:SPF] == 'pass'
  end

 def my_logic
    # メール件名
    mail_subject = params[:subject]

    # メール本文
    mail_body = params[:text]

    # 本文の解析例
    amount = mail_body.match(/注文金額:([\d,]+)/)[1]
  end

前述の通り、セキュリティーのためにベーシック認証を設定します。これにはRailsが提供しているauthenticate_or_request_with_http_basicメソッドを使います。ユーザー名とパスワードは環境変数で設定し、SendGridで設定したものと一緒かどうかを確認します。

環境変数の設定例:

# Bash
export SENDGRID_BASIC_USER=your_username
export SENDGRID_BASIC_PASSWORD=your_password
export HTTP_MAIL_FROM=sender@example.com

また、FROMヘッダーやSPFの認証結果もパラメーターに含まれるので、SPFがパスしているか、送信元が設定通りかも追加で検証しています(valid_sender?メソッド)。

ベーシック認証と追加検証が問題なかったら、POSTパラメーターに含まれるメール内容を解析してアプリケーション独自の処理ロジックを実行します。上記コードに解析例を記載したので参考にしてみてください。

テスト

Railsアプリをステージング環境にデプロイし、Eメールを送信してSendGridからのリクエストを受信できるかどうか確認します。

もしうまく行かない場合、調査するポイントは以下の通りです。

MXレコードが適切に設定され、インターネット上に浸透しているか

MXレコードはdigコマンドで確認できます。以下のコマンドを実行し、MXレコードが正しく設定されているか確認してください。

dig mail.example.com MX

SendGridにメールが届いていてInbound Parseで処理されているか

SendGrid管理コンソールのActivityメニューから送信先メールアドレスを入力して検索し、Inbound Parseのエントリーがあるかどうか調査します。

Railsでエラーが起こっていないか

Railsのサーバーログ(log/production.logなど)を調査します。

まとめ

連携したいサードパーティーシステムがAPIやウェブフックを提供していなくてもEメールさえ送られていれば、RailsとSendGridのInbound Parseを使用して連携できる可能性があります。もしそのような状況であったら、ぜひこの記事の内容を参考にしてみてください。