WEBLOG
Laravel > メール
Laravel公式の「メール」で「Mailableの記述 > Senderの設定」の箇所には、メール送信の分だけSenderを作成する方法が書かれてあります。また、各メール送信において view は送信メール・自動返信メールの2ファイルを作ることになります。htmlメールを送信したい場合はさらにtext形式のファイルを作成することになり、4ファイルが必要です。
この方法だとメール送信の数だけSenderとview(blade)4ファイルを作成することになりますが、下記のようなメール送信を行う場合、どのような管理になるでしょうか。
上記の場合30ファイル作成することになります。
管理面からもいい構築方法とは思えません。
弊社では、Senderは共通1ファイル、view(blade)は各メール1ファイルで管理。結果、7ファイルで構築しています。
今回はこの管理方法を紹介します。
基本的なファイル構成は下記のように配置します。
■ app
|-■ Http/Controller
|- XxxController.php(メール送信実行)
|- MailSend.php(Sender)
■ resorces/views
|- ■ emails
|- mail-contact.blade.php(view)
|- mail-order.blade.php(view)
|- 以下略(view)
コントローラーには、設定値と送信実行部分を記述します。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use App\Mail\MailSend;
use Error;
use Mail;
use Str;
class XxxController extends Controller
{
/**
*
* thanks
*
*/
public function thanks(Request $request)
{
/* validate */
/* mail */
$thanks_text = 'エラーが発生しました。';
if ($request->_token === session('_token')) {
$mail_subject = 'お問い合せ';
$mail_config = (object) [
'client' => (object) [
'email' => \C::MAILTO,
'name' => \C::MAILNAME,
],
'user' => (object) [
'email' => $request->email,
'name' => $request->name ?? 'no_name',
],
'subject' => (object) [
'to' => 'オンラインシステムからの' . $mail_subject,
'auto_return' => $mail_subject . 'を受付けました(' . \C::MAILNAME . ')',
'error' => 'メールエラーが発生しました',
],
'content' => (object) [
'markdown' => 'emails.mail-contact',
'with' => [
'mail_subject' => $mail_subject,
'email' => $request->email,
'name' => $request->name,
'is_error' => false,
],
],
];
$thanks_text = $mail_subject . 'が完了いたしました。<br>メールにてお送りしておりますのでご確認ください。';
try {
Mail::to($mail_config->client)
// ->bcc([])
->send(new MailSend($mail_config, 'to'));
Mail::to($mail_config->user)
->send(new MailSend($mail_config, 'auto_return'));
$request->session()->regenerateToken();
} catch (\Exception $e) {
$thanks_text = $mail_subject . '送信時にエラーが発生しました。';
$thanks_text .= $e->getCode() === 450 ? '<br>「' . $mail_config->user->email . '」のドメインが特定できませんでした。' : '';
Mail::to($mail_config->client)
->send(new MailSend($mail_config, 'error'));
}
}
return view('public.contact-thanks', [
'thanks_text' => $thanks_text,
]);
}
}
\C::MAILTO(送信先メールアドレス) や \C::MAILNAME(クライアント様名) は、別途設定している定数です。
$request でフォームから name(名前)とemail(Eメール)を取得している想定です。
この$mail_config 部分記述をすれば、後は後述のSenderがメールを送信してくれます。
Senderファイルは、「MailSend.php」としました。
これは、どのプロジェクトでも共通でそのまま使用します。
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class MailSend extends Mailable
{
use Queueable, SerializesModels;
public $mail_config;
public $type;
/**
* メッセージ インスタンス作成
*
* @return void
*/
public function __construct(object $mail_config, string $type)
{
$this->mail_config = $mail_config;
$this->type = $type;
}
/**
* メッセージ エンベロープ取得
*
* @return \Illuminate\Mail\Mailables\Envelope
*/
public function envelope()
{
if ($this->type === 'to') {
$form = (object) [
'email' => $this->mail_config->user->email,
'name' => $this->mail_config->user->name,
];
$subject = $this->mail_config->subject->to;
} elseif ($this->type === 'auto_return') {
$form = (object) [
'email' => $this->mail_config->client->email,
'name' => $this->mail_config->client->name,
];
$subject = $this->mail_config->subject->auto_return;
} elseif ($this->type === 'error') {
$form = (object) [
'email' => $this->mail_config->client->email,
'name' => $this->mail_config->client->name,
];
$subject = $this->mail_config->subject->error;
}
// dd(new Address($form->email, $form->name));
return new Envelope(
from: new Address($form->email, $form->name),
subject: $subject,
);
}
/**
* メッセージ内容の定義
*
* @return \Illuminate\Mail\Mailables\Content
*/
public function content()
{
return new Content(
markdown: $this->mail_config->content->markdown,
with: array_merge($this->mail_config->content->with, ['type' => $this->type]),
);
}
/**
* メッセージの添付ファイル
*
* @return array
*/
public function attachments()
{
return [];
}
}
viewは、markdown形式で記述します。送信メールも自動返信メールも一つのファイルで作成します。
@php
/*--------------------------------------------------------------------------
mail-contact.blade
@memo
/*---------------------------------------------------------------------------*/
@endphp
@section( 'main_content' )
## {{ $email }}
@endsection
<x-mail::message>
@if ( $type === 'to' )
# 下記のメールが届きました
<x-mail::panel>
@yield( 'main_content' )
</x-mail::panel>
@elseif( $type === 'error' )
# メールエラーが発生しました
メールアドレスなどに問題があり自動返信は停止されました。
<x-mail::panel>
@yield( 'main_content' )
</x-mail::panel>
@elseif( $type === 'auto_return' )
# この度は、{{ $mail_subject }}いただき誠にありがとうございました。
本メールは、送信いただいた皆様に自動返信しております。<br>
ご連絡いただいた内容は下記の通りです。
<x-mail::panel>
@yield( 'main_content' )
</x-mail::panel>
拝見させていただいた上で追って連絡いたします。<br>
お返事に関しましては、事情により数日かかる場合がございますので、しばらくお待ちください。
どうぞよろしくお願いいたします
@include('emails.sign')
@endif
</x-mail::message>
署名は別途 sign.blade.php で作成しています。
***
{{ \C::MAILNAME }}
xx市xx区xx町1丁目1-1<br>
TEL : 078-000-0000(代)
***
htmlメールのデザインは、「resources\views\vendor」に公式の方法でファイルを作成し、cssやマークアップを変更します。
デザインの確認は、毎回メールを送信していてはロスなので、「web.php」に確認用ルートを作成します。
下記のルーティングを設置しておけば「/mailpreview/to/」「/mailpreview/auto_return/」で、ブラウザ確認できます。
Route::get('/mailpreview/{type}', function ($type) {
$mail_type = $type ?? 'auto_return'; // to || auto_return || error
$mail_config = (object) [
'client' => (object) [
'email' => 'formtest@oldoffice.com',
'name' => \C::MAILNAME,
],
'user' => (object) [
'email' => 'xxx@xxx.com',
'name' => 'Preview',
],
'subject' => (object) [
'to' => 'メールタイトル(to)',
'auto_return' => 'メールタイトル(auto_return)',
],
'content' => (object) [
'markdown' => 'emails.mail-contact',
'with' => [
'email' => '{email}',
'error' => 'メールエラーが発生しました',
],
],
'content' => (object) [
'markdown' => 'emails.mail-contact',
'with' => [
'mail_subject' => '{mail_subject}',
'name' => '{name}',
'email' => '{email}',
],
],
];
return new App\Mail\MailSend($mail_config, $mail_type);
});