メール送信
モジュール作成の一番最初の項目は「メール送信」である。 メールの送信機能は web サービスを運営していく上で現代ではまだ必要不可欠である。 メールの送信は、単にユーザー認証だけでなく、お便り、緊急のメンテナンス、通知などさまざまな利用法がある。
メール送信の厄介なところは rails や Next 意外にクラウドや DNS、メールプロトコルを活用しなくてはならないことである。 近年は AWS の SES が利用できるので、メールサーバーを運用したりと面倒なことは比較的少なくなった。 それでもまだまだ面倒な設定が多々ある。
このモジュールではメール送信が最終目標ではあるが、その過程で、ドメインの取得、SES の認証と設定、IAM の取得、rails の設定と段階的に解説する。
Route53 でドメインを取得
SES を使ったメールの送信は大きく分けて2つある。 1つはあなたが保有している gmail などの web メールを利用して ses が代理で送る機能である。 ただ、こちらの方法は web サービスで利用す仕組みとしてはあまり推奨されてない。 多くの場合、web サービスを運用するドメインから送信する方法が採用されている。 n ドメインの取得は web サービスをリリースする上で遅かれ早かれ必要になる。 ただ、web サービス名が決まっていなかったり、作っていく過程でサービス名が変わってしまったりするので、 理想的にはこれでサービス名が定まってからドメインは取得した方が良い。
ここでは仮にサービス名が定まり、ドメインを取得できる算段が立ったと仮定して解説を進める。 なお、すでにテスト用のドメインがある場合はここで無理にドメインを購入せずに、適当なドメインを利用してもよい。
Route 53 のマネジメントコンソールを開く。 左のサイドバーの「登録済みドメイン」をクリックする。

「ドメインの登録」を選択。

取得したいドメイン名、例えばexample.netを入力・選択し「チェック」を押すと、使用の可否と関連するドメインが表示される。
取得したいドメインが使用可能であれば、カートに入れて次に進む。

あなたの連絡先の詳細を入力する。 取得するドメインによって異なるが、.net の場合、「登録者」「管理者」「技術者」の連絡先を別々で登録するか、全て同じにするか選べます
danger
「プライバシーの保護」を必ず有効化する。(whois コマンドで一部連絡先情報が非表示になる)

次に進み、入力した情報を確認する。

danger
「ドメインを自動的に更新しますか?」は必ず有効化する。(期限切れ防止)
先ほど入力した「登録者」のメールアドレスに確認メールが飛んだことが記載されている。 メール確認の前に、注文を完了させることができるので、先に進む。

注文が正常に送信されたことが確認できる。

ドメインの注文完了から登録完了まで最大3日程度かかる。

注文直後は、ドメインは保留中のリクエストとして登録されている。

しばらくすると登録が完了する。
danger
しかし、ここで 5 分以上待たされる場合は先にメールを確認しにいく。(確認メールの有効期限は注文完了から 15 分以内)
メール確認が完了すると、以下の通り「検証済み」に変更される。

ドメインの取得が完了。
SES でドメイン認証
SES からメールを送る場合は取得したドメインが本当にあなたのものであるか確認する必要があ流。 ここからはその手順を紹介する。
AWS コンソールの SES のページに移動し、左のメニューの「Verified identities」をクリックする。

移動後、オレンジ色の「Create identity」をクリック。

「Domain」にチェックを入れて、現れたフィールドに取得したドメインを入力する。

「Verifying your domain」の隠れている「Advanced DKIM settings」をクリックして、「Easy DKIM」をクリック。 「DKIM signing key length」は「RSA_2048_BIT」を選択。

最後にオレンジの「Create Identity」をクリックする。 SES が作成され、自動的に DKIM のレコードが Route53 に登録される。


しばらくすると(5 分程)、Verified(確認済み)、Successful(成功)の文字が表示される。

SNS の作成
SES では、バウンスや苦情の対応が必要になる。放置しておくと SES 利用停止になってしまう。
まずは新しく SNS を作成する。
AWS マネージメントコンソールのサービスメニューから[SNS]を選択する。 左メニューから[トピック]を選択する。

一覧上部に表示される[トピックの作成]をクリック。

トピックの設定では下記設定にて新規登録をおこなう。
タイプ:スタンダード 名前:任意の名称 (ses-feedback)

内容を入力して画面下の[トピックの作成]をクリックする。
SNS と SES の連携
AWS コンソールの[SES]に移動する。
左メニューから[Verified identities]を選択して、作成済みの設定からバウンス処理が必要な Identity を選択して詳細画面を表示する。

詳細画面で[Notifications]タブを選択し、「Email feedback forwarding」の項目が Enabled になっている事を確認して、 「Feedback notifications」の[Edit]をクリックする。

