プログラミング

初心者でもできる! Ruby on Rails、PostgreSQL、SendGridでメール受信

更新日:

Ruby on RailsとSendGridでのメール送信に関する記事はたくさんあるのですが、受信の記事は少なかったのでまとめました。

SendGridとは

SMTPプロバイダ、つまり自分でメールサーバを用意せずにSendGridのSMTPサーバーを使って送受信ができるサービスを提供しています。

さらにエラー通知や開封率の確認といった機能も提供しているので、APIを使えばメール関連の機能がほぼ全てカバーできます。また、基本的に無料で日本語ドキュメントや公式ブログが充実しているのも嬉しいポイントです。

SMTP(Simple Mail Transer Protocol)とは

メールの送信受信に主に使われるプロトコル。一般的にメールを送信する際には設定されたSMTPサーバーに接続してSMTPプロトコルで通信する。

今回はこのSendGridを使って、Railsアプリでメール受信するまでをまとめました。

自分のメモを兼ねてRailsアプリの作成から途中で使うツールの解説まで出来る限り丁寧に書いています。

これを作ります

自分のドメイン名宛のメールをSendGrid経由で受信してリストにするところまで作ります。

フレームワーク: Ruby on Rails

データベース: PostgreSQL

その他使うもの: Heroku, ngrok, PG Commander, GitHub

事前準備:

① Rails, Heroku, GitHubが使えるようにしておく(Railsチュートリアルが終わっていればOK)

② ドメインを一つ取得しておく(今回はお名前ドットコムを使用)

Railsアプリの作成

アプリケーション生成
$ rails _5.1.6_ sendgrid_app

Gem file 設定
$ bundle install

(あらかじめGitHubでリポジトリを作成しておく)

ローカルでGitの設定
$ git init
$ git add -A
$ git commit -m 'Initialize repository'
$ git remote add origin <GitHubのリポジトリ>
$ git push -u origin --all

Hello Worldを表示

controller/application_controller.rb

config/routes.rb

Herokuにpush

$ heroku create
$ git push heroku master

PostgreSQLの設定

Homebrewでインストール

$brew install
$brew update postgresql

試しに起動(エラーが出る)

$postgres

エラーが出たらpostgresが入っているのでOK

環境変数の設定

postgresqlをインストールした時に作成された/usr/local/var/postgresを環境変数に入れる

~/.bashrcに以下を追加

export PGDATA='/usr/local/var/postgres'

$ source ~/.bashrc

database.ymlの設定

config.database.yml

設定に合わせてDBとUSER作成

$ createdb sendgrid_development
$ createdb sendgrid_production
$ createuser xxxxxx

development用の環境をマイグレーションする
$ rails db:migrate RAILS_ENV=development

作ったDBの確認

$ psql -l

Name         |    Owner    | Encoding |   Collate   |    Ctype    |      Access privileges

----------------------+-------------+----------+-------------+-------------+-----------------------------

postgres                 | <ユーザー名>| UTF8     | en_US.UTF-8 | en_US.UTF-8 |

sendgrid_development | <ユーザー名> | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

sendgrid_production   |<ユーザー名> | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

PG CommanderでDBの中身を確認

インストールする

https://eggerapps.at/pgcommander/

アプリを開いて設定

Nickname: 自分が分かればOK。アプリの名前とか

Host: localhost

User: database.ymlに設定したユーザーネーム

Password: database.ymlに設定したパス

Database: database.ymlに設定したdatabase

Connectをクリックして接続されればOK

Userの作成

$rails generate controller Users new
$rails generate model User name:string email:string
$rails db:migrate

controller/users_controller.rb

models/user.rb

views/users/new.html

config/routes.rb

nameとemailを持ったユーザー登録が出来るようになりました!

SendGridの設定

SendGridに登録(無料)

https://sendgrid.kke.co.jp/

ReceiveMessageモデルの作成

ReceiveMessageモデルとして受け取ったメールのデータを保管していきます。
$ rails generate model ReceiveMessage from:string subject:string body:text
$ rails g controller ReceiveMessages
$ rails db:migrate

controllers/receive_messages_controller.rb

models/receive_message.rb

views/receive_messages/index.html.erb

メールのデータをDBに直接入れて表示を確認

PG Commanderを開いて左下のNew Rowをクリック

確認用なので適当にデータを入れます。

迷ったらcreated_at, updated_atはフォームの右端をクリックして今日の日付を入れればOKです。

http://localhost:3000/receive_messagesを開くとこんな感じ

