Laravel中級編③メールの使い方

Webサービスではユーザーにメールを送る機能がよく使われています。キャンペーンのお知らせやパスワードの変更など様々な場面で使われていますよね。Laravelにもメール機能が備わっていて簡単に実装できるので学んで行きましょう。

この記事の対象者
  • Laravelでメールを実装したい
  • MailTrapについて知りたい
  • markdownについて基本的な知識がない

基本的なメールの使い方

メールといってもLaravelにはMailファサードが備わっているので簡単に実装できます。コントローラーでMailファサードを呼び出し、宛先やタイトルを設定します。

use Illuminate\Support\Facades\Mail;

public function Send(Request $request){
      $this->validate($request, [
    		'email' => 'required|email'
    	]);

      Mail::raw('動作しました', function($message){
        $message->to(request('email'))->subject('タイトル');
      });
      return redirect('/mail')->with('message' , '送信しました');
}

Viewは下記のような感じで設定しました。コントローラーで設定したバリデーションのエラーやうまくいった時のセッションを受け取れるように書いて行きます。

<form method="post" action="{{ url('/mail/send') }}">
	@csrf
  <div>
    <input type="text" name="email">
		@error('email')
		<div>{{$message}}</div>
		@enderror
		<button type="submit">送信</button>
  </div>
	@if('session')
	<div>{{session('message')}}</div>
	@endif
</form>

@errorやsessionで受け取ります。
ブラウザで確認します。

ルーティングも設定して行きましょう。

Route::get('/mail', function () {
    return view('mail');
});
Route::post('mail/send', 'HomeController@Send');

では、実行して行きましょう。

上手くいってますね。うまくコントローラーが機能してsessionにメッセージが渡り、表示されています。

ですが、これではメールが本当に送られたのか判断できません。メールが送信されたかは「storage/logs/laravel.log」で確認できます。

タイトルは文字化けしてますが、送信先やメッセージは正常なことが確認できます。

この他にもメールの送信者やそもそもlogではなく別の方法でメールを確認したい、ということがあると思います。その時は.envを編集しましょう。

MAIL_MAILER=log //ここでlogから確認できるよう設定しています
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=user
MAIL_PASSWORD=1234
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=admin@example.com //送信者のアドレスを設定
MAIL_FROM_NAME="${APP_NAME}"

MailTrapの設定

送信されたメールをログで確認していましたが、MailTrapを使うともっと便利に確認できます。

使い方は超絶簡単です。
ユーザー登録をして選択項目からLaravelを選択します。
表示された情報を.envファイルに入力します。

.envファイルに入力してもキャッシュが残っているので削除しましょう。

php artisan config:cache

もう一度同じようにブラウザから送信します。

MailTrapに新しいメールがきていると思うので開きます。

実際にメールがきた時のような表示がされていて、確認しやすいですね。

Mailクラスの使用

上記までで簡単なメールは送れるようになりました。しかし、複雑なメールとなるとコントローラー内で完結するのが難しいです。そこで、下記のコマンドを使用し、メール文面を作成するViewを呼び出すように書いて行きます。

php artisan make:mail ContactMail

「app/Mail/ContactMail」が作成されているので、編集して行きます。

public function build()
    {
        return $this->view('emails.contactMail'); //編集
    }

「views/emails/contactMail.blade.php」を作成し、編集します。
今回は簡単なものにしました。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>

    </head>
    <body>
        <p>ContactMail</p>
    </body>
</html>

あとは、コントローラーからContactMailを呼び出すように書いて行きます。

use App\Mail\ContactMail; //追加

public function Send(Request $request){
      $this->validate($request, [
    		'email' => 'required|email'
    	]);
      // Mail::raw('動作しました', function($message){
      //   $message->to(request('email'))->subject('タイトル');
      // });
      Mail::to(request('email'))->send(new ContactMail()); //追加

      return redirect('/mail')->with('message' , '送信しました');
    }

