Laravel5で送信メールサーバー設定

2017.6.11 (日)

SMTPサーバの設定

Laravelからメール送信するには、.envで送信メールサーバの設定をしておきます。phpのsendmail(mb_sendmailかな。)を使う場合は、MAIL_DRIVERをmailで設定します。
ここではGmailのSMTPを使った設定をします。自分のGmailアカウントに合わせて設定しておきます。

# .env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=xxxxxx@gmail.com
MAIL_PASSWORD=xxxxxxxxxxxxxxx
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=from@example.com
MAIL_FROM_NAME=test

.envはconfig/mail.phpで読み込まれているのでmail.phpの設定も合わせて確認しておきましょう。
確認はtinkerでできるっぽいです。to@mail.comを受信できる適当なメールアドレスにしてテストします。

php artisan tinker
>>> Mail::raw('test mail',function($message) {$message->to('to@mail.com')->subject('test');});

ステータスが1で返ってきたらOK。(しかし私の環境ではnullが返ってきたのだけど正常にメール送信されました。)
また以下のような返り値が来る場合があります。

Swift_TransportException with message 'Expected response code 250 but got code "530", with message "530 5.7.1 Authentication required"'

ステータスが250で正常なのだけど530もあるよということで、メール送信できない。そういう場合は、キャッシュをクリアすると正常になります。

php artisan cache:clear
php artisan config:cache

メールの設定デバック

tinkerで

dd(\Config::get('mail'));

をすると現在の設定が出ます。たいていキャッシュに古い設定情報が残っているというのが原因。

メール送信の開発系の便利なツール(Mailtrapを利用して、テストメールを送信する)

こういうのが無料で使えるんだからすごいですよね。
https://mailtrap.io/

クロージャを使って送信する

ルーティングの際に直接メールを送信させます。

Route::get('welcome/{name?}', function($name = "ゲスト") {
    Mail::send('mails.welcome', ['name' => $name], function($message) {
        $message->to('user@example.com')->subject('Welcome');
    });

    return "Welcome メッセージを $name に送りました";
});

/welcome/foobarみたいな感じでアクセスすると送信できます。
テンプレートは以下のように設定しておきます。

resources/views/mails/welcome.blade.php

コントローラからメール送信

Larabelのメール送信はLaravel5.3でメール送信の実装でとてもわかり易く説明してあります。
汎用的に使うとしたらルーティングのクロージャではなくメール送信クラスを作成してそれをそれぞれのコントローラで使うというやり方になります。
メールクラスはartisanで雛形を作成できます。

php artisan make:mail BaseMail
app/Mial/BaseMail.phpが作成されます。

リクエスト(POST値とか)がない場合

フォームの入力内容などを送信メールに反映させるみたいなものがない場合は、そのまま送信することができます。
設定が必要なものは以下になります。
– .env
– config/mail.php
– app/Mail/BaseMail.php
– welcome.blade.php: resources/views/mails/welcome.blade.php
– 任意のコントローラ

.envとconfig/mail.phpはすでに設定してあるものとします。
artisanで作成したBaseMailは以下のように設定しておきます。

// app/Mail/BaseMail.php
/**
 * Build the message.
 *
 * @return $this
 */
....
public function __construct($options, $data)
{
    $this->options = $options;
    $this->data = $data;
}

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->from($this->options['from'], $this->options['from_jp'])
        ->subject($this->options['subject'])
        ->bcc($this->options['bcc'])
        ->view($this->options['template']);
}
....

こんな感じでbuildメッセージを追加しておきます。
任意のコントローラでは、

// Require for sendmail
use Mail;
use App\Mail\BaseMail;

....
public function mail() {
    $mail_to = "oosamuuy@gmail.com";
    $options = [
        'from' => 'from@example.com',
        'from_jp' => '【○○より】',
        'to' => $mail_to,
        'subject' => '登録完了のお知らせ',
        'template' => 'mails.welcome',
        "bcc" => "oosamuuy@gmail.com",
    ];

    $emaildata = [
        'mail_to' => $mail_to,
                'text' => 'foobar',
    ];
    Mail::to($mail_to)->send(new BaseMail($options, $emaildata));
}
....

こんな感じになります。BaseMailクラスに$emaildataでまとめてパラメータを送っているので、メールテンプレート(view)では上記の場合だと{{$mail_to}}とか{{$text}}で値を受け取ることができます。

リクエストがある場合

通常メール送信はリクエストからきたデータを何らかの形でつかうことが多いと思うのでこっちが主流かと思います。
まずはBaseMail.phpのbiuldメソッドでリクエストを受けてあげます。

use Illuminate\Http\Request; // 追加
....
public function build(Request $request)
{
    var_dump($request->input('INPUTNAME'));
    return $this->view('mail.sample')
            ->with("username", $request->input('INPUTNAME1'))
            ->with("email", $request->input('INPUTNAME2'))
            ->subject('テストメール');
}

もし別のリクエストクラスを使っているのだったらそのクラスを呼んでください。これでリクエストをメールクラス内で扱えるようになります。リクエストから利用するPOST値をもってくればよいです。
リクエストの値をメールテンプレート内で利用するにはWEBページと同じでwith()メソッドで渡してあげます。指定したbladeのテンプレートでそのまま使うことができます。これはらくちんだ。
メールのクラス(つまりフロントコントローラの1つ前だとリクエストをテンプレートに送信できますが、フロントコントローラでも同じことができるんだろうか?

Laravel5.3でメール送信の実装
laravel5.5のmailableクラスでメール送信を行う[導入/入門編]