目次


洗練されたPerl:PerlでIMAPを使う

Mail::IMAPClient CPANモジュールで構築されたIMAPクライアント

Comments

IMAP(Internet Message Access Protocol)と一般的なPOP3(the Post Office Protocol)は、どちらもe-mailにアクセスを許可するプロトコルとして幅広く実装されています。POPは非常によく使われていますが、多くの場合IMAPの方がメールを扱う上ではより良い選択です。例えば、POP3の一つしかないメールボックスモデルでは、一箇所に何千通もの大量のメッセージを受信するので、アクセスと管理は退屈な仕事のようになります。しかしIMAPでは、メールボックスは多種に分類されており、サーバー上にメッセージを残すように設計されています。また、POP3では毎回新たに接続しなおさなければなりませんが、IMAPでは確立されたIMAP接続を通して、新着メールをチェックできます(両者の技術的な詳細へのリンクについては、本記事の参考文献をご覧ください。"Scaling and Operational Considerations"には、POP3 RFCの接続に関する特殊な情報があります )。

本稿で、私はIMAPに焦点を当て、e-mailを管理するためのifrom ユーティリティをお教えしましょう(ifrom .plをダウンロードするには、参考文献をご覧下さい)。私は個人的にifromをIMAPサーバのメッセージの一覧表示、出力、移動に使っています。また私はバックアップをとらないと恐怖さえ感じる性質なので、自分のIMAPメールのバックアップを取るために、夜毎ifromを作動させています。(あなたもまだ病的にバックアップをとっていないというだけで、今後もそのままであるとは限らないことを覚えておいてください。)

メッセージのリスト

ifromの最も簡単な呼び出しには、なんのオプションも要りません。IMAサーバー上の受信箱にアクセスすれば、番号表示されたメッセージが表示されます。-hostオプションは、ifromにどのIMAPサーバに接続すべきかを知らせます。

他のすばらしい機能の中で、ifromは設定されたデフォルト値でAppConfigモジュールを使用することにご注意ください。

ifromの認証は、通常のLOGIN(IMAPサーバに、あなたのパスワードとユーザーネームがプレーン・テキストで宣言されていることを意味します)でなされます。Mail::IMAPClientパッケージのAuthmechanism capabilityへのリンクは、本稿の参考文献に示してあります。IMAPClientでのメールで他の方法がサポートされていない時には、-crammd5 スイッチによってCRAM-MD5 認証を使うことが出来ます。ですから一般的な-authentication スイッチをわざとセットアップしませんでした。自分の認証を実装出来る事に注意して下さい。(IMAPClientドキュメンテーションを参照)

リスト1:IMAPサーバの認証
if ($config->CRAMMD5())
{
 my $authmech = "CRAM-MD5";
 if ($imap->has_capability($authmech))
 {
  print "Switching to $authmech authentication\n";
  $imap->Authmechanism($authmech);
 }
}

-user-passwordスイッチを使うか、またはauthinfo(AKA netrc)ファイルを通して、コマンドラインから自分の名前とパスワードを指定します。authinfoファイルは、次のように認証オプションの一部として格納します。

リスト2:ifrom用Authinfo ファイルフォーマット
machine imap.yourserver.here login joe password JoeSecret
machine imap.yourserver.there password FredSecret port 244

authinfoファイルは他のプログラムで使用されていますので、フォーマットはそれらのプログラム次第で可変となります。ifromはマシンを探して、ログイン名、パスワード、ポート番号などのキーワードを解析します。いずれのキーワードも宣言されていない時には、デフォルトが使われます。authinfoファイルは、-userおよび-passwordコマンドライン・スイッチを無視します。自分のauthinfoファイルが自分だけ読み込み可能であることを確認してください。

マシン名はあなたのIMAPサーバ名です。authinfoファイルのマシン名は-hostスイッチでifromに与えられた名前と正確に一致しなければなりません。

ifromがサーバーに接続したら、Peekを可変で1にセットし、未読メールを調べます。

次にifromは、-mailboxスイッチによって指定されたメールボックスを開きます。これはデフォルトでは、標準的なIMAPメインのメールボックスである、受信箱(INBOX)に設定されています。

この後、ifromはフォーマットを使って、メッセージを表示します。

リスト3:メッセージヘッダーの表示
printf "%5d %-35.35s %s\n", $count, $address,
   ((defined $data->{Subject}->[0]) ? $data->{Subject}->[0] : '');

