ActionMailerのSMTP設定を動的に変更する
この記事について
Rails からメールを送る際、ActionMailerを使ってメールを送るケースが多いと思だろう。
しかし メールを送るサーバーを動的に設定したい場合はどうすればいいかについて解説している記事は少ないため、この記事で解説する。
一般的にRailsからActionMailerを使ってSMTP経由でメールを送る場合、下記の記事が参考になる。
この場合、SMTPサーバーの設定を config/environment.rb
や config/environments/production.rb
に config.action_mailer.smtp_settings = { ... }
として設定することになる。
これは、1つのアプリケーションから1つのメールサービスしか使用しない場合は問題なく動作するが、ユーザーやグループによってアプリケーションが使用するメールサーバーを変えたい場合は意図したように機能しないだろう。
この記事ではユーザーやグループによってアプリケーションが使用するメールサーバーを変えたい場合、つまりは1つのアプリケーションから複数のメールサーバーを使用する場合について1つの解法を示していく。
定石
Railsでメールを送る場合、Railsガイド / Action Mailer の基礎 / Action Mailerを設定する に沿ってメールサーバーの設定を config/environment.rb
や config/environments/production.rb
に対して config.action_mailer.smtp_settings = { ... }
として設定することになる。
ActionMailer::Base.smtp_settings = {
:user_name => 'your_sendgrid_username',
:password => 'your_sendgrid_password',
:domain => 'yourdomain.com',
:address => 'smtp.sendgrid.net',
:port => 587,
:authentication => :plain,
:enable_starttls_auto => true
}
この場合はActionMailer経由の全てのメールがこのSMTP設定を用いて配信されることになる。
カスタマイズ
しかし実際のところはユーザーやグループによっては特定のメールサーバーにSMTPで接続してメールの配信を行いたいといったケースが出てくる事が多い。
上記のように ActionMailer::Base.smtp_settings = {}
で設定してしまう場合、適用した瞬間から次に上書きされるまでの間はそのSMTP接続を使用してメール送信を行なってしまうため、タイミング次第では意図しないSMTPサーバーの使用・・・古い言葉を使うと『混線』を起こすことになる。
これに対する1つの解法としては、ユーザーやグループといったメールサーバー毎にコンテナ化したアプリを配置することで解決する方法もあるが、今回は1つのRailsアプリ(コンテナ)で複数のメールサーバー話を使用するカスタマイズを行うやり方の1つを紹介する。
やり方
カスタマイズといってもそう大したことをするわけではなく、 ActionMailer::Base#mail
の引数である delivery_method_options:
を利用する。
delivery_method_options
については Railsガイドで解説されているが、実際に認知されているケースは多くないように感じる。
Railsガイドではuser_name
、password
、address
を上書きしている例が書かれているが、実はこの delivery_method_options:
は同様に他のsmtp_settings
の値についても設定する事ができる
実際にやってみる
はじめに、ActionMailer::Base
モジュールに設定されたデフォルトのsmtp_settings
を取得してみる
ActionMailer::Base.smtp_settings
=> {:address=>"localhost", :port=>25, :domain=>"localhost.localdomain", :user_name=>nil, :password=>nil, :authentication=>nil, :enable_starttls_auto=>true}
何も設定されない場合は上記のような設定になっている。
ここでSaaS経由でのメール送信について実行してみる。
SendGridでAPIキーを使ったメール送信を行う場合、SMTP接続設定パラメータは下記のようになる。
ActionMailerの設定項目 | 設定値 |
---|---|
user_name |
apikey |
password |
APIキーの値 (仮に {APIキー} とする) |
address |
smtp.sendgrid.net |
domain |
メール送信元ドメイン (仮に {送信元ドメイン} とする) |
authentication |
login |
enable_starttls_auto |
true |
port |
587 |
これをActonMailerで動的に使用する場合、下記のようにdelivery_method_options:
を使って、メール毎のSMTPサーバーの設定を上書きする。
(送信先アドレスは、仮に{YOUR_TEST@MAIL.ADDRESS}
として設定)
ActionMailer::Base.mail(
to: '{YOUR_TEST@MAIL.ADDRESS}',
from: 'from@{送信元ドメイン}',
subject: 'テストメール',
body: 'メール本文',
delivery_method_options: {
user_name: 'apikey',
password: '{APIキー}',
address: 'smtp.sendgrid.net',
domain: '{送信元ドメイン}',
authentication: 'login',
enable_starttls_auto: true,
port: 587,
}
).deliver_later
上記の例では ActionMailer::Base
に対して上書きを行っているが、app/mailers
配下の各クラスに対しても同様の処理を行ってメール配信を行う事ができる。
HogeNotify.mail(
to: '{YOUR_TEST@MAIL.ADDRESS}',
from: 'from@{送信元ドメイン}',
subject: 'テストメール',
body: 'メール本文',
delivery_method_options: {
user_name: 'apikey',
password: '{APIキー}',
address: 'smtp.sendgrid.net',
domain: '{送信元ドメイン}',
authentication: 'login',
enable_starttls_auto: true,
port: 587,
}
).deliver_later
また、rails consoleから確認する場合は deliver_later
ではなく deliver
を使う事で同期的にメールを送って確認する事ができる。
1. consoleを起動する
bundle exec rails c
Running via Spring preloader in process 2509
Loading development environment (Rails 6.0.3.4)
2. メールを送信する
ActionMailer::Base.mail(
to: '{YOUR_TEST@MAIL.ADDRESS}',
from: 'from@{送信元ドメイン}',
subject: 'テストメール',
body: 'メール本文',
delivery_method_options: {
user_name: 'apikey',
password: '{APIキー}',
address: 'smtp.sendgrid.net',
domain: '{送信元ドメイン}',
authentication: 'login',
enable_starttls_auto: true,
port: 587,
}
).deliver
まとめ
以上のように ActionMailerが利用するメールサーバーは、 config/environment.rb
や config/environments/production.rb
に対して設定する以外に、ActionMailer::Base#mail
の引数である delivery_method_options:
を使って設定する事で、動的なSMTPサーバー設定を施す事ができる。
これはサービスを利用するユーザーやグループ単位でのメールサーバの切替等に活用できる仕組みであり、Railsの高い汎用性を表している一面であるとも言えるのではないだろうか。
Discussion