Skip to main content

メール送信

モジュール作成の一番最初の項目は「メール送信」である。 メールの送信機能は web サービスを運営していく上で現代ではまだ必要不可欠である。 メールの送信は、単にユーザー認証だけでなく、お便り、緊急のメンテナンス、通知などさまざまな利用法がある。

メール送信の厄介なところは rails や Next 意外にクラウドや DNS、メールプロトコルを活用しなくてはならないことである。 近年は AWS の SES が利用できるので、メールサーバーを運用したりと面倒なことは比較的少なくなった。 それでもまだまだ面倒な設定が多々ある。

このモジュールではメール送信が最終目標ではあるが、その過程で、ドメインの取得、SES の認証と設定、IAM の取得、rails の設定と段階的に解説する。

Route53 でドメインを取得

SES を使ったメールの送信は大きく分けて2つある。 1つはあなたが保有している gmail などの web メールを利用して ses が代理で送る機能である。 ただ、こちらの方法は web サービスで利用す仕組みとしてはあまり推奨されてない。 多くの場合、web サービスを運用するドメインから送信する方法が採用されている。 n ドメインの取得は web サービスをリリースする上で遅かれ早かれ必要になる。 ただ、web サービス名が決まっていなかったり、作っていく過程でサービス名が変わってしまったりするので、 理想的にはこれでサービス名が定まってからドメインは取得した方が良い。

ここでは仮にサービス名が定まり、ドメインを取得できる算段が立ったと仮定して解説を進める。 なお、すでにテスト用のドメインがある場合はここで無理にドメインを購入せずに、適当なドメインを利用してもよい。

Route 53 のマネジメントコンソールを開く。 左のサイドバーの「登録済みドメイン」をクリックする。

route53のダッシュボード

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

ドメインの登録を選択

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

取得したいドメインが使用可能であれば、カートに入れて次に進む。

ドメインの確認

あなたの連絡先の詳細を入力する。 取得するドメインによって異なるが、.net の場合、「登録者」「管理者」「技術者」の連絡先を別々で登録するか、全て同じにするか選べます

danger

「プライバシーの保護」を必ず有効化する。(whois コマンドで一部連絡先情報が非表示になる)

住所の登録

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

項目の確認

danger

「ドメインを自動的に更新しますか?」は必ず有効化する。(期限切れ防止)

先ほど入力した「登録者」のメールアドレスに確認メールが飛んだことが記載されている。 メール確認の前に、注文を完了させることができるので、先に進む。

注文の確定

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

注文結果

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

登録後に

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

メールの確認待ち

しばらくすると登録が完了する。

danger

しかし、ここで 5 分以上待たされる場合は先にメールを確認しにいく。(確認メールの有効期限は注文完了から 15 分以内)

メール確認が完了すると、以下の通り「検証済み」に変更される。

検証済みドメイン

ドメインの取得が完了。

SES でドメイン認証

SES からメールを送る場合は取得したドメインが本当にあなたのものであるか確認する必要があ流。 ここからはその手順を紹介する。

AWS コンソールの SES のページに移動し、左のメニューの「Verified identities」をクリックする。

Verified identities

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

create identity

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

input domain

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

dkim

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

ses cname

route53 cnames

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

ses success

SNS の作成

SES では、バウンスや苦情の対応が必要になる。放置しておくと SES 利用停止になってしまう。

まずは新しく SNS を作成する。

AWS マネージメントコンソールのサービスメニューから[SNS]を選択する。 左メニューから[トピック]を選択する。

topic

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

new topic

トピックの設定では下記設定にて新規登録をおこなう。

タイプ:スタンダード 名前:任意の名称 (ses-feedback)

create ses feedback

内容を入力して画面下の[トピックの作成]をクリックする。

SNS と SES の連携

AWS コンソールの[SES]に移動する。

