忍者ブログ

Outlook の.msgを読み込む

とりあえずの成果物をhttp://higambana.ashigaru.jp/にアップしておいてみた。
まともに使用するにはまだ不足なのだがそれには訳がある。

その前にまずわかったこと、わかっていることについてまとめておく。
まず、.msgはほかのMS Officeのファイル形式と同様にStructured Storage((DocFileとかCOM stuctured storage OLE2 compound documentsとか構造化ストレージ呼ばれていたりします)という形式になっている。構造化ストレージのバイナリ構造は
http://sc.openoffice.org/compdocfileformat.pdf
が参考になる。
また、構造化ストレージは当然MSに多くの情報があるし、Windows上ではIStorageというものでサポートされている。
またOutlookの.msgに関しては
http://www.wotsit.org
に情報が存在する(完璧ではないが)。CPANにも
http://search.cpan.org/src/MVZ/Email-Outlook-Message-0.903/lib/Email/Outlook/Message.pm
というモジュールが存在した(ついさっき知った)。

これらのほかにわかったことといえば時刻の位置ぐらいのもので私はなんら活躍していないともいえる。


さて、Outlook ExpressとOutlookの間でインポートエクスポートしてどういうものが出てくるかというものを一番の参考にしていたのだが、そのとき、Outlookでインポートを選択した場合と、Outlook Expressでエクスポートを選択した場合とで出来上がる.msgは異なることがわかった。Outlookでインポートを選択した場合のほうがより詳細なファイルになるようだ。

大方の構造についてはwotsit.orgとcpanのモジュールを読めばわかりそうだが、問題になったのは日付だ。
日付は__substg1ではなく__properties_version1.0に格納されているようで、ここにはもっと多様な情報がありそうなのだ。
ちなみに日付は"40 00 39 00 06 00 00 00"の直後の8octetに入っている。リトルエンディアンなのでバイトオーダーを逆転させて読むこと。ちなみにFILETIME形式である。FILETIMEとUNIX timeの変換はMSのkb/167296 に存在する。今はD Langで作成しているのでd_timeに変換するが、その方法はFILETIMEからd_timeへの変換に載せてある。

Outlook側でインポートしたデータでは"03 00 DE 3F 06 00 00 00"の後にあるデータが元のエンコードのコードページを示しているのではないかとにらんでいるがこれは憶測である。
憶測ついでだが、この__properties_version1.0エントリー以下のデータは16オクテットセットで、始めの8オクテットがデータの識別子で、その後8オクテットがデータ本体ではないか考えている。サンプルが少なすぎてわからない部分が多すぎるので推測でのみ語っている。

__substg1.0_10090102 には見たところメールの本文が圧縮されて入っているようだが、ここにはコードページらしきものも書かれている。ここがデコードできればいいのかもしれないがここまでは……。

ともあれ、この程度で大方のデータは取得できる。ヘッダで重要なのはやはりFromやTo、Cc、Subject、Date等の項目で(Reply-toなんかも必要だろうがFromほど重要ではない。もっともとるのは簡単である)、ReceivedとかのSMTPリレーはデータ本体ほど重要ではないだろう(スパム判定なんかでは重要だが)。もっとも重要な本文と添付ファイルが取り出せるようになっていればそうそう困らないのではないだろうか。


蛇足だがThunderbirdではOutlookからインポートすると時刻がDOS Timeにでもしているのかずれていたり、メールアドレスがぶった切れたりすることが多々あった。あまりお勧めできるとはいいがたかった。ちなみにバージョンは2.0.0.9であった。

----2008/03/16 追記
SenderとReply-Toヘッダフィールドについて
Senderは0C1Aに表示名、0C1Fにアドレスが入る。Fromと同等の扱いでよさそう。
一方Reply-Toだが、なぜか表示名は0050にあるのだがアドレスがない。
ただし、004Fに表示名、プロトコル、アドレスが含まれているようなのでとりあえずこれを使う。
01 00 00 00 6C 00 00 00  68 00 00 00 00 00 00 00
81 2B 1F A4 BE A3 10 19  9D 6E 00 DD 01 0F 54 02
00 00 01 80
という羅列の後に表示名、プロトコル、アドレスの順にNull文字区切りで格納されているようだ。でもたぶん頭のほうは変わるかな。特に6Cと68は絶対変わると思う。試せっていう話ですが。
ちなみにFromとSenderも似たような部分があってそれぞれ0041、0C19にある。
こちらは
00 00 00 00 81 2B 1F A4  BE A3 10 19 9D 6E 00 DD
01 0F 54 02 00 00 01 80
こうなっていた。たぶんこのあたりは全く変わるんじゃないかと思うけども、00 00 00 00 以降が一致しているので、まあそんなもんなんだろうと思うことにする。とりあえず、実装としては00 00 00 00を検出するまでスルーして、さらにその後20オクテットぶっ飛ばすようにしてみた。
ちなみにここは0102という型からもわかるように文字列型ではない。どうやらUTF-16固定のような気がするのでそのようにしてしまう。

実装は汚いし、本当に解決できているか怪しいがこれで大体ほしいヘッダは集まったかな(日付はローカルタイムにしていいみたいだし)。
後はエンコードをどうするかが難関。圧縮されているっぽい、10090102の頭の方にコードページっぽいところがあるのでこいつを使わせてもらうことにしてもいいかも。でもShift_JIS(というかCP932)だったらiso-2022-jpとするとかいう対応はどうすればいいんだろ?
いっそすべてUTF-8でやってしまうのも楽でいいんだが。

現在のところは以上。

PR

2008/03/02 Programming Comment(0)

COMMENT

COMMENT FORM

NAME
MAIL
WEB
TITLE
COMMENT
PASSWORD

カテゴリー
 
 
 
最新記事
 
(03/28)
(05/31)
(03/21)
(03/19)
(12/26)
 
 
ブログ内検索
 
 
 
カレンダー
 
05 2020/06 07
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 
 
アーカイブ
 
 
 
最新TB
 
 
 
最新CM
 
 
 
リンク
 
 
 
Feed
 
 
 
注意点
 

英字のみのコメントは拒否しています。スパムの排除のためご理解をお願いいたします。(でも結構スルーされてしまいます。たまに掃除していますがご容赦のほどを。)

 
 
カウンター
 
 
 
アクセス解析