LaravelでGmailを使って問い合わせがあった場合に自動でメールを送信する機能を作成する。
いろんなサイトで送信方法に関するページがあるが、ControllerとMailableの違いなど、どのファイルがなんの処理をしているのかがわかりにくかったので一つづつ確認しながら作成し理解を深める。
##目次
-
概要
2. MailファサードとMailableクラスの違い - メール送信に必要なファイル
-
.envの設定
5. Gmailのパスワード
6. ポート番号587と465の違い
7. (補足)MAIL_MAILER=log
の機能
8.MAIL_FROM_ADDRESS
とは?MAIL_USERNAME
との違い
9.MAIL_FROM_NAME
とは? -
コントローラの作成
11. use Mailとは?
12. indexアクションの中身
13. sendアクションの中身
14. sendメソッド
15. Mailファサードのメソッド一覧
16. 入力データを渡す方法 - ルーティングの作成
- コンタクトフォームの作成(view)
- メール内容の作成(view)
- サーバーを起動とメール送信処理の実行
- Mailableを使ったメール送信
##概要 Laravelメールを送信する機能に、`Mailファサード`と`Mailable`クラスがある。
どちらもメール本文となるviewを指定できたりと類似機能があるので混乱のタネになる。
コントローラのsendアクションとMailファサードのsendメソッドも異なるので注意が必要。
###MailファサードとMailableクラスの違い **Mailファサード(を使ったコントローラ)は必須**だけど、**Mailableはなくてもメール送信可能**。
Mailableは本文と添付ファイルの組み合わせを複数パターン作るときに便利。
▼Mailファサード
- コントローラに記述。メール送信に必須。
-
use Mail;
で読み込む - 使い方は
Mail::メソッド
**▼`Mailableクラス`**
- Mailファサードのサポート役
- メール本文を指定できる。
- なくてもメールは送信できる。
- 添付ファイルの指定が簡単。
-
php artisan make:mail [mailableクラス名]
で生成
Mailableを使うパターンと使わないパターンのそれぞれでメールの送信方法を確認する。
###メール送信に必要なファイル
ファイル | 必須 | 内容 |
---|---|---|
.env | ✔︎ | 送信元となるgmailを使うための、環境変数を記述する。メアドとPWなど |
web.php | ✔︎ | ルーティングの設定。コンタクトフォームのルートや送信後のPOSTメソッドで実行するアクションの指定など |
controller | ✔︎ | Mailファサードで送信先やメッセージの内容を指定する |
コンタクトフォームのview | ✔︎ | submitボタンクリックでメール送信を発火する |
メール本文のview | ✔︎ | 送信するメールの本文 |
mailableのクラス | メール送信先やメッセージの内容を指定する |
##.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="送信者の名前" //メールの送信者に表示される名前
###Gmailのパスワード
スマホやPCではなくLaravelなどの外部アプリからGmailを使う場合はアプリパスワードを作成する必要がある。
Googleアカウントにログイン
↓
↓ セキュリティ
↓ アプリパスワード
↓ アプリを選択:メール
↓ デバイスを選択:その他(名前を入力) (例:Laravelなどなんでもいい)
↓ アプリを選択:生成
表示された16桁のパスワードをコピー。(一度しか表示されない!)
これで、アプリパスワードの生成が完了。
###ポート番号587と465の違い `MAIL_PORT=587`はサイトによっては465を使っているところもある。
どちらもメール送信用のポートだが587推奨。
メール送信のプロトコルで指定したSMTP専用のポートが587。
465は過去に使われていた名残で今も使えるが587が正式とのこと。(465はTLS用のポート)
###(補足)`MAIL_MAILER=log`の機能 Gmailを使うためのMAIL_MAILERにはSMTPを指定している。これをlogに変更すると、メールを送信せずに、メールの内容をログに吐き出すようになる。
Gmailなどを使わずに簡易的にメール機能を確認したい場合に使える。
▼ファイルの出力先
storage > logs > laravel.log
▼出力例
メッセージを送信しました。
[2021-01-19 02:11:01] local.DEBUG: Message-ID: <c00e537b1a501@127.0.0.1>
Date: Tue, 19 Jan 2021 02:11:01 +0000
Subject: =?utf-8?Q?=E3=83=86=E3=82=B9=E3=83=88=E9=80=81=E4=BF=A1?=
From: xxx@gmail.com
To: xxx@gmail.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
###MAIL_FROM_ADDRESSとは?MAIL_USERNAMEとの違い `MAIL_FROM_ADDRESS`と`MAIL_USERNAME`に同じメールアドレスを記載している例があるが、**gmailの場合`MAIL_FROM_ADDRESS`は不要**。
MAIL_FROM_ADDRESS
はメールに表示されるメール送信元の表示を変更する機能。
gmailの場合は、MAIL_USERNAME
が送信元のメアドになるため、MAIL_FROM_ADDRESS
を記述してもgmailによって書き換えられてしまう。
###`MAIL_FROM_NAME`とは MAIL_FROM_NAMEに指定した値が、実際にメール送信された時のメール送信者のところに表示される。
例えば、MAIL_FROM_NAME="sample sender"
の場合、以下のように表示される
sample sender <xxx@gmail.com>
指定がない場合は、Exampleとなる。
##定型のメッセージを返信する機能の作成 まずは、入力内容などを使わず、単に決められたメッセージを返す簡単な機能を作成することで、メール送信ができることを確認する。
##1. コントローラの作成 コンタクトフォームの表示とメール送信を行うコントローラを作成する。
作成するのは1ファイルのみでOK。
・$ php artisan make:controller [コントローラ名]
「app > Http > Controllers > コントローラ名.php」 が生成される。
**▼実例**
$ php artisan make:controller ContactController
Controller created successfully.
ファイルを開いて以下を追記する。追記するのは3点。
- Mailファサードのuse宣言
- indexアクション(コンタクトフォームの表示)
- sendアクション(メール送信処理)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mail; //追記
class ContactController extends Controller
//以下追記
{
public function index() //コンタクトフォームを表示
{
return view('contact.index');
}
public function send(Request $request) //メールの自動送信設定
{
Mail::send('emails.text', [], function($data){
$data ->to('送信先のメアド')
->subject('送信メールの表題');
});
return back()->withInput($request->only(['name']))
->with('sent', '送信完了しました。'); //送信完了を表示
}
}
###use Mailとは? `use Mail`はMailファサードのuse宣言。
Illuminate\Support\Facades\Mail::class
のaliasなので、use Illuminate\Support\Facades\Mail
としても同じ。
▼aliasの確認
app > config > app.php にデフォルトで記載されている。
'Mail' => Illuminate\Support\Facades\Mail::class,
###indexアクションの中身
return view('contact.index');
ルートでContactControllerのindexアクションが指定された場合に、ビューとして、ファイルパス views > contact > index.blade.php を返す。
ルーティングとビューは後ほど作成する。
###sendアクションの中身 メール送信機能を担う重要なアクション。
public function send(Request $request) //メールの自動送信設定
{
Mail::send('emails.text', [], function($data){
$data ->to('送信先のメアド')
->subject('送信メールの表題');
});
return back()->withInput($request->only(['name']))
->with('sent', '送信完了しました。'); //送信完了を表示
}
}
####▼public function send(Request $request)
sendはアクション名。引数では、Requestクラスのインスタンスを変数$requestとして渡している。
この手法をメソッドインジェクション(依存注入)と呼ぶ。
####▼Mail::send
Mailファサードのsendメソッドを呼び出している。
####▼sendメソッド
send('ビュー', 関数に渡すデータ, 関数)
- 3つの引数はすべて必要でどれかが抜けるとエラーになる。
- 返信用メールにデータ(例えば、宛先や名前など)を渡す場合は、第2引数に記述する。
- 第3引数の関数で宛先やメールタイトルを指定する。
**▽データがない場合の記述例**
Mail::send('emails.text', [], function($data){
//処理
});
**▽データがある場合の記述例**
Mail::send('emails.text', ['msg'=>'ありがとう!'], function($message){
//処理
});
$data = $request->all() //送信されてきたすべてのデータ
Mail::send('emails.text', $data, function($message){
//処理
});
**※sendメソッドの引数が一つの場合** Mailableクラスを使用する場合はsendメソッドでMailableクラスのインスタンスを渡す。その場合引数は1つとなる。
・例:send(new [Mailableクラス名]($data)
この場合、ファイル上方でMailableクラス名のuse宣言がなされている必要がある。
####▼Mailファサードのメソッド一覧
-
to('メアド', '表示名')
:宛先のメアド。表示名はなくてもいい。 -
subject('テキスト')
:メールの標題 -
cc('メアド')
: cc送信先のメアド -
bcc('メアド')
: bcc送信先のメアド -
from('メアド', '表示名')
:
**・toメソッドの表示名** 送信したメールのtoの部分のメールアドレスを、指定した表示名に置き換える。
**・fromメソッドの注意点** fromメソッドのメアドは環境変数の`MAIL_FROM_ADDRESS`を上書きする処理のためgmailの場合意味をなさない。
表示名でMAIL_FROM_NAME
を上書きすることができる。ただしこの場合でも第一引数にダミーでなんらかのメアドを入れておかないとエラーになる。
##returnの処理 returnは**送信処理完了後に表示するページや内容**を指定する。
returnの記載がない場合、sendアクションが実行されると空白ページが表示される。
・return redirect('パス');
redirect関数でパスを指定すると、指定したパスに飛ぶ。
・return back();
元のページを表示する。
###入力データを渡す方法 ページ遷移をした後に、そのページにフォームの入力データを渡したい場合に使えるメソッドがある。
・withInput()
入力内容をすべて渡す。データの取得はold('キー名')
・withInput($request->only(['name']));
特定のデータのみ渡す。
・with('キー名', 'データ')
指定したデータを渡す。「送信完了しました」などを渡せる。受け取りはsession('キー名')
。
if文の条件で存在確認をしたい場合はSession::has('キー名')
▼実例
return back()->withInput($request->only(['name']))
->with('sent', '送信完了しました。');
よってこれは、現在のページに(1)キー名がnameのデータと、(2)キー名sentで「送信完了しました。」という2つの情報を渡している。
実際に画面に表示する処理はこの後のビュー作成時に指定する。
##2. ルーティングの作成 ルーティングに作成したコントローラのアクションを登録する。
routes > web.php に以下を追記。
Route::get('contact', 'ContactController@index');
Route::post('contact', 'ContactController@send');
・1行目
URL /contactにアクセスしたときに、ContactControllerのindexアクションを実行する。
・2行目
/contactページでpostメソッドが使われたとき、ContactControllerのsendアクションを実行する。
####(注意点)Laravel8の場合 Laravel8の場合、デフォルトではコントローラの名前空間を完全なパスで表記しなければいけない。
省略表記するためには、app > Providers > RouteServiceProvider.phpのコメントアウトを解除する。(以下ページ参照)
##3. コンタクトフォームの作成(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('contact') }}" method="POST">
@csrf
<p>名前:<input type="text" name="name"></p>
<input type="submit" value="送信">
</form>
・@if ( Session::has('sent'))
withメソッドで渡されたデータ(キー名:sent)が存在するなら以下のdivタグを表示する。
つまり、送信ボタンが押された場合にこのdivタグが表示される。
return back()->withInput($request->only(['name']))
->with('sent', '送信完了しました。');
・old('name')
withInput()
で渡されたデータ
・session('sent')
with()
で渡されたデータ
##4. メール内容の作成(view) 送信されるメール本文となるビューを作成する。 コントローラのsendアクションでビューを`emails.text`と指定しているので、以下パスにファイルを作成する。
resources > views > emails > text.blade.php
emailsディレクトリのtext.blade.phpの内容です。
##5. サーバーを起動とメール送信処理の実行
$ php artisan serve
http://127.0.0.1:8000/
http://127.0.0.1:8000/contact にアクセスする。
↓ contacts.index.blade.phpの内容が表示される
↓ 「送信」をクリック
**▼Gmailの受信内容**
ページも表示され、Gmailにもメッセージが届いている。
##Mailableを使ったメール送信 ここまででかなり長くなったので、Mailableを使ったメール送信は別記事で作成します。。