今参加しているプログラミングスクールでの課題で、LaravelでECsiteを作っているのですが、注文が確定したときにメールを送信する機能をつけようと思いました。
それを備忘録ようにメモします。
作りたいもの
- ECsite(の一部)
- 商品の注文が確定したときに、「注文完了」のメールを送りたい
- gmailのアドレスから送信する
gmailの二段階認証の設定とアプリパスワードの発行
送信元のgmailのアカウントの二段階認証がOFFの場合はONにします。
googleアカウント -> (左側の一覧から)セキュリティ -> 2段階認証
に進み、指示に従って設定を済ませてください。
そして再び「セキュリティ」画面に戻ると、「2段階認証」がオンになっている下で、「アプリパスワード」という項目があると思うので、それをクリックします。
認証が完了するとアプリパスワードの生成画面が出てくるので、「アプリを選択」->「メール」、「デバイスを選択」->「windowsパソコン」に設定します、デバイスの部分はお使いのデバイスに合わせてください。
そして生成を押すと、16桁のアプリパスワードが生成されるのでこれをコピーしておきます。
メールドライバやFromアドレスの設定
ドライバ等の設定はlaravel/config/mail.phpで行っていますが、実際の記述は.envファイルに記述するようになっているので、laravel/.envを確認し、以下のように変更します。
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=<送信元gmailのアドレス> #gmailの場合、USERNAMEはFROM_ADDRESSと同じ
MAIL_PASSWORD=<先程のアプリパスワード>
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=<送信元gmailのアドレス>
MAIL_FROM_NAME=ECSiteSample #メールの件名なのでご自由に
Laravelのmailableクラスの作成
メール送信クラスであるmailableクラスを生成します。 クラス名は「SampleNotification」とします。
# artisanコマンドでmailableクラスを生成する
php artisan make:mail SampleNotification
メール本文の作成
resources/viewにemailフォルダを作り、そこにsample_mail.blade.phpを作成します。メール毎に内容を変えたい部分は変数を置いておきます。
<!DOCTYPE html>
<html lang="ja">
<style>
body {
background-color: #fffacd;
}
h1 {
font-size: 16px;
color: #ff6666;
}
#button {
width: 200px;
text-align: center;
}
#button a {
padding: 10px 20px;
display: block;
border: 1px solid #2a88bd;
background-color: #FFFFFF;
color: #2a88bd;
text-decoration: none;
box-shadow: 2px 2px 3px #f5deb3;
}
#button a:hover {
background-color: #2a88bd;
color: #FFFFFF;
}
</style>
<body>
<p>{{$text}}</p></br>
<p>購入商品は</p>
<table>
@foreach ($data as $values)
<td>{{$values['product_name']}}</td>
<td>{{$values['number']}}</td>
@endforeach
</table>
</br>
<p>ありがとうございました</p>
</body>
</html>
mailableクラスの変更
mailableクラスを以下のように変更します。送りたい内容に合わせて、適宜変更してください。
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class SampleMail extends Mailable
{
use Queueable, SerializesModels;
protected $title;
protected $text;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($name, $text, $data)
{
$this->title = sprintf('%s様', $name);
$this->text = $text;
$this->data = $data;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.sample_mail')
->subject($this->title)
->with([
'text' => $this->text,
'data' => $this->data,
]);
}
}
__constructはコンストラクタで、メール処理が発動した際に引数をとって、それぞれをメンバ変数へ格納しています。
build()メソッド内では、view()メソッドでHTMLメールのビューをセット、subject()メソッドでメールのタイトルをセット、withメソッドでviewに渡す変数をセットしています。先ほどの本文で他に変数を設定した場合は、ここで値を渡してあげてください。
コントローラーの設定
コントローラーにメールを送るように記述します。
ルーティングによって、注文ボタンが押されたらpostPurchaseCompleteメソッドを呼び出すようにし、以下の記述を加えます。
$mail_name = $request->get('user_name');
$mail_text = $mail_name.' 様、ご購入ありがとうございました';
$data = $request->session()->get('ordered_data');
$mail_to = $request->get('mail_address');
Mail::to($mail_to)->send( new SampleMail($mail_name, $mail_text, $data) );
僕の場合は確認画面からPOSTで購入者氏名とメールアドレス、そしてsessionに購入データが
$data = { {'prodeut_name'=>'りんご', 'number'=>3}
{'product_name'=>'バナナ', 'number'=>1} };
という形で入っているので、これをそのまま渡しています。
取り敢えず、先程のSampleMail.phpのconstructメソッドに渡した引数を、SampleMailクラスに渡せば大丈夫です。
うまくいかない場合
一度エラーが出たら
php artisan config:cache
によってキャッシュを削除しないと、ファイルを変更してもうまくいかない場合があるようです(この理由はよくわかりません...)