Perl: 2010年5月アーカイブ

POP3 でメールを受信し、添付で送られてきた画像データを抜き出すスクリプトを Perl で書いた。

最初は受信してきたメールを MIME::Parser で解析して添付ファイルを抽出しようと思ってたんだけど、日本語ファイル名が含まれていた時に何か問題あるという話を見つけたので、十年くらい前に自作した Parser を使うことにした。

ちゃんと RFC 見て書いたコードじゃないけど、何年か業務システムで使っていた間に、「OutlookExpress のメールは、Quoted-Printable エンコードなのかよ!」とか、「EdMax の boundary 文字列には、エスケープしないといけない特殊記号がバンバン混ざってるのね」とか、そんなメールソフト毎の微妙なフォーマットの違いや、添付ファイルが多段に展開する HTML メールとか、色々なことに実践的に対応してきたので、大概のメールは問題なく処理出来るようになってるからな・・・と思ってたんだけど・・・

iPhone のメールはまた独特じゃねえ(^^;
結局今回は iPhone 対応が必要じゃった。

iPhone メールで送られてきたメールが他のメールソフトのものと違うところ。

まず一つめ。添付ファイルのヘッダの順番が全然違う。
ほとんどのメールソフトが添付ファイルのスタートを表す boundary 文字列のあと、Content-Type ヘッダが来るんだけど、iPhone(つーか、Apple 製のメールソフトは皆そうなん?)の場合は Content-Disposition ヘッダが来るんだな。

次に、Content-Disposition ヘッダの filename の記述が独特じゃねえ。
普通は(日本語ファイル名なら)
filename="=?ISO-2022-JP?B?GyRCJF4kJCReJCQbKEIxLmpwZw==?="
という形なんだけど、iPhone メールは
filename*=iso-2022-jp''%1B%24B%3CL%3F%3F%1B%28B.jpg
てな形で来るな。
MIME B エンコードじゃなく、URL エンコードしたファイル名が来るんだな。
filename と = の間に * があるのも謎だし。

いや、どっちも致命的な問題じゃなくて、添付ファイルの抜き出しそのものには影響ないんだけど、Content-Type ヘッダをヘッダ情報をログに吐き出す開始トリガーにしてたり、オリジナルのファイル名がセットされているかどうかを正常にヘッダ情報が抜き出せたかの判断材料にしてたりしたので(filename の後ろに * が付いている形は想定してなかったので、オリジナルのファイル名が抜けなかったのだ)、ちょっと変な動きをしてしまった。

まあ、生のメールデータを見れば問題点はすぐわかるので、ささっと対応したが。

こんなこと書くと、「RFC ちゃんと読んでコード書けば問題ないじゃろ」と知ったかぶりに指摘する人がいるんだが、例えば日本のケータイのメールアドレスなんて(天下の NTT DoCoMo からして)RFC なんか無視してるし、実際のデータを解析して対応しないとどうしようもない部分があるんだぜ。

まあ、興味がある人は、色々なメールソフトから送った生のメールデータを見てみると色々楽しいよ。
全てのソフトのデータを問題なく抽出するにはどんな正規表現を書けばいいかとか、パズルみたいで楽しいよお。(笑)

現在、Perl で作ったシステムをお客さんのサーバに移行中だが、MIME-tools の関係がインストールされていないので、

Can't locate MIME/Words.pm in @INC ~

なエラーが発生。

ということで、CPAN モジュールを使って MIME::Words モジュールのインストールを行ったのだが、結局、関連する以下のモジュールのインストールまたはアップデートが発生した。

    IO::Stringy
    Mail::Header
    ExtUtils::MakeMaker
    Mail::Field
    File::Temp
    Mail::Internet
    Date::Format
    Test::Pod
    Date::Parse
    Module::Build
    Pod::Simple
    ExtUtils::CBuilder
    Test::Harness
    ExtUtils::ParseXS
    Pod::Escapes

CPAN モジュール使ったインストールだと、なんだかんだと make test で失敗して手動インストールしないといけないケースも多々発生するので気分が重かったのだが、どれ一つ失敗することなく無事インストール終了。

う~む。これは朝から気分爽快。

無事当該 Perl スクリプトも動くようになって、今日は朝から気持ち良いのであります。ぶひっ。

う~む。(何か、最近この唸り声で始まるパターンが多いな(^^;)

日頃 Perl で正規表現使ってると、ActionScriptで正規表現使うのが面倒くせぇ、面倒くせぇ。(^^;

例えば、日付がセットされている文字列('Fri, 16 May 2010 02:45:00 +0900')から年月日を抜き出したい時、

Perl なら、変数 dateData に日付がセットされていれば、

    if ($dateData =~ /^.+?(\d+)\s(.+?)\s(\d{4})/) {
        $y4 = $3;
        $m2 = $2;
        $d2 = $1;
    }

じゃん(冗長に書いても)。これが ActionScript になると、

    var pattern:RegExp = /^.+?(\d+)\s(.+?)\s(\d{4})/;
    var result:Object = pattern.exec(dateData);
    if (result != null) {
        y4 = result[3];
        m2 = result[2];
        d2 = result[1];
    }

とか。
まあ、オブジェクト指向言語なので仕方ないのだが(^^;、RegExp オブジェクトを使って云々というのが面倒臭いというか、if 文一発で済んじゃう Perl からすると、どうにも冗長な印象が否めない。

あと、null 値を文字変数に突っこむ時には空文字に型キャストしてくれれば良いのに。

マッチングせずに結果に null 値が返ってきた時、そのまま y4 = result[3] しようとしたら、

Cannot access a property or method of a null object reference.

って怒られちまったい。(^^;

まあ、ちゃんと結果を if (result != null) って確認してからセットすれば全然問題ないんだけど(^^;

いやあ、文字、数値の型の区別も無く、正規表現と親和性の高い言語仕様の Perl を使い続けてると、ほんまに別の言語を使うのが面倒くさくなるな。

確かに Perl は自由度が高くて、それ故に「教育しづらい言語」あるいは「社内のコーディング基準を作りづらい言語」なのは事実だと思うが、もう少し「業務システムの構築にも使える言語」として浸透してもよかったのになあと思う。
なんか、VisualBasic と Java しか知らん人間が「Perl はどうやらこうたら」という誤解に満ちた評価を口にしているのを見ると、ムッとする今日この頃である。:-P

このアーカイブについて

このページには、2010年5月以降に書かれたブログ記事のうちPerlカテゴリに属しているものが含まれています。

前のアーカイブはPerl: 2010年2月です。

次のアーカイブはPerl: 2010年7月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら