LoginSignup
0
0

More than 1 year has passed since last update.

AWS SES + Ruby / Rails – メールが送信できない場合 ( aws-sdk-rails / aws-sdk-ses )

Last updated at Posted at 2023-04-07

結論

  • 実行ユーザーの IAMに ses:SendEmail ses:SendRawEmail の権限を与える
  • アクセスキーを発行してメール送信を実行する

結論としてはシンプルだが、この手順で解決した

image.png

image.png

問題

  • 「SMTP認証情報の作成」でIAMユーザーに付与される権限 AmazonSesSendingAccess ( AmazonSesSendingAccess ) では何故か送信できなかった
  • 「SMTP認証情報の作成」で発行される「SMTP ユーザー名」「SMTP パスワード」を利用してもメール送信は出来なかった

「SMTP ユーザー名」「SMTP パスワード」はいかにもAWSのアクセスキー・シークレットのような文字列なのだが別物らしい

公式ガイドの手順 ( Ruby で試す )

ApplicationMailer など Rails的なコードを作らなくても、
公式ガイドの手順でRubyでのテストが出来る

Amazon SES E メールアドレスへのメッセージの送信
https://docs.aws.amazon.com/ja_jp/sdk-for-ruby/v3/developer-guide/ses-example-send-email.html

自分の場合は便宜的にRailsでモデルのメソッドにして試した

gemには aws-sdk-ses を使う

require 'aws-sdk-ses' # v2: require 'aws-sdk'

sender = 'yuma.inaura@gmail.com'

recipient = 'yuma.inaura@gmail.com'

subject = 'Amazon SES test (AWS SDK for Ruby)'

htmlbody =
  '<h1>Amazon SES test (AWS SDK for Ruby)</h1>' \
  '<p>This email was sent with <a href="https://aws.amazon.com/ses/">' \
  'Amazon SES</a> using the <a href="https://aws.amazon.com/sdk-for-ruby/">' \
  'AWS SDK for Ruby</a>.'

textbody = 'This email was sent with Amazon SES using the AWS SDK for Ruby.'

encoding = 'UTF-8'

credentials = Aws::Credentials.new(
  '*****',
  '*****'
)

ses = Aws::SES::Client.new(
  region: '*****',
  credentials: credentials
)

begin
  ses.send_email(
    destination: {
      to_addresses: [
        recipient
      ]
    },
    message: {
      body: {
        html: {
          charset: encoding,
          data: htmlbody
        },
        text: {
          charset: encoding,
          data: textbody
        }
      },
      subject: {
        charset: encoding,
        data: subject
      }
    },
    source: sender
  )

  puts 'Email sent to ' + recipient

# If something goes wrong, display an error message.
rescue Aws::SES::Errors::ServiceError => e
  puts "Email not sent. Error message: #{e}"
end

SMTPユーザー/パスワードをアクセスキー・シークレットに指定した場合は以下エラーが起きていた

ruby aws-email.rb

Email not sent. Error message: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

このコードの例はHTMLメールなので、 SendRawEmailの権限しかない場合は
権限がない場合は以下エラーが発生していた

ruby aws-email.rb

Email not sent. Error message: User `arn:aws:iam::00000000:user/ses-smtp-user.000000-000000' is not authorized to perform `ses:SendEmail' on resource `arn:aws:ses:**********:0000000000:identity/***********'

Rails

Gem は aws-sdk-rails をインストールしておく

gem 'aws-sdk-rails'

require "active_support/core_ext/integer/time"

Rails.application.configure do
  # 他のメール送信方法との設定の違いはこの1行だけに収まる ( aws-sdk-rails (3.7.1) )
  config.action_mailer.delivery_method = :ses

  config.action_mailer.default_url_options = { host: 'example.com' }

  config.action_mailer.perform_deliveries = true
  config.action_mailer.perform_caching = false

  # エラーは検知するようにしておこう
  config.action_mailer.raise_delivery_errors = true
...

無理だった例

gemのバージョン ( aws-sdk-rails (3.7.1) ) のせいかは分からないが
次のように credeitials をいちど作って渡す方式では無理で、環境変数を利用しないとうまくメール送信できなかった

credentials = Aws::Credentials.new(
  ENV.fetch('AWS_ACCESS_KEY_ID', nil),
  ENV.fetch('AWS_SECRET_ACCESS_KEY', nil)
)

Aws::Rails.add_action_mailer_delivery_method(
  :ses,
  credentials:,
  region: 'ap-northeast-1'
)

config.action_mailer.delivery_method = :ses

rails console で実行してみる

export AWS_ACCESS_KEY_ID="*******"
export AWS_SECRET_ACCESS_KEY="*********"
export AWS_REGION=**********

rails console

てきとうにメーラーを作っておいてメール送信を実行

irb(main):001:0> ExampleMailer.new_email.deliver_now

SMTP認証情報の作成

image

SMTP認証情報の作成をするとIAMユーザーが作成され、次のように認証情報がダウンロードできる

ses-smtp-user.0000000000-0000000000

SMTP ユーザー名:
*****************

SMTP パスワード:
*****************

だがこのキーを使ってもメール発行は出来なかった

環境

  • aws-sdk-rails (3.7.1)

参考

コマンドラインを使用し、Amazon SES SMTP インターフェイスを介して E メールを送信する
https://docs.aws.amazon.com/ja_jp/ses/latest/dg/send-email-smtp-client-command-line.html

コマンドひとつでメール送信する方は
環境変数にAWSのキーを設定しておく必要があり、なおかつ「SMTP ユーザー名」「SMTP パスワード」は利用できなかった

openssl s_client -crlf -quiet -starttls smtp -connect email-smtp.us-west-2.amazonaws.com:587

ユーザー名やパスワードをbase64 エンコードする方やり方では
この方法では「SMTP認証情報の作成」の「SMTP ユーザー名」「SMTP パスワード」が利用できた

openssl s_client -crlf -quiet -starttls smtp -connect email-smtp.us-west-2.amazonaws.com:587 < input.txt

検証済みメールアドレスにしかメール送信できない

Email address is not verified. The following identities failed the check in region *****
(Aws::SES::Errors::MessageRejected)

送信元に検証済みメールアドレスしか指定できないのは分かるが、送信先にも指定できないとはどういうことだ?

image.png

と思ったらサンドボックス環境だとそういう動作になるようだ

AmazonSESで登録したメールアドレスにしかメールが送れない理由
https://blog.framinal.life/entry/2018/08/24/094009

Amazon SES サンドボックス外への移動

E メールの送信先は、検証済み E メールアドレスおよびドメイン、または Amazon SES メールボックスシミュレーターに制限されます。
https://docs.aws.amazon.com/ja_jp/ses/latest/dg/request-production-access.html

ECSでは

RailsにWebアクセスした時にメール送信する場合、
タスク定義のタスクロールにメール送信のポリシー ( ses:SendEmail ses:SendRawEmail )をつければ良いようだ
(タスク実行ロールではなく)

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

Twitter

0
0
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
0
0