再び、ブラウザから送信してメールを確認します。

タイトルが指定していないのでファイルの名前になっています。
その他は上手くいってますね。

引数を使う

メールに引数を渡すことも出来ます。
タイトルを変える方法と一緒に紹介します。

まずはコントローラーから任意の文字を渡します。

public function Send(Request $request){
      $this->validate($request, [
    		'email' => 'required|email'
    	]);
      // Mail::raw('動作しました', function($message){
      //   $message->to(request('email'))->subject('タイトル');
      // });
      Mail::to(request('email'))->send(new ContactMail('Laravel')); //ContactMeに渡す文字を指定

      return redirect('/mail')->with('message' , '送信しました');
    }

ContactMailも文字を渡せるように編集して行きます。

class ContactMail extends Mailable
{
    use Queueable, SerializesModels;

    public $topic; //追加

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($topic)
    {
        $this->topic = $topic; //追加
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.contactMail')
        ->subject('トピックは' . $this->topic . 'です。'); //追加
    }
}

Viewでも引数を受け取れるように編集します。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>

    </head>
    <body>
        <p>ContactMail</p>
        <p>{{$topic}}</p> //追加
    </body>
</html>

では、ブラウザから再び送信してメールを確認します。

上手くいってますね。

markdownを使う

Laravelではmarkdownが用意されています。
markdownを使うことでオシャレなメールが簡単に使えます。

まずはコントローラーを編集して行きます。

public function build()
    {
        return $this->markdown('emails.contactMail') //viewをmarkdownに変更
        ->subject('トピックは' . $this->topic . 'です。');
    }

viewをmarkdown用に変更します。

@component('mail::message')
# head

- list
- list
- list

@component('mail::button', ['url' => 'ここにURL'])
  URL
@endcomponent

@endcomponent

インデントやスペースがズレただけで機能しなくなるので注意しましょう。

では、ブラウザから送信してメールを確認します。

随分と変わりましたね。

markdownの編集

componentのbuttonなどは「vender/laravel/framework/src/Illuminate/Mail/resources/views/html」の中にあります。デザインが気に入らなければここを編集しましょう。

また、Laravelのロゴがいらないな、という時にはターミナルから下記の2つのコマンドを打ちます。

php artisan vendor:publish --tag=laravel-notifications
php artisan vendor:publish --tag=laravel-mail

「resources/views/vendor/mail/」の下に「header.blade.php」などのメールテンプレートのソースコードが作成されます。ロゴを消すためには下記を削除します。

@if (trim($slot) === 'Laravel')
<img src="https://laravel.com/img/notification-logo.png" class="logo" alt="Laravel Logo">
@else
{{ $slot }}
@endif

気づいたかもしれませんが、ターミナルで入力したコマンドによって「vender/laravel/framework/src/Illuminate/Mail/resources/views/html」の中にあったファイルが「resources/views/vendor/mail/」の中に来ています。深い階層まで行かなくて良いので便利ですね。

markdownの便利機能

markdownはメールクラス作成時に指定することも出来ます。
下記のように入力することでMailクラス作成とViewの作成を一気に行なってくれます。

php artisan make:mail Contact --markdown=email.contact

markdownを指定することでMailクラスに最初からmarkdownで書かれたファイルが作成されます。

public function build()
    {
        return $this->markdown('email.contact');
    }

一緒に作成されたviewも確認してみましょう。

@component('mail::message')
# Introduction

The body of your message.

@component('mail::button', ['url' => ''])
Button Text
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

上手く出来てますね。
コントローラーも編集してContactが機能するようにしましょう。

public function Send(Request $request){
      $this->validate($request, [
    		'email' => 'required|email'
    	]);
      Mail::to(request('email'))->send(new Contact('Laravel')); //new Contactに変更

      return redirect('/mail')->with('message' , '送信しました');
}

では、ブラウザから送信してメールを確認します。

ロゴも消えて上手く表示されています。

関連記事