はじめに
あるプロジェクトでファイル名が日本語のPDFをメールで送信する必要がありました。
公式や記事を見ながら実装したところ、何故か日本語部分だけが送信できないという事象が発生しました。
前提
Centos7系
PHP7系
LaravelのMailファサード・Mailableクラスを用いて実装しています。
HogeController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Mail\SampleMailable;
use Mail;
public function sendMail()
{
Mail::to('hogehoge@hogehoge')->send(new SampleMailable());
}
SampleMailable.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class SampleMailable extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.test')
->from('XXX@XXXX','Test')
->subject('テストメールです。')
->attach(storage_path('app/pdf/テストfile.pdf'));
}
}
事象
送られてきたメールを確認すると、添付されているファイル名が以下のようになっていました。
結果
file.pdf
期待値
テストfile.pdf
調査
以下の順序で調査を行いました。
- config.phpのlocaleがjaになっているか
- 参考記事のようにファイル名を参照する際にbasename()を使用しているかどうか
- サーバーのlocaleが正しいか
- php.iniの設定が正しいかどうか
調査結果
php.configの値
config.php
'locale' => 'ja',
basename()
今回、basenameは未使用。
laravelのソースも確認しましたが、使用されていませんでした。
サーバーのlocale
正しい値のようでした。
LANG=ja_JP.utf8
LC_CTYPE="ja_JP.utf8"
LC_NUMERIC="ja_JP.utf8"
LC_TIME="ja_JP.utf8"
LC_COLLATE="ja_JP.utf8"
LC_MONETARY="ja_JP.utf8"
LC_MESSAGES="ja_JP.utf8"
LC_PAPER="ja_JP.utf8"
LC_NAME="ja_JP.utf8"
LC_ADDRESS="ja_JP.utf8"
LC_TELEPHONE="ja_JP.utf8"
LC_MEASUREMENT="ja_JP.utf8"
LC_IDENTIFICATION="ja_JP.utf8"
LC_ALL=
php.iniの設定値
php.iniでlocale設定がされていなかったです。
原因
日本語を扱えるようにするにはphp.ini内で設定が必要ですが、デフォルト値のまま変更がされていませんでした。
対処法
効果がなかった対処法
こちらに記載されていたMailableのローカライズを参考にしましたが、期待通りに反映されませんでした。
HogeController.php
public function sendMail()
{
Mail::to('hogehoge@hogehoge')->locale('ja')->send(new SampleMailable());
}
今回の対処法
大人の事情でサーバー上にあるphp.iniを編集することは叶いませんでしたので、以下の内容で対応しました。
AppServiceProvoder.php
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
setlocale(LC_ALL, 'ja_JP.UTF-8');
}
}
これでLaravel上の処理は全て日本語対応されるはずです。
ちなみに、LC_ALLは他のLC関連の環境変数よりも優先される環境変数です。
別の対処法
php.iniの設定を変更したほうが良いと思います。
php.ini
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.encoding_translation = Off
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII
これでもうまくいくと思います。(未検証なので、ご存知の方がいらっしゃいましたら教えていただけると幸いです!)