顧客「Aの機能の時は、hoge@gmail.comで確認メールを送信して欲しいんだよね」
ぼく「わかりました」
顧客「Bの機能の時は、hogehoge@gmail.comで確認メールを送信して欲しいんだよね」
ぼく「承知の助」
1時間後
ぼく「ん?むずくね?」
というわけで、詰まったお話
##なんで詰まったのか
LaravelのMailってfromとかのfunctionがあって一見簡単に切り替えられるように見えるんですけど
Mail::from('hogehoge@gmail.com')
->to($request->user_mail)
->send(new Mail($request->user_name));
まぁ当たり前なんですけど、ダメなわけで
そもそもGmailを使用するには、当然usernameとpasswordを使用しているわけで、それを.envに書いて読み込んでるわけですよね
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME= hoge@gmail.com
MAIL_PASSWORD=passpasspasspasspass
MAIL_ENCRYPTION=ssl
要はこの
MAIL_USERNAMEと
MAIL_PASSWORDはいつ読み込まれて、どうやって変更するんだ!!
って悩んだわけですよ。
参考にさせてもらったのが↓
かなりわかりやすくプロセスのライフサイクルとサービスコンテナについて書いてくれていて助かりました。
かいつまんで説明すると
・ユーザーからリクエストがくる
・app.phpがMailServiceProviderをコンテナに格納する
・内部でTransportManagerがnewされる(singleton)
・createSmtpDriver()でusernameとpasswordがconfigから読み込まれる
・メールをsendする際に、読み込まれたusernameとpasswordなどからメールが送信される
という流れなわけですよ。
これsingletonとか諸々の影響で、後から書き換えられない(できるかもしれないけど)せいでまぁえらい時間がかかりました。
結局どうやったの?
こうやりました↓
extract(\Config::get('temp_mail'));
$transport = (new \Swift_SmtpTransport($host, $port))
->setUsername($username)
->setPassword($password)
->setEncryption($encryption);
\Mail::setSwiftMailer(new \Swift_Mailer($transport));
\Mail::to($request->user_mail)
->send(new TempMail($request->user_name));
<?php
return [
'host' => 'smtp.gmail.com',
'port' => '465',
'username' => 'hogehoge@gmail.com',
'password' => 'passpasspasspass',
'encryption' => 'ssl',
];
何をやっているの?
既存のSwiftMailerだと
transport(usernameとかpasswordとか持ってるあれ)
がcontrollerに処理が届く前に、configから読み込まれて上書きできないので
もう1から$transportを作って、 SwiftMailerもろともnewしちゃいましょうって解決法でした。
これは
https://laravel.io/forum/07-22-2014-swiftmailer-with-dynamic-mail-configuration
にて参考にさせてもらいました。
というかね
本当にlaravelのMailでさくっと出来ないんですかね・・・?
めちゃくちゃ頻発する案件だと思うんですが。。
何か他にさくっとできる方法があったら共有していただきたいです。