PEAR::Mail_mimeDecodeで日本語のメール添付ファイル名取得

メールに添付して日本語が入った名称のファイル送って「PEAR::Mail_mimeDecode」で取得しようとしたら文字化けしてた。。。
正確にはデコードしきれてなかったというか。。。
PEAR::Mail_mimeDecode」が原因というわけでもなかったというか。。。


テストした環境では

$decoder = new Mail_mimeDecode($mail);
$decoded = $decoder->decode($params);
$fileName = $decoded->parts[$idx]->ctype_parameters['name'];

ってやって取ってきた「$fileName」が暗号状態。
その後に

$fileName = mb_convert_encoding($fileName, 'UTF-8', 'ISO-2022-JP');

とかやっても全く意味無し。
けど化けてる文字の中に見覚えあるような文字列も混じってるようなー
って事で一度URLデコードしてから文字コードエンコードしてやることに。

$fileName = urldecode($fileName);
$fileName = mb_convert_encoding($fileName, 'UTF-8', 'ISO-2022-JP');

ってやったらうまくいった。


あと

  • 「ctype_secondary」からじゃ欲しい拡張子が取れない
  • ファイル名はメールタイトルから取得して2つ目以降は連番付ける
  • メールタイトルが未設定の場合に添付ファイルのオリジナル名称使う

とかってやろうとしたら最終的には以下のような感じに。

// デコード処理
$decoder = new Mail_mimeDecode($mail);
$decoded = $decoder->decode($params);

// ヘッダ部分データ取得
$headers = $decoded->headers;
$headFrom = mb_convert_encoding($headers['from'], 'UTF-8', 'ISO-2022-JP');
preg_match('/[0-9a-zA-Z_\.\-]+@[0-9a-zA-Z_\.\-]+/', $headFrom, $matchs);
$from = $matchs[0];
$to = mb_convert_encoding($headers['to'], 'UTF-8', 'ISO-2022-JP');
$subject = mb_convert_encoding($headers['subject'], 'UTF-8', 'ISO-2022-JP');

$file = null;
$fileType = null;
$fileName = null;
if (!empty($decoded->parts)) {
    // bodyを取得
    $body = $decoded->parts[0]->body;
    $body = mb_convert_encoding($body, 'UTF-8', 'ISO-2022-JP');

    $index = 1;
    for ($idx = 1; $idx < count($decoded->parts); $idx++) {
        $file = $decoded->parts[$idx]->body;
        //$fileType = $decoded->parts[$idx]->ctype_secondary; ← 今回は使えないから別方法で拡張子「$ext」を取得。

        $name = '';
        $ext = '';
        $indexed = false;

        $fileName = isset($decoded->parts[$idx]->ctype_parameters['name'])
            ? $decoded->parts[$idx]->ctype_parameters['name']
            : $decoded->parts[$idx]->ctype_parameters['name*']; // ← ファイル名が日本語の場合は「name*」の方に入ってた。

        $tmpArray = explode('\'\'', $fileName, 2); // ← 「''」の左側に文字コード入ってたけど今回は以下にベタ書きで。
        if (count($tmpArray) > 1) {
            $fileName = array_pop($tmpArray);
            $fileName = urldecode($fileName);
            $fileName = mb_convert_encoding($fileName, 'UTF-8', 'ISO-2022-JP');
        }

        $tmpArray = explode('.', $fileName, 2);
        if (count($tmpArray) > 1) {
            $ext = '.'.array_pop($tmpArray);
        }

        //$name = array_pop($tmpArray); ← これも化けてるファイル名なんで今回は使えない。
        if ($subject == '') {
            $name = preg_replace('/[.].+/', '', $fileName);
        } else {
            $name = $subject;
            if ($index == 1) {
                $name = $subject;
            } else {
                $name = "{$subject}({$index})";
            }
            $indexed = true;
        }

        /********************/
        /* ここに実処理記述 */
        /********************/

        if ($indexed) {
            $index++;
        }
    }
} else {
    // 添付ファイルが無い場合
    $body = $decoded->body;

    /********************/
    /* ここに実処理記述 */
    /********************/
}


個人的な要件たくさん組んでるけどまあ流れは。