Laravel 6 メールログの Quoted-printable エンコードされた件名と送信先をデコード
はじめに
Laravel にはメール送信する代わりにログファイルに残す機能があります。
しかし、ログファイル内の件名や送信元は Quoted-printable という方式でエンコードされており、一見してそれが正しいかを把握することはできません。
そこで今日は Laravel のメールログで Quoted-printable エンコードされた件名と送信元をデコードする方法を紹介します。今回使用したのは Laravel 6.18.3 です。
1. テスト用メール送信機能
まずは動作確認のためのメール送信機能を実装します。
/app/Http/Controllers/SampleController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mail;
class SampleController extends Controller
{
public function index()
{
Mail::send('sample.mailbody', [], function ($msg) {
$msg->to('user@example.com', 'サンプルプログラム')
->subject('テストメール送信');
});
}
}
/resources/views/sample/mailbody.blade.php
これはテストメールです1。
これはテストメールです2。
これはテストメールです3。
/routes/web.php
// ▼これを追加
Route::get('/sample', 'SampleController@index');
.env
MAIL_DRIVER=log # ← log を指定
ブラウザで /sample にアクセスすると /storage/logs/laravel.log に下記のように出力されます。
/storage/logs/laravel.log
[2020-04-05 12:34:56] local.DEBUG: Message-ID: <1234567890@example.com>
Date: Sun, 05 Apr 2020 12:34:56 +0000
Subject: =?utf-8?Q?=E3=83=86=E3=82=B9=E3=83=88=E3=83=A1?=
=?utf-8?Q?=E3=83=BC=E3=83=AB=E9=80=81=E4=BF=A1?=
From:
To: =?utf-8?Q?=E3=82=B5=E3=83=B3=E3=83=97=E3=83=AB?=
=?utf-8?Q?=E3=83=97=E3=83=AD=E3=82=B0=E3=83=A9=E3=83=A0?=
<user@example.com>
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
これはテストメールです1。
これはテストメールです2。
これはテストメールです3。
2. デコード機能
本題のデコード機能です。今回はフォームとして実装しました。
/app/Http/Controllers/SampleController.php
class SampleController extends Controller
{
// ▼ これを追加
public function decode(Request $request)
{
$decStr = '';
$rawStr = $request->input('raw_str') ?? '';
if ($rawStr) {
// 余分な文字列を除去
$encStr = preg_replace("/Subject:|To:|(\s)?=\?utf-8\?Q\?|\?=|\r|\n/", '', $rawStr);
// デコード
$decStr = quoted_printable_decode($encStr);
}
return view('sample.decode', compact('decStr', 'rawStr'));
}
...
}
- PHP: quoted_printable_decode - Manual
- https://www.php.net/manual/ja/function.quoted-printable-decode.php
/resources/views/sample/decode.blade.php
<form method="post">
<div>
<textarea name="raw_str" style="width:100%; max-width:640px; height: 150px">{{ $rawStr }}</textarea>
</div>
<div>
<button type="submit">Decode</button>
@csrf
</div>
</form>
@if ($decStr)
<div>{{ $decStr }}</div>
@endif
/routes/web.php
// ▼これを追加
Route::any('/sample/decode', 'SampleController@decode');
ブラウザで /sample/decode にアクセスし、laravel.log の Subject: ~ や To: ~ の部分をコピペして送信してみてください。その際「Subject:」や、送信元のメアド部分が含まれていてもOKです。
余談ですが、上記 routes/web.php では Route::any() を使ってますが、今回は get と post だけなので Route::match() の方が適切だったかなと思います。match() の使い方は、下記公式ドキュメントにあります。
- Basic Routing (Routing - Laravel)
- https://laravel.com/docs/6.x/routing#basic-routing
3. おわりに
最初は js で実装しようかと思ったのですが、ちょっと調べたら手段がいくつかみつかり、検討に時間がかかりそうだったので、今回はデコード機能が標準関数で提供されている PHP を使いました。
動的に変換したい場合は上記サンプルコードをちょっと改造して Ajax でやればいいかなぁと思っています。