Mailableを使ってメールを送信する方法について。
【Laravel】Localhostでgmailを使ってメールを送信する方法。Mailableを使わない方法と使う方法の続きです。
基本的な設定や各記述の意味は上記リンク参照。
##目次
- .envの設定
-
Mailableクラスの作成
3. Mailableで使える主なメソッド - コントローラの作成
- ルーティングの作成
- コンタクトフォームの作成(view)
- メール内容の作成(view)
- サーバーを起動とメール送信処理の実行
- メールにデータを添付する方法
- メール本文に画像を埋め込む方法
-
メール本文にデータを渡す方法
12. Controllerの変更
13. Mailableクラスの変更
14. コンタクトフォームのview変更
15. メール本文のview変更
16. メール送信結果の確認
##1. .envの設定 Gmailを送信元のメールサーバーとして使うため、環境変数の設定が必須。
ルートディレクトリ直下の.envの下記部分に追記する。
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
↓
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com //gmailを指定
MAIL_PORT=587 //メッセージ送信のポート(465ではない)
MAIL_USERNAME=xxxx@gmail.com //gmailアドレス
MAIL_PASSWORD=xxxxxxxxxxxxxxxx //16桁のPW
MAIL_ENCRYPTION=tls //tls通信
#MAIL_FROM_ADDRESS=null //gmailの場合不要
MAIL_FROM_NAME="送信者の名前" //メールの送信者に表示される名前
##2. Mailableクラスの作成
・php artisan make:mail [Mailableクラス名]
▼実例
$ php artisan make:mail ContactReply
Mail created successfully.
▼ファイルを編集
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ContactReply extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
//以下追記
return $this->view('emails.text')
->subject('メールの標題');
}
}
中にある関数は、__construct
とbuild
の2つのみ。
今回は、build関数にメール本文の処理を記述。
宛先はコントローラに記述する。
・`Illuminate\Bus\Queueable` キュー関連のメソッド(接続指定など)をもつクラス。
・Illuminate\Contracts\Queue\ShouldQueue
非同期で実行するため、ジョブをキューへ投入することをLaravelへ知らせるクラス。
・Illuminate\Mail\Mailable
メール送信処理を指定するメソッドを持つクラス。
・Illuminate\Queue\SerializesModels
Eloquentモデル(モデルのこと)をシリアライズするメソッドを持つクラス。
詳しいことは説明が見つからずよくわからなかったが、Mailableクラスとキューに関係するクラスのuse宣言をしている。
**・`__construct()`** コンストラクタ。クラスをインスタンス化した初回時に実行する処理を記述する。
▼コンストラクタの使用例
コントローラのsendアクションから渡されたデータを受け取り、プロパティに代入する場合などに使える。
$params = array();
$params['name'] = 'your name';
Mail::to('送信先メールアドレス')->send(new ContactReply($params));
↓ インスタンス生成時にデータ$paramas
を渡す
public function __construct($params)
{
$this->params = $params;
}
paramsプロパティに$params
が入る。
**・`build()`** build関数の中にメール本文となるビューの指定などを記述する。
public function build()
{
return $this->view('emails.text')
->subject('メールの標題');
}
・view('emails.text')
メール本文になるビューを指定。
・subject('メールの標題')
メールのタイトルを指定。
###Mailableで使える主なメソッド
メソッド | 概要 | 使用例 |
---|---|---|
view('ビュー') | メール本文となるビューを指定 | view('emails.text') |
subject('') | メールのタイトルを指定 | subject('お問い合わせ') |
with([]) | データを渡す | with(['orderName' => $this->order->name]) |
attach('ファイルパス') | データを添付する。第2引数でファイル名やmimeタイプを指定可能 | attach(public_path('img/cat.jpg') |
attachFromStorage('ファイルパス') | ファイルシステム(オンラインストレージ)のデータを添付する | attachFromStorage('/path/to/file') |
text('ビュー') | 平文で表示するビューを指定 | text('emails.text_plain') |
・平文テキストとは?
暗号化していないデータ。指定したビューの内容をそのまま送る。
##3. コントローラの作成
・$ php artisan make:controller コントローラ名
▼実例
$ php artisan make:controller MailableController
Controller created successfully.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mail; //追記
use App\Mail\ContactReply; //追記
class MailableController extends Controller
{
//以下追記
public function index() //コンタクトフォームの表示
{
return view('contact.index');
}
public function send(Request $request) //メールの自動送信設定
{
Mail::to('hlaupcpky38@gmail.com')
->send(new ContactReply());
return back()->withInput($request->only(['name']))
->with('sent', '送信完了しました。'); //送信完了を表示
}
}
基本的な記述はMailableを使用しないコントローラと同じ。
▼変更点
・use App\Mail\ContactReply;
生成したMailableクラスを使う宣言をする。
・send(new ContactReply())
sendメソッドの引数でMailableクラスのインスタンスを渡す。
##4. ルーティングの作成 ルーティングに作成したコントローラのアクションを登録する。
routes > web.php に以下を追記。
Route::get('contact2', 'MailableController@index');
Route::post('contact2', 'MailableController@send');
・1行目
URL /contact2にアクセスしたときに、ContactControllerのindexアクションを実行する。
・2行目
/contact2ページでpostメソッドが使われたとき、ContactControllerのsendアクションを実行する。
formのactionでこのパスを指定しておく。
####(注意点)Laravel8の場合 Laravel8の場合、デフォルトではコントローラの名前空間を完全なパスで表記しなければいけない。
省略表記するためには、app > Providers > RouteServiceProvider.phpのコメントアウトを解除する。(以下ページ参照)
##5. コンタクトフォームの作成(view) /contactにアクセスしたときに表示するビューを作成する。
indexアクションでview('contact.index')
を指定しているので、resources > views > contact > index.blade.php を作成する。
views配下ならどこでもいいが、contactディレクトリを作成するのはコンタクトフォームに様々な種類ができたときにまとめて保存しておくため。
@if ( Session::has('sent'))
<div>
<p>{{old('name')}}さん、{{ session('sent') }}</p>
</div>
@endif
<form action="{{ url('contact2') }}" method="POST">
@csrf
<p>名前:<input type="text" name="name"></p>
<input type="submit" value="送信">
</form>
submitボタンをクリックすると、actionで指定したcontact2のページにPOSTメソッドでアクセスし、ルーティングでコントローラのsendアクションを実行する。
・@if ( Session::has('sent'))
withメソッドで渡されたデータ(キー名:sent)が存在するなら以下のdivタグを表示する。
つまり、送信ボタンが押された場合にこのdivタグが表示される。
return back()->withInput($request->only(['name']))
->with('sent', '送信完了しました。');
・old('name')
withInput()
で渡されたデータ
・session('sent')
with()
で渡されたデータ
##6. メール内容の作成(view) 送信されるメール本文となるビューを作成する。 コントローラのsendアクションでビューを`emails.text`と指定しているので、以下パスにファイルを作成する。
resources > views > emails > text.blade.php
emailsディレクトリのtext.blade.phpの内容です。
##7. サーバーを起動とメール送信処理の実行
$ php artisan serve
http://127.0.0.1:8000/
http://127.0.0.1:8000/contact2 にアクセスする。
↓ contacts.index.blade.phpの内容が表示される
↓ 「送信」をクリック
**▼Gmailの受信内容**
ページも表示され、Gmailにもメッセージが届いている。
以上でMailableを使ったメールの送信が完了。
以降は応用編として。
##メールにデータを添付する方法 ファイルや画像をメールに添付する方法について。
Mailableのattach
メソッドを使うことで簡単に添付できる。
・attach('ファイルのパス')
▼パス指定の注意点
パスはURIではなくディレクトリパスを指定する。
・OK: public_path('img/cat.jpg')
戻り値はディレクトリパスになる。
・NG: assets('img/cat.jpg')
戻り値はURI。
public function build()
{
//以下追記
return $this->view('emails.text')
->subject('メールの標題')
->attach(public_path('img/cat.jpg'));
}
・attach(public_path('img/cat.jpg'))
public_pathヘルパ関数はpublicディレクトリ配下のパスを指定することで完全なパスを返す。
###画像を設置する
今回の場合は、 public > img > cat.jpg
画像の添付に成功。
###storageディレクトリを活用する方法 publicディレクトリは公開されているディレクトリのため、公開していないアセットを送りたい場合は、storageディレクトリに設置する方法がある。
・attach(storage_path('ファイルパス'))
ファイルパスにstorage配下のパスを指定すればOK。
###メール本文に画像を埋め込む方法 メールに添付する以外に、メール本文に画像を埋め込むことも可能。
<img src="{{ $message->embed(ファイルパス) }}" >
-
$message
はLaravelが自動生成する。定形として使用。 -
embed
メソッドでファイルパスを指定する
この場合も、asset
ヘルパー関数でURLを指定するのではなく、ディレクトリのパスを指定する。
emailsディレクトリのtext.blade.phpの内容です。
<img src="{{ $message->embed(public_path('img/small-cat.jpg')) }}" alt="">
▼メール本文
##メール本文にデータを渡す方法 コンタクトフォームに入力されたデータをメール本文に渡す方法について。
変更する必要があるファイルは3つ。
- Controller
- Mailable
- View
- コントローラで入力されたデータを受け取り、Mailableインスタンスに渡す。
- MailableインスタンスからViewにデータを渡す。
- Viewで受け取ったデータを表示する
といった流れとなる。
##1. Controllerの変更
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mail;
use App\Mail\ContactReply;
class MailableController extends Controller
{
public function index() //コンタクトフォームの表示
{
return view('contact.index');
}
public function send(Request $request) //メールの自動送信設定
{
$data = $request->all(); //追記
Mail::to('hlaupcpky38@gmail.com')
->send(new ContactReply($data)); //変更
return back()->withInput() //変更
->with('sent', '送信完了しました。'); //送信完了を表示
}
}
・$data = $request->all();
コンタクトフォームに入力された内容を受け取り、変数dataにいれる。
allメソッドでRequestの全データを取得する。
・send(new ContactReply($data))
Mailableのクラス(ContactReply)からインスタンスを作成した際に$data
を渡すため引数に記載。
・withInput()
withInputの引数を削除。これまでは1つのデータ(name)のみを送信後の画面に渡していたが、すべてのデータを渡すようにする。
遷移後のページでデータを参照する時はold('キー名')
とする。
##2. Mailableクラスの変更 コントローラから受け取ったデータ(`$data`)を受け取り、使えるようにする。
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ContactReply extends Mailable
{
use Queueable, SerializesModels;
public $data; //追記
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($data) //変更
{
$this->data = $data; //追記
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
//以下追記
return $this->view('emails.message')
->subject('メールの標題')
->with('data', $this->data); //追記
}
}
・public $data;
コントローラからのデータを受け取るため、インスタンスプロパティを用意する。
・$this->data = $data;
__construct
の引数で変数を指定し、受け取ったデータをインスタンスプロパティにセットする。
・->with('data', $this->data);
withメソッドでインスタンスプロパティのデータをviewに渡す。
##3. コンタクトフォームのview変更 コンタクトフォームのビューにメアドとメッセージの入力欄を追加する。
@if ( Session::has('sent'))
<div>
<p>{{old('name')}}さん、{{ session('sent') }}</p>
</div>
@endif
<form action="{{ url('contact2') }}" method="POST">
@csrf
<p>名前:<input type="text" name="name" value="{{old('name')}}"></p>
<p>メールアドレス:<input type="text" name="email" value="{{old('email')}}"></p>
<p>メッセージ:
<textarea name="message">{{ old('message') }}</textarea></p>
<input type="submit" value="送信する">
</form>
・url('contact2')
urlヘルパ関数で指定したURLの完全なURIを返す。
・old('キー名')
withやwithInputメソッドで渡されたデータを表示する。
上記では、送信ボタンをクリック後に入力データがそのまま残るように指定している。
##4. メール本文のview変更 メール本文に受け取ったデータを使って表示するコードを追記する。 今回は、新しいファイルを用意して記述する。
resources > views > emails > message.blade.php
<p>名前:{{ $data['name'] }}さん</p>
<p>メールアドレス:{{ $data['email'] }}</p>
<p>---以下メッセージが送信されました---</p>
<p>{!! nl2br( $data['message'] ) !!}</p>
・$data['キー名']
Mailableの->with('data', $this->data);
で渡されたデータを取得している。
・{!! !!}
htmlspecialcharsをエスケープせずに呼び出す。
よく見かける{{ }}
はクロスサイトスクリプティング(XSS)防止のため一部の特殊な記号が実行されないように変換される。
ここで{{!! !!}}
を使うのは、ユーザーが打ち込んだ内容をそのまま表示するため。
これがないと、改行が<br />
として表示されてしまい読みづらい。
・nl2br()
改行を改行のまま表示するメソッド。
これがないと、改行がスペースに変換され繋がって表示されてしまう。
なので、{!! nl2br( ) !!}
はユーザーの入力データをそのまま表示するためのコード。
以上で修正が完了
##5. メール送信結果の確認
↓送信する
送信後も入力内容が表示されている。
**▼メールの受信内容**
入力した内容がそのままメール本文に反映されている。