必要ならば何時でも、簡単な正規表現を使って、$adressの送信人のアドレスをユーザのフルネームから取り出せます。

もしifrom_dumpスイッチを与えるなら、メッセージのヘッダーに続いて、内容も表示できます。これはメーラーを立ち上げて、メッセージの中身をチェックする時間も取れないようなときには非常に便利です。ifromが容量の大きなメッセージを表示している時に中断しても大丈夫です。Peekオプションで1にセットしてサーバを開いたので、メッセージは削除されないか、影響されないでしょう。

注 _dumpスイッチはbody_string()関数を使用します。後ほど見てゆきますが、-backupオプションではmessage_string()関数を使用することに注意してください。

メッセージの移動

時として、あるメールボックスから、別のメールボックスへ移動させたいことがあるでしょう。多量のメッセージがあり、それらを移動中、あなたのメールクライアントがIMAPサーバへの接続が維持できない場合(遅いネットワークリンクでは、しばしば起きることですが)などに役立ちます。

-mailbox-toオプションを使うだけです。とても簡単です。ifromをこのように動作させます。

リスト4:ifromでメッセージを移動させる
ifrom -mailbox newmail -to archive

またifrom-nスイッチを使って、ある数以降のメッセージの移動を止めさせることもできます。

ここに、移動を行う際の実際のコードがあります。IMAPは移動に組み込みの規約を持っていますから、クライアントは単純にmove()関数を呼び出すだけです。

リスト5:Perlで、どのようにしてメッセージが移動されるのか
 foreach my $message (@msg_list)
 {
  $count++;
  if ($config->TO)
  {
   die "Could not move message $message: $!" unless $imap->move($config->TO, $message);
   print "Moved message $message to " . $config->TO, "\n";
   $imap->expunge() if $config->EXPUNGE_OFTEN;
   last if $count >= $config->N;
  }
 }
 if ($config->TO)
 {
  $imap->expunge();
 }

IMAP上でのメッセージの移動は、Peekのセッティングを考慮しません。1にセットしても、Peekはメッセージを見るのに適切なだけです。Mail::IMAPClientによってインプリメントされるように、メッセージを移動させると、目的のメールボックスにコピーが置かれた後、オリジナルのメッセージは削除されるようになります。

メッセージボックスの消去と削除

前述したように、メッセージを移動させると、あなたは不思議なexpunge()関数に気づくに違いありません。expunge()関数は、IMAPサーバに削除すべくマークされたメッセージを全て削除し、メイルボックスを空にするように伝えます。私たちはPeekを1にセットしているので、通常、メッセージのリストが作成された時、削除されるものとしてそれらに注意を払いません。しかし上述したように、それらのメッセージを本当に削除するかどうかに関わらず、move()関数は、削除するものとして区分します。実際に削除するには、expunge()関数を呼び出して使います。

もしIMAPが実際にメッセージを移動させれば、これは必要ありません。しかし実際にはしませんので、Mail::IMAPClientが、削除によって後続のcopy()関数として、move()関数をインプリメントします。

これは何故有用なのでしょうか?間違って全てのメールを削除してしまった時、このIMAPの機能は、あなたが削除する直前のメッセージを復活させることを可能にします。

-echange_oftenフラグは、あなたが信頼性の低いネット上のリンクにいて、いつでも接続を切ることができる時、メッセージを移動させるためにあります。expunge()関数が呼び出され、全てのメッセージが後で移動されることを保証します(そうでない時は、メッセージはメールボックスに残ります)。しかし、もっと簡単にexpunge()関数を使うには、メッセージを全て移動させた後で-nフラグと組み合わせて使用します。expunge()はそのようにあなたが指定した多量のメッセージが移動した後で、あるいは10件もしくは15件移動後毎に呼び出されます。

また私はifrom-delete_mailbox_reallyオプションをつけました。そのオプションでは、ifrom-mailboxスイッチによって、指定されるどんなメールボックスであれ削除しようとするでしょう。ですからデフォルトのINBOXメールボックスでは、決して使用しないでください。このPerlコードは簡素にはなりえませんでした。

リスト6:メールボックスの削除
if ($config->DELETE_MAILBOX_REALLY)
{
 $imap->delete($config->MAILBOX)
  or warn "Could not delete mailbox " . $config->MAILBOX . "\n";
}