通知設定は Bounce / Complaint / Delivery の 3 点がある。 今回は Bounce と Complaint に対して作成した SNS を適応させる。

Include original email headers にチェックを入れる。
「Save changes」ボタンを押して完了。
SNS からメールに通知を送る
再び SNS のコンソール画面に戻り、サブスクリプションの追加を行う。 「ses-feedback」はどこに通知したら良いかを設定する。
左の「トピック」から作成した「ses-feedback」を選択

「サブスクリプションの作成」をクリック。

「プロトコル」で E メールを選び、出てきたテキストフィールドにあなたのメールアドレスを入力する。
一番下の「サブスクリプションの作成」をおす。

すると AWS からメールが届くの登録したメールアドレスの受信ボックスにとび、届いたメールを開く。 リンクの「Confirm subscription」をクリックすれば、SNS の利用が可能になる。

テストメールの送信
SES バウンスが SNS で通知されるか、テストメール送信を送信する。 SES コーンソール画面で作成した Identity をクリックする。 詳細画面の「Send test email」をクリック。

入力項目をこの様に埋める。
- From-address:test
- Scenario:Bounce
- Subjent:バウンステスト件名
- Body:バウンステスト本文

入力が終わったら「Send test mail」ボタンをおす。 下記のようにメールが届いたら問題なく動作している。

同様に、苦情もテストメールする。
もう1度、「Send test email」 をクリックして、フォームを表示して、下の様に埋める。
- From-address:test
- Scenario:Complaint
- Subjent:苦情テスト件名
- Body:苦情テスト本文

SES に何らかの悪意ある攻撃でバウンスが多発しても対処できる準備ができた。
サンドボックス環境の解除
SES は作成するとサンドボックス環境におかれる。 メールを外部に送信するにはこのサンドボックス状態を解除する必要がある。

- Mail type: Transactional
- website URL: オプションなので、リリース用のドメイン URL があれば指定する。まだはっきりしない場合は空。
- Use case description: 利用目的を英語で書く
- Preferred contact language: En と Ja 選べるけど En で良い。
「Acknowledgement」にチェックを入れる。
入力が終わったら、「Submit request」をおす。


申請後、内容が確認されて、問題がなければ sandbox が解除される。

サンドボックス内で外部にメールを送る場合
承認に時間がかかったり、用途が必ずしも本番環境とは限らない場合、無理に申請を通す必要はない。 SES にあらかじめ送信先のメールアドレスを登録しておけば、SES からそこにメールを送ることができる。
SES の verified identities 画面の「create identity」ボタンをおす。

Email Address にチェックを入れて、あなたが受信できるメールアドレスを入力する。「create identity」ボタンをクリックする。

入力したメールアドレスにメールが送られてくるので、リンクをクリックする。
認証が完了すれば、SES は登録したメールアドレスに自由にメールを送ることができる。 この時の挙動は Sandbox を抜けた場合と同じなので、試しにやる分にはこの方法で問題ない。
試しにメールを贈りたい場合は上のバウンスメールを送信したように、SES コーンソール画面で作成した Identity をクリックする。
詳細画面の「Send test email」をクリック。
項目を入力する。
- From-address:no-reply
- Scenario:Custom
- Custom recipient: 登録したメールアドレス
- Subjent:hello
- Body:hello

Send test mail で問題なくメールが送られる。
SES の IAM の取得
SES 経由でメールが送れる準備が整ったので、次に IAM の取得に移る。 SES を外部のプログラムから実行するには権限を持つ IAM を作成する必要がある。
IAM のコンソール画面に移動。

サイドバーのユーザーに移動。

右上の「ユーザーを追加」をクリック。

任意のユーザ名を入力し「アクセスキー-プログラムによるアクセス」を選択する。

「ユーザーを追加 」では特に権限を付与せずに、進める。

タグも特につけない。

最終確認で「ユーザーの作成」をクリック。

とりあえず、権限なしのユーザが作成される。 アクセスキー ID とシークレットアクセスキーはこのタイミングでしか保存、ダウンロードできないので大事に保管しておく。

そしたら、一度、閉じて、ユーザー一覧に移動し、作成したユーザーを選ぶ。
そのまま「アクセス権限」タブの「アクセス権限の追加」 をおす。

「既存のポリシーを直接アタッチ 」タブを選び、検索フォームで「sesfull」と打ち込む。表示された ses の full アクセスにチェックを入れる。
「次のステップ:確認」を押す。

確認画面を見て、そのまま「アクセス権限の追加」ボタンを押す。
追加される。

