end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転しました

Becky! ver.2.52からのメールはMIME::Parser->parse_data()で失敗

thunderbirdのメールはMIME::Parser->parse_data()できるのにBecky! ver.2.52はできないので調べてみたら、MIME::Parser がcontent headerのparseに失敗しているようでした。

thunderbirdBecky! ver.2.52のcontent header

まず、thunderbirdBecky! ver.2.52のそれぞれのcontent headerは次の通りです。

thunderbirdのcontent header

Content-Type: application/vnd.ms-excel;
 name="=?ISO-2022-JP?B?My0xLTEzXxskQkdeQk4+cEpzRn5OT01RJVUlKSE8JV4lQyVIGyhCKHRvcA==?=
 =?ISO-2022-JP?B?aWNzKS54bHM=?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename*0*=ISO-2022-JP''%33%2D%31%2D%31%33%5F%1B%24%42%47%5E%42%4E%3E%70;
 filename*1*=%4A%73%46%7E%4E%4F%4D%51%25%55%25%29%21%3C%25%5E%25%43%25%48;
 filename*2*=%1B%28%42%28%74%6F%70%69%63%73%29%2E%78%6C%73

Becky! ver.2.52のcontent header

Content-Type: application/octet-stream;
 name="=?ISO-2022-JP?B?GyRCR15CTj5wSnNGfk5PTVElVSUpITwlXhsoQg==?=
 =?ISO-2022-JP?B?GyRCJUMlSBsoQigbJEIlIiVRITwlSCU7JV8bKEI=?=
 =?ISO-2022-JP?B?GyRCJUohPBsoQikueGxz?="
Content-Disposition: attachment;
 filename="=?ISO-2022-JP?B?GyRCR15CTj5wSnNGfk5PTVElVSUpITwlXhsoQg==?=
 =?ISO-2022-JP?B?GyRCJUMlSBsoQigbJEIlIiVRITwlSCU7JV8bKEI=?=
 =?ISO-2022-JP?B?GyRCJUohPBsoQikueGxz?="
Content-Transfer-Encoding: base64

エラー内容

先程のcontent headerを含んだメールを次のようなscriptでparse_data()しようとすると、MIME::Parser::Filer が勝手に無視して、例外もcatch出来ませんでした。

sub parse_mail {
    my ($self,$msg_src) = @_;

    my $parser = MIME::Parser->new();                   #MIME::Parserの準備
    $parser->output_dir($CONF->{pop}->{tmp_dir});       #mailの一次保存場所

    my $entity = $parser->parse_data($msg_src);
    unless ($entity){
        my $msg = join("\n",
                       "mailの読込みに失敗しました.",
                       "$msg_src");
        $self->error($msg);
        die $msg;
    }
}

error msg

ignoring text in character set `ISO-2022-JP'
 at /usr/local/lib/perl5/site_perl/5.10.0/MIME/Parser/Filer.pm line 659

とりあえずの対応策

そこで、MIME::WordDecoder でwarningを出すものの文字列はそのまま返すようにしました。

sub unknown_mime_encoding {
    my ($self,@tmp) = @_;
    $self->warn("unknown_mime_encoding: $tmp[0]");
    return $tmp[0];
}


#multi partなmailをparseし、添付されているxlsのpathを返します
sub parse_mail {
    my ($self,$msg_src) = @_;

    my $mime_wd =
        MIME::WordDecoder->new(['ISO-2022-JP' =>"KEEP",
                                '*'=>sub{$self->unknown_mime_encoding(@_)}]);
    MIME::WordDecoder->default($mime_wd);

    my $parser = MIME::Parser->new();                   #MIME::Parserの準備
    $parser->output_dir($CONF->{pop}->{tmp_dir});       #mailの一次保存場所

    my $entity = $parser->parse_data($msg_src);
    unless ($entity){
        my $msg = join("\n",
                       "mailの読込みに失敗しました.",
                       "$msg_src");
        $self->error($msg);
        die $msg;
    }
}

とりあえず動作しているので、しばらく様子を見ます。