IMAPメールのバックアップ

私はバックアップをとることが好きです。バックアップを取っていたおかげで、私は本当に何回も何回も、仕事上で助けられました。e-mailと言えば、バックアップを取ることは、それほど重要でないように見えるかもしれませんが、実際には日常のやり取りの多くはe-mailで行われます。しばしば、非常に時間がたってから、金曜日に着ていたショートパンツに関するメモを削除すべきではなかったことに気付いたり、今から月一回の全社規模の会議が始まることを思い出させてくれたりします。

ifromを使って、メールのバックアップを取るためには、ifrom-backupフラグを立ててください。保存されたメッセージをどこに置くかで、-savedirスイッチも重要になります。認証、ホスト、ポート番号等の全ての要素が、規則的なifromのように動作します。ifromが全てのメールボックスをバックアップするので、-mailboxパラメータは作動しません。私は"全てのメールボックス"を無視するために、特別な-backup_mailboxフラグを持てたかもしれません。しかし正直なところ、私はそれを必要としたことはありません。

IMAPメールボックス上のメッセージは、一意の番号を持っています。savedir/mailbox/messageNumaberファイルへ各メッセージを保存する時に利用します。すでにファイルが存在する時には、メッセージをスキップします。

リスト7:メッセージをバックアップする
  foreach my $message (@msg_list)
  {
   my $filename = "$dir/$f/$message";
   next if -e $filename;
   print "saving message $f/$message to $filename\n" if $config->VERBOSE;
   my $data_fh = new IO::File $filename, "w";
   my $data = $imap->message_string($message);
   warn "Empty message data for $f/$message" unless defined $data && length $data;
   $data_fh->print($data);
  }

message_string()関数を使用して、メッセージ全体を検索します。body_string()関数では、メッセージのヘッダー(e-mailを手早く見ている時には、通常面白くありません)をより早くスキップする-dumpスイッチを使います。

まとめ

ifromユーティリティは小さなスクリプトの一つで、Perlスクリプトは、これからも有用な特色を増やし続けていくでしょう。他の人たちが独自のifromスクリプトを作成したとしても、驚く様な事ではありません。マシンルームでシステムのメンテナンスを行っていてIMAPメールのチェックが出来ない時や、回線速度が遅い時には、ifromの基本となるメッセージのリストアップという機能は、信じられないほど役に立ってくれました。

たまたま重要なメールを削除してしまった時、ifromで修復したことも何回かあります。例え私のIMAPサーバーを置くISPがメールボックスを消失しても(私は過去にも同じ経験をしたことがあります)、貴重なメールのために一日を費やすだけですむと分かっているので、安心です。

本稿が、IMAPのインターフェイスのためにPerlを書いている人にとって興味深いものであり、またifromがお役に立つことを願っています。ifromをお使いになるのなら、あなたの使い方を教えて下されば幸いです。


ダウンロード可能なリソース


関連トピック

  • Tedの「洗練されたPerl」シリーズの他の記事はこちらからお読みになれます。
  • ifromのスクリプトは、ifrom.plからダウンロードできます。
  • Mail::IMAPClientのマニュアルページは、Authmechanism apabilltyを含み、パッケージ製品の基本リソースとして使用できます。
  • Net::IMAPは、Mail::IMAPClientの代わりに使用できますが、1999年以来更新されていません。Mail::IMAPClientの開発の方がより活発に見えます。Mail::IMAPClientは完璧に私の必要性に応じてくれたので、私はNet::IMAPを使用しませんでした。
  • IMAP4rev1 RFC2060(IMAPプロトコルの現在のバージョンが定義されたドキュメント)を読むことをお勧めします。
  • 同じくPOP3 RFC1939(現在のPOP3のバージョンが定義されたドキュメント)もお読みください。
  • CPANモジュールアーカイブには、望みうる限りのPerlモジュールが入っています。
  • さらに多くのPerlに関する情報や、関連するリソースについてお知りになりたい方は、Perl.comをお訪ねください。
  • IMAPや他のプロトコルをサポートしているJavaをベースにしたメールサーバ用に、"Jamesの使用 第1回 :ApacheのJamesエンタープライズ・電子メール・サーバーの紹介" (developerWorks, 2003年6月)をお読みください。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=226663
ArticleTitle=洗練されたPerl:PerlでIMAPを使う
publish-date=06192003