Edited at

Encode::decode('MIME-Header', $value) の挙動について

More than 3 years have passed since last update.

メールのヘッダのデコードに Encode::decode('MIME-Header', $value) を使っていたのだが、うまくいかないケースがでてきた。

use strict;

use warnings;
use feature 'say';
use Encode qw/encode_utf8 decode/;

# 実際のデータ
my $subject = "=?utf-8?B?44Ku44Ks44K344ON44OeIHdpdGggVS1ORVhUIOOBiueUs+OB?=
=?utf-8?B?l+i+vOOBv+WujOS6huOBruOBiuefpeOCieOBmw==?=
";

my $decoded = decode('MIME-Header', $subject);

say encode_utf8 $decoded;


出力結果

ギガシネマ with U-NEXT お申\xE3\x81\x97込み完了のお知らせ


この subject は2行に分かれているが、どうやら「し」という文字がちょうど2行に分断されてしまっていて、別々にデコードされた結果を文字列結合したためこのようになっているっぽい。実際 \xE3\x81\x97 は「し」に相当する。

print "\xE3\x81\x97"; # し

一方で、MIME::Wordsdecode_mimewords($value) を使うときちんとデコードできるっぽい。

use strict;

use warnings;
use feature 'say';
use MIME::Words qw/decode_mimewords/;
use Encode qw/encode_utf8 decode/;

# 実際のデータ
my $subject = "=?utf-8?B?44Ku44Ks44K344ON44OeIHdpdGggVS1ORVhUIOOBiueUs+OB?=
=?utf-8?B?l+i+vOOBv+WujOS6huOBruOBiuefpeOCieOBmw==?=
";

my $decoded = decode_mimewords($subject);

say $decoded; # なぜか encode_utf8 は不要


出力結果

ギガシネマ with U-NEXT お申し込み完了のお知らせ


おそらく内部的に、utf8 でデコードする前に結合するか、後にするかの違いだとは思う。

MIME::Words::decode_mimewords よりも Encode::decode('MIME-Header', $value) が使いやすいし、精度も高いと思うのでこっちでなんとかしたいところだが・・・。MIME::Words::decode_mimewords は不親切だし・・・。

どなたか、Encode::decode('MIME-Header', $value) を使った解決策があればご教示いただきたいです・・・。