letter_opener_web が動かなかった
現在やっているプロジェクトを開始した当初からメール送信のローカル確認のために letter_opener_web を入れていた。
これは以前からも利用しており特に問題が起きたこともなかったので普通に動くだろうと思って導入した。
が、動かなかった。
正確に言うと http://localhost:3000/letter_opener
にアクセスしてメール確認画面は何の問題なく表示されるが、メールが届かない。それ以外、どこにも何もエラーが出ていない。。
意味不明な状態だった。
とりあえず使っている、開発環境
利用している開発環境は以下のような形で、特に特殊なことはしていない
- Docker for Mac
- Rails 6.x
- Ruby 2.x
- docker-compose
- Sidekiq (メールの送信もこちらを使って非同期で送信)
結局、、
- Mailer を常に
deliver_later
で利用している - letter_opener_web のメール情報のデフォルト保存先が
tmp/letter_opener
になっている - tmp 下が docker-compose で volumes で同期対象外になっていた
の組み合わせで起こっているという事が原因でした。
Mailer を常に deliver_later
で利用している
順を追って説明していくとまずこちら。
Sidekiq worker を利用しているためメール送信は全て deliver_later として全て worker に任せています。
それをデバッグのために rails console で deliver_now!
としたのが始まりでした。
# 実装では deliver_later を使っている
UserMailer.hoge.deliver_later
# のを ↓ で rails console 上でデバッグ
UserMailer.hoge.deliver_now!
すると無事メールが届いた。
でも何故?
謎が解けないので、 letter_opener_web を改めて見ることにした
すると README.md でも書かれているが
If you're using :letter_opener_web as your delivery method, you can change the location of the letters by adding the following to an initializer (or in development.rb):
LetterOpenerWeb.configure do |config|
config.letters_location = Rails.root.join('your', 'new', 'path')
end
のような設定を発見。
なるほど、メールはファイルとして config.letters_location
に指定された場所に保存されるのか。
で、デフォルトの config.letters_location
は?
で見つけた。なるほど tmp/letter_opener
か。
ここでやっと気付き
docker-compose で tmp
を同期しないようにしていたっけ
# この app_base を rails と sidekiq で共通に利用している
x-base: &app_base
# ...略...
volumes:
- .:/app
- /app/tmp
- /app/log
- /app/.git
↑ のようにローカルのファイルを全て /app
に同期しつつ、 tmp
log
.git
は同期しないように別ボリュームにしてしまっている。
全てを理解した
deliver_later
でメール送信した場合に Sidekiq 側で問題なくメール送信 (tmp/letter_opener にメール書き出し) が行われていたが、いざ rails server 側で http://localhost:3000/letter_opener
にアクセスしようとすると、 tmp/letter_opener
の同期がコンテナ間で同期されていないためメールが見えなかった。
deliver_now!
で送信した際にはメールは rails server 側で送信されるため、http://localhost:3000/letter_opener
にアクセスした際もローカルに作成されている tmp/letter_opener
を参照する為届いているように見えた。
という単純なことでした。
解決策としては
-
tmp
を volume 同期対象にする -
letters_location
をtmp
外にする
のどちらかを行えば解決出来そうとのことで、現在のプロジェクトでは
LetterOpenerWeb.configure do |config|
config.letters_location = Rails.root.join('.letter_openner')
end
のコードを入れることにより無事 letter_opener_web が動くようになりました。
めでたしめでたし
教訓
README 読め!
以上