LoginSignup
10
15

More than 3 years have passed since last update.

【Laravel】Mailableを使ってメールを送信する方法。データや画像を添付する方法や入力データをメール本文に渡す方法

Posted at

Mailableを使ってメールを送信する方法について。

【Laravel】Localhostでgmailを使ってメールを送信する方法。Mailableを使わない方法と使う方法の続きです。

基本的な設定や各記述の意味は上記リンク参照。

目次

  1. .envの設定
  2. Mailableクラスの作成
    1. Mailableで使える主なメソッド
  3. コントローラの作成
  4. ルーティングの作成
  5. コンタクトフォームの作成(view)
  6. メール内容の作成(view)
  7. サーバーを起動とメール送信処理の実行
  8. メールにデータを添付する方法
  9. メール本文に画像を埋め込む方法
  10. メール本文にデータを渡す方法
    1. Controllerの変更
    2. Mailableクラスの変更
    3. コンタクトフォームのview変更
    4. メール本文のview変更
    5. メール送信結果の確認


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.

image.png

▼ファイルを編集

ContactReply.php(編集後)
<?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('メールの標題');
    }
}

中にある関数は、__constructbuildの2つのみ。
今回は、build関数にメール本文の処理を記述。

宛先はコントローラに記述する。



Illuminate\Bus\Queueable
キュー関連のメソッド(接続指定など)をもつクラス。

Illuminate\Contracts\Queue\ShouldQueue
非同期で実行するため、ジョブをキューへ投入することをLaravelへ知らせるクラス。

Illuminate\Mail\Mailable
メール送信処理を指定するメソッドを持つクラス。

Illuminate\Queue\SerializesModels
Eloquentモデル(モデルのこと)をシリアライズするメソッドを持つクラス。

詳しいことは説明が見つからずよくわからなかったが、Mailableクラスとキューに関係するクラスのuse宣言をしている。



__construct()
コンストラクタ。クラスをインスタンス化した初回時に実行する処理を記述する。

▼コンストラクタの使用例

コントローラのsendアクションから渡されたデータを受け取り、プロパティに代入する場合などに使える。

Controllerのsendアクション
$params = array();
$params['name'] = 'your name';

Mail::to('送信先メールアドレス')->send(new ContactReply($params));

 ↓ インスタンス生成時にデータ$paramasを渡す

ContactReply.php
public function __construct($params)
{
   $this->params = $params;
}

paramsプロパティに$paramsが入る。



build()
build関数の中にメール本文となるビューの指定などを記述する。

Mailableの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.

image.png

MailableController.php
<?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 に以下を追記。

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ディレクトリを作成するのはコンタクトフォームに様々な種類ができたときにまとめて保存しておくため。

image.png

index.blade.php
@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タグが表示される。

Controllerのsentアクション
 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

image.png

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の内容が表示される

image.png

 ↓ 「送信」をクリック

image.png



▼Gmailの受信内容

image.png

ページも表示され、Gmailにもメッセージが届いている。

以上でMailableを使ったメールの送信が完了。

以降は応用編として。


メールにデータを添付する方法

ファイルや画像をメールに添付する方法について。

Mailableのattachメソッドを使うことで簡単に添付できる。

attach('ファイルのパス')

▼パス指定の注意点
パスはURIではなくディレクトリパスを指定する。

・OK: public_path('img/cat.jpg')
戻り値はディレクトリパスになる。

・NG: assets('img/cat.jpg')  
戻り値はURI。

ContactReply.php
    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
image.png

▼メール送信結果
image.png

画像の添付に成功。


storageディレクトリを活用する方法

publicディレクトリは公開されているディレクトリのため、公開していないアセットを送りたい場合は、storageディレクトリに設置する方法がある。

attach(storage_path('ファイルパス'))
ファイルパスにstorage配下のパスを指定すればOK。


メール本文に画像を埋め込む方法

メールに添付する以外に、メール本文に画像を埋め込むことも可能。

<img src="{{ $message->embed(ファイルパス) }}" >
  • $messageはLaravelが自動生成する。定形として使用。
  • embedメソッドでファイルパスを指定する

この場合も、assetヘルパー関数でURLを指定するのではなく、ディレクトリのパスを指定する。

text.blade.php
emailsディレクトリのtext.blade.phpの内容です

<img src="{{ $message->embed(public_path('img/small-cat.jpg')) }}" alt="">

▼メール本文

image.png


メール本文にデータを渡す方法

コンタクトフォームに入力されたデータをメール本文に渡す方法について。

変更する必要があるファイルは3つ。

  1. Controller
  2. Mailable
  3. View
  • コントローラで入力されたデータを受け取り、Mailableインスタンスに渡す。
  • MailableインスタンスからViewにデータを渡す。
  • Viewで受け取ったデータを表示する

といった流れとなる。


1. Controllerの変更

MailableController.php
<?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変更

コンタクトフォームのビューにメアドとメッセージの入力欄を追加する。

index.blade.php
@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

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. メール送信結果の確認

image.png

 ↓送信する

image.png

送信後も入力内容が表示されている。



▼メールの受信内容

image.png

入力した内容がそのままメール本文に反映されている。

10
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
15