今は直接DBにデータを入れましたが、ここからメールを受信したら自動的に一覧に表示されるようにしていきます。

GitHubとHerokuにPush

$ git add -A
$ git commit -m "add: receive_messages"
$ heroku run rails db:migrate

HerokuとPostgreSQLを接続

$ heroku pg:psql
テーブルを確認
<herokuのアプリ名>::DATABASE=> select * from receive_messages;

id | from | subject | body | created_at | updated_at

----+------+---------+------+------------+------------

(0 rows)

空っぽなのでこちらにも手動でデータを入れます。

Heroku用のDBをPG Commanderに接続

Herokuのダッシュボードから現在のアプリケーション→Resources→Heroku Postgres :: Database→Settings→View Credentials

ここに載っている情報をPG Commanderに入力します。

登録できたら同様にPG Commanderからデータを手で入力、保存します。

自分のドメインをSendGridで使えるようにする

SendGridのDomain Whitelabel設定

SendGridを受信用サーバーとして扱うために、SendGridがユーザー(自分)から許可を得てメールの受信をしているという証明が必要となります。

SendGrid公式の解説が詳しいので詳しくはこちらをどうぞ(お名前ドットコムが例で使われています)

https://sendgrid.kke.co.jp/docs/Tutorials/D_Improve_Deliverability/using_whitelabel.html

流れとしては

① Sender Authentication画面で2つの質問に答える

1.の質問はお名前.comを利用している場合は何も選択せず、2.はNoを選びましょう。

② 自分が取得したドメイン名を入力

右側のプレビューの@より後ろが自分のドメイン名になっていればOK。Advanced Settingは不要です。

③ 設定に必要なDNSのレコードが3つ生成される

これらをお名前.com画面でCNAMEレコードとして登録するとSendGridは自分のドメイン宛のメールを受信する許可を得ているという証明になります。

SendGridは開いたまま、お名前.comの「DNSレコード設定」を開いてこれらのCNAMEレコードを設定します。

ホスト名→SendGridからコピー

TYPE→CNAME

TTL→3600

VALUE→SendGridからコピー

ちなみにSendGrid上ではHOSTをコピーするとドメイン名まで丸ごとコピーされますが、お名前.comの画面では自分のドメイン名はあらかじめ入力されているのでコピペするときは注意しましょう。

④ 同じ画面でMXレコードも登録。

ホスト名→自分のドメイン

TYPE→MX

TTL→3600

VALUE→mx.sendgrid.net

全て登録するとこんな感じです。

DNSレコード

サーバーがフルサービスリゾルバ(DNSキャッシュサーバー)にIPアドレスとドメイン名の紐付けについて問い合わせた際、フルサービスリゾルバはさらに権威DNSサーバーに問い合わせます。この際、権威DNSサーバーが自分が管理するドメイン名のDNSレコードを見て応答します。

DNSレコードにはMXレコード、Aレコード、CNAMEレコードなどが含まれます。

MXレコード

ドメイン名と配送先のメールサーバーが書かれています。複数のメールサーバーが指定されているときは"IN MX.."に続く数字が小さい方が優先です。

Aレコード

ドメイン名とそれに対するIPアドレスが書かれています。

CNAMEレコード

ドメイン名とそれに対する別名のドメイン名(あだ名)が書かれています。

④ DNSレコードを登録したら"Verify"を押して、情報が正しく入力されていることを確認します。5分ほどかかったので、黄色の文字でエラーが出るときは何度かVerifyを押してみるとよいかもしれません。

それでも認証ができない場合はコピペのミスかお名前.com上のTYPEがCNAMEになっているかを再度確認してください。

この画面でVerifyの横に自分のドメイン名が表示されればOK

⑤ Address Whitelistの設定

Mail SettingsのAddress WhitelistをONにして自分のドメインを設定する

ngrokの設定

SendGridから受信したメールをHTTPでPOSTしてもらう際には一意のURLを用意してエンドポイントを作る必要があります。

最終的にはHerokuのアドレスにPOSTしますが、開発環境でもngrokを使えば確認が可能です。

ngrokとは

ローカルホストで実行されている内容を...ngrok.ioのアドレスで外部に公開できるサービス。

ngrokが便利すぎる

↑この記事がとても分かりやすいのでここに従いダウンロードと設定を行います。

ちなみにこの記事の「nginxのインストール」の後にngrokのインストールも必要な場合があります。

nginxの起動後に$ ngrok http <自分が現在作業中のローカルホストのポート番号>を入力して"ngrok: command not found"と言われた場合は