左メニューから[Verified identities]を選択して、作成済みの設定からバウンス処理が必要な Identity を選択して詳細画面を表示する。

ses bounce check

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

ses notification

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

enable sns

Include original email headers にチェックを入れる。

「Save changes」ボタンを押して完了。

SNS からメールに通知を送る

再び SNS のコンソール画面に戻り、サブスクリプションの追加を行う。 「ses-feedback」はどこに通知したら良いかを設定する。

左の「トピック」から作成した「ses-feedback」を選択

go topic

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

create subscription

「プロトコル」で E メールを選び、出てきたテキストフィールドにあなたのメールアドレスを入力する。

一番下の「サブスクリプションの作成」をおす。

use email

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

recieve email

テストメールの送信

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

send test mail

入力項目をこの様に埋める。

  • From-address:test
  • Scenario:Bounce
  • Subjent:バウンステスト件名
  • Body:バウンステスト本文

input send mail form

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

sns mail

同様に、苦情もテストメールする。

もう1度、「Send test email」 をクリックして、フォームを表示して、下の様に埋める。

  • From-address:test
  • Scenario:Complaint
  • Subjent:苦情テスト件名
  • Body:苦情テスト本文

complain email

SES に何らかの悪意ある攻撃でバウンスが多発しても対処できる準備ができた。

サンドボックス環境の解除

SES は作成するとサンドボックス環境におかれる。 メールを外部に送信するにはこのサンドボックス状態を解除する必要がある。

sandbox

  • Mail type: Transactional
  • website URL: オプションなので、リリース用のドメイン URL があれば指定する。まだはっきりしない場合は空。
  • Use case description: 利用目的を英語で書く
  • Preferred contact language: En と Ja 選べるけど En で良い。

「Acknowledgement」にチェックを入れる。

入力が終わったら、「Submit request」をおす。

input email for

requested

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

sandbox resolved

サンドボックス内で外部にメールを送る場合

承認に時間がかかったり、用途が必ずしも本番環境とは限らない場合、無理に申請を通す必要はない。 SES にあらかじめ送信先のメールアドレスを登録しておけば、SES からそこにメールを送ることができる。

SES の verified identities 画面の「create identity」ボタンをおす。

new identity mail

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

input own mail

入力したメールアドレスにメールが送られてくるので、リンクをクリックする。

認証が完了すれば、SES は登録したメールアドレスに自由にメールを送ることができる。 この時の挙動は Sandbox を抜けた場合と同じなので、試しにやる分にはこの方法で問題ない。

試しにメールを贈りたい場合は上のバウンスメールを送信したように、SES コーンソール画面で作成した Identity をクリックする。

詳細画面の「Send test email」をクリック。

項目を入力する。

  • From-address:no-reply
  • Scenario:Custom
  • Custom recipient: 登録したメールアドレス
  • Subjent:hello
  • Body:hello

send custom recipeint

Send test mail で問題なくメールが送られる。

SES の IAM の取得

SES 経由でメールが送れる準備が整ったので、次に IAM の取得に移る。 SES を外部のプログラムから実行するには権限を持つ IAM を作成する必要がある。

IAM のコンソール画面に移動。

iam console

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

iam user

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

add user

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

input ses iam form

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

user group

タグも特につけない。

iam tag

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

click user creation

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

blank user

そしたら、一度、閉じて、ユーザー一覧に移動し、作成したユーザーを選ぶ。

そのまま「アクセス権限」タブの「アクセス権限の追加」 をおす。

select new policy

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

「次のステップ:確認」を押す。

ses full access

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

追加される。

ses iam result

取得したアクセスキーとシークレットキーがあれば、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:で指定したメールアドレスのメールボックスにこのメールが来たら成功である。

recieve email from ses

少し改造して、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

この様なメールが届く。

with subject

rails から ses を使ってメールを配信できる様になった。

「メール送信」モジュールはここまでである。

git add .
git commit -m "Send email from rails and ses"