取得したアクセスキーとシークレットキーがあれば、ses を外から操作することが可能になった。
Rails からメール送信
このモジュールでは開発環境下における rails のサーバー側だけで動くメール送信を試す。 フロントから何らかの情報を受け取りメールを送るような仕組みはまだ作らない。
環境変数の設定
Rails で扱う環境変数(SES を操作するための IAM のアクセスキーとシークレットキー)は rails5.2 からconfig/credentials.yml.encに保存される様になった。このファイルは少々特殊で、そのまま開くと暗号化されて中身が確認できない様になっている。
ファイルを開く場合は、こちらのコマンドで開き編集する。ちょうどcorntab -e に近い操作感である。
ファイルを開くエディタはその都度指定するが、解説上は VSCode を利用する。
まずは、master_key がないと rails を利用できないように指定する。
config/environments/development.rbを開き、適当なところに以下のコードを追加する。
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
config.require_master_key = true
続いて、本番環境でも master_key がない場合は利用できなくしたいので、config/environments/production.rbを開く。
こちらはすでに master_key の設定がコメントアウトされた状態であるので、それをコメントインする。
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
config.require_master_key = true
下のコマンドでcredentials.yml.encを開く。
EDITOR="code --wait" bin/rails credentials:edit
このようなファイルが開かれる。
# aws:
# access_key_id: 123
# secret_access_key: 345
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: xxxx
ここの aws のところをコメントインして、上で取得した SES のアクセスキーとシークレットキーを入力する。
aws:
access_key_id: your_aws_access_key
secret_access_key: your_aws_secret_key
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: xxxx
Command + s で保存して、Command + w でファイルを閉じる。するとconfig/credentials.yml.encに Git の差分が生まれる。
git add .
git commit -m "Set aws keys"
メール送信の設定
Rails で SES の設定をするには、aws-sdk-rails を利用する。
bundle add コマンドから追加する。
bundle add aws-sdk-rails
それと rails6.1.5 に限った問題でメールを送信しようとすると smtp のエラーが発生する。
詳しい記述はこちらの記事に書いてある。
https://qiita.com/jnchito/items/4ef331281f0050428716
そのため、こちらもインストールしておく。 また、将来的に本番環境下でも同様にnet-popとnet-imapが無いとエラーが出るのでそれも加える
bundle add net-smtp net-pop net-imap
git add .
git commit -m "Install aws-sdk-rails"
aws-sdk の設定を記述するファイルを作成する。
touch config/initializers/aws.rb
config/initializers/aws.rbを開いて以下を記述する。region は東京つまり ap-northeast-1 を利用していると思う。
もしも違う場合は aws ses の console で調べてそちらを入力する。
Aws::Rails.add_action_mailer_delivery_method(
:ses,
credentials: Aws::Credentials.new(Rails.application.credentials.aws[:access_key_id],
Rails.application.credentials.aws[:secret_access_key]),
region: 'ap-northeast-1'
)
config/environments/development.rbを開き、action mailer で利用するタイプを ses に設定する。
config.action_mailer.delivery_method = :ses
次にテスト用の mailer を作って送信してみる。
bin/rails g mailer TestMailer test
自動的に複数のファイルが作成される。
app/mailers/test_mailer.rbを開いて
内容を SES のものに変更する。
- from: は SES のコンソールで Bounce と Complain の送信を試した時の「From-address」のアドレスを利用する。
- to: は自分が受け取れるメールアドレスを指定する。
class TestMailer < ApplicationMailer
default from: 'no-reply@example.com' # example.comにSESで登録したアドレスを指定
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.default_mailer.test.subject
#
def test
@greeting = "Hi"
mail to: "テストメールを受信するあなたのアドレス" #追加
end
end
保存したら Rails のコンソールから作成した TestMailer 経由で SES からメールが送れるか試す。
bin/rails c
コンソールが切り替わったら、TestMailer.test.deliver_nowを実行する。これは TestMailer クラスの test 関数からメールを送るというコマンドである。
TestMailer.test.deliver_now
to:で指定したメールアドレスのメールボックスにこのメールが来たら成功である。

少し改造して、test 関数に引数を持たせて、ダイナミックにメールの subject を変更できる様にする。
app/mailers/test_mailer.rbを開いて、test関数をこのように変更する。
def test(subject="default subject")
@greeting = "Hi"
mail to: "テストメールを受信するあなたのアドレス", subject: subject
end
Rails コンソールをリロードして、変更を再読み込み。
reload!
メールのサブジェクトをこんにちは世界に変更して送ってみる。
TestMailer.test("こんにちは世界").deliver_now
この様なメールが届く。

rails から ses を使ってメールを配信できる様になった。
「メール送信」モジュールはここまでである。
git add .
git commit -m "Send email from rails and ses"