PEAR::Mail_mimeで日本語ファイル名の添付ファイルを送る方法

世の中もう大体 UTF-8 で OK かなと思ったら、メールの添付ファイル名はそうでもないっぽいです。UTF-8 + URLエンコードで添付した日本語ファイル名が正しく読めないメール環境があったので、ISO-2022-JP + base64 にしたら大丈夫でした。


これをするのにPEAR::Mail_mimeだと、ややこしい引数を渡さなければいけないのでそれのメモ。以下のソースは UTF-8 で書かれていることを前提にしています。

<?php
require_once 'Mail.php'; // PEAR::Mail
require_once 'Mail/mime.php'; // PEAR::Mail_mime

$textbody = '日本語の本文。';
$filename = '日本語添付ファイル名.txt';
$filedata = '日本語添付ファイルの中身';

// 文字コードを ISO-2022-JP に変える
mb_convert_variables('ISO-2022-JP', 'UTF-8', $textbody, $filename);

// 各 mime パートの構築
$mime = new Mail_mime;
$mime->setParam('text_charset', 'ISO-2022-JP');
$mime->setParam('text_encoding', '8bit');
$mime->setTxtBody($textbody);
$mime->addAttachment($filedata // data
                     ,'application/octet-stream'  // content-type
                     ,$filename // attached file name
                     ,false // isfile
                     ,'base64' // encoding
                     ,'attachment' // disposition
                     ,'' // charset
                     ,'' // language
                     ,'' // location
                     ,'base64' // n_encoding
                     ,'base64' // f_encoding
                     ,'' // description
                     ,'ISO-2022-JP' // h_charset
    );

$subject = '日本語表題';
$jis = mb_convert_encoding($subject, 'ISO-2022-JP', 'UTF-8');
$encsubj = mb_encode_mimeheader($jis, 'ISO-2022-JP', 'B');

$recpts = 'example@example.jp';

$headers = array(
    'From' => 'webapp@example.jp';
    'To' => $recpts,
    'Subject' => $encsubj,
    );
$headers = $mime->headers($headers);
$body = $mime->get();

// メール送信には SMTP を直接使うのが好きw
$mail = Mail::factory('smtp', array('host' => 'localhost'));
$mail->send($recpts, $headers, $body);