$ brew install ngrok
もしくは
$ brew cask install ngrok

でngrokをインストールしましょう。

brew caskはhomebrewの拡張であるhomebrew-caskのコマンドです。homebrew-caskを使うとgoogle-chromeなどのアプリケーションもターミナル上でコマンドにより管理が可能です。

準備が完了したら、現在ローカルホストは3000なので
$ ngrok http 3000
と入力すると..

このForwardingに続くURLでローカルホストの内容が公開されています。

では先程作ったメール一覧画面にアクセスすると...

ローカルの内容に外部からアクセスできるようになりました!!

では"....ngrok.io/receive_messages/create"のエンドポイントを作り、ここに受信したメールのデータをPOSTするしてもらいましょう。

ちなみにこのngrok.ioのURLはngrokを再起動する度に変わってしまうので注意してください。

エンドポイントの設定

エンドポイント

APIにアクセスするためのURLのこと。今回はParse Webhook APIを使い、あらかじめ決めたエンドポイント(.../receive_messages/create)にJSON形式にメール情報をPOSTしてもらいます。POSTされた情報の処理はreceive_messagesコントローラーのcreateアクションに書いていきます。

Inbound Paeseの設定

ダッシュボードのSettings→Inbound Parseを選択

Add Host & URLから先程Domain Whitelabel設定をしたドメインが選択できるので入力

subdomain...空欄

Domain...Whitelabelに設定したドメインが選択肢に出てくるので選択

Destination URL...エンドポイントを入力

エンドポイントを作る

これでSendGridに登録されたドメイン宛にメールが来たらエンドポイント(.../receive_messages/create)にJSON形式にメール情報をPOSTされるようになりました。

POSTされた情報の処理をreceive_messagesコントローラーのcreateアクションに書いていきます。

config/routes.rb

controllers/receive_messages.rb

届いたメールの本文、差出人などの情報がJSONに含まれています。メールが届く度に新しいReceiveMessageモデルを作成して取り出したデータをDBに保管していきます。

この部分はクロスサイトリクエストフォージェリ(CSRF)の対策用にあらかじめRailsに組み込まれている設定を無効にするコードです。

クロスサイトリクエストフォージェリと必須セキュリティトークン

ログインが必要なサイトなどでcookieベースのセッションを使用している場合、ブラウザはリクエストを送信する度にcookieも自動的に送信しています。これを利用して別のサイトからのリクエストをユーザーが閲覧しているサイトに仕込み、別のサイトへのリクエストに対してもcookieを送信させるのがクロスサイトリクエストフォージェリです。

これに対してRailsは必須セキュリティトークンというそのサイトしか知らないトークンを生成してトークンに含めています。リクエストが正しいサイトから送信されているかは必須セキュリティトークンの有無で判断が可能です。

そのためSendGridなど外部のサイトからPOSTリクエストを送信した場合、必須セキュリティトークンを含まないためエラーが発生します。これを防ぐために"protect_from_forgery except: :create"と書くことでReceiveMessageControllerのcreateアクションにおけるリクエストでは必須セキュリティトークンが不要となります。

メール送信してみよう!

さっそく先程設定したドメイン宛にメールを送信してみます。

届いた!!

ちなみにメール送信したのに届かない場合はSendGridのActivity Feedを確認しましょう。

Activity Feedに「Parse」とドメイン名が書かれていればSendGridまではメールが到達していることが確認できるので、ターミナル上でエラーを確認すると良いかもしれません。ここにも表示されていない場合はSendGridにも届いていないのでMXレコードなどを確認してください。

GitHubとHerokuへデプロイ

ここは先程と同じです
$ git add -A
$ git commit -m 'Receive Email'
$ git push
$ git heroku push

SengGridにHerokuを登録

このままでは送信されたメールが全てローカルにPOSTされます。

そこで、Send GridのInbound Parse画面から今度はHerokuのアドレスをPOST先に設定しましょう。

では再度メールを送信!

Herokuのアプリ上でメールを受信できました!!

これでSendGridを使ってRailsアプリ上でメールを受信できるようになりました。

今回はメールの受信ボックスをイメージして、件名と差出人のみ表示してみました。ここから件名をクリックするとメール全文が表示されたり、差出人ごとにボックスを分けたりと工夫してみてください。

 


-プログラミング

Copyright© 言葉の森をてくてくと  , 2020 All Rights Reserved Powered by STINGER.

%d人のブロガーが「いいね」をつけました。