WEBLOG

Laravel > メール

Laravel メールでMalable(sender)とblade(view)を共通化する

Create:

Update:

Category:Laravelメール

[ Version.22 ]

概要

Laravel公式の「メール」で「Mailableの記述 > Senderの設定」の箇所には、メール送信の分だけSenderを作成する方法が書かれてあります。また、各メール送信において view は送信メール・自動返信メールの2ファイルを作ることになります。htmlメールを送信したい場合はさらにtext形式のファイルを作成することになり、4ファイルが必要です。

この方法だとメール送信の数だけSenderとview(blade)4ファイルを作成することになりますが、下記のようなメール送信を行う場合、どのような管理になるでしょうか。

  • 新規登録メール
  • リマインダーのパスワードリセットメール
  • 受注受付メール
  • 商品発送メール
  • 退会完了メール
  • 問い合わせメール

上記の場合30ファイル作成することになります。

  • Sender:6ファイル
  • view:24ファイル

管理面からもいい構築方法とは思えません。

弊社では、Senderは共通1ファイル、view(blade)は各メール1ファイルで管理。結果、7ファイルで構築しています。

今回はこの管理方法を紹介します。

環境

  • Laravel9
  • php 8.2

Laravelファイル構成

基本的なファイル構成は下記のように配置します。

■ app

|-■ Http/Controller

  |- XxxController.php(メール送信実行)

|-■ Mail

  |- MailSend.php(Sender)

■ resorces/views

|- ■ emails

  |- mail-contact.blade.php(view)

  |- mail-order.blade.php(view)

  |- 以下略(view)

XxxController

コントローラーには、設定値と送信実行部分を記述します。

<?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

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(blade)

メール本文

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メールのデザイン

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);
});
pagetop
loading