このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

mboxを切り出したいのです

発言者:だいとう
( Date Wednesday, September 01, 2004 09:41:37 )


今回メールサーバーの移行がありまして、
サーバー上にあるユーザーのメールデータを次のサーバに移す必要が出てきました。
以前の発言にもありましたが、mboxerでダウンロードしたものからは
リソースの区切り情報に従ってファイルに分けられました。
これをUVJで新しいサーバに送信しようと考えています。
これをTanakasOSAXを使って生のmboxファイルから行いたいのですが、
リソースに書かれている8桁の区切りを表す数字の意味がわからないのです。
おそらくFromをキーにして先頭からの文字数と思うのですが、
mboxerでのconvert to filesの動きをもう少し詳しく教えていただけませんか?

→  mboxerの動作

田中求之 さんからのコメント
( Wednesday, September 01, 2004 11:03:38 )

mList リソースに並んでいるのは、そのファイルに収められているそれぞれの
メールの先頭の位置のバイトオフセットです。ただし、最後の行には、その
ファイルのサイズ(=最終の文字の次のオフセットになる)が書かれています。

たとえば、ある mbox のファイルの mList リソースが次のようになっていた
とします。この場合、メールは2通入っていることになります。

一通目のメールを読みだすには、ファイルのオフセット 00000000 から
2行目のオフセット 00043228 の手前のオフセットが指している部分まで
読み込めばいいことになります。

00000000
00043228
00089412

このように、N通目のメールを読みだすには、mList のN行目のオフセットから
(N+1)行目のオフセットの手前までを読み出すという処理になります。

Tanaka's osax 2.0 のスクリプトでは次のようになります。

-- tgFile が mboxer のファイルだとする

-- リソースを読み込む
set mList to MT Read Resource tgFile of type "TEXT" ID 1000

-- 読み込んだリソースをリスト形式に変換
set oldDel to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set mList to text items of mList
set AppleScript's text item delimiters to oldDel

-- メールの数を数える
-- リソースには最後に改行(空行)が入っているので、メールの数はリストの
-- 項目数より2少なくなる
set x to (count mList) - 2

-- メールを個々に読みだす
repeat with i from 1 to x
  
  -- MT Read File はバイトオフセットではなくバイト数で読み込み位置を指定
  -- するため、オフセットに1を加えたものを使う
  set startByte to ((item i of mList) as integer) + 1
  set endByte to (item (i + 1) of mList) as integer
  
  set myData to MT Read File tgFile from startByte to endByte
  
  --- この時点で mydata の中には i 番目のメールのデータが入っている
end repeat

参考になれば幸いです。

なお、mboxer のファイルの個々のメールは、必ず

From ???@??? Fri Apr 23 10:22:10 2004

という行から始まります(日付の部分は変わりますが)。ですから、この
From ???@??? を目印として探してメールを見つけ出すこともできます。

だいとう さんからのコメント
( Wednesday, September 01, 2004 13:36:45 )

早速のコメントありがとうございます。
mboxerとUVJはメールに関していろいろなことができるので、
重宝して、感謝しております。

さて、スクリプトまで書いていただき恐縮なのですが、
mboxerがダウンロードしたファイルを切り出すのではなく、
メールサーバから直接コピーしてきた生のmboxファイルを、
mboxerが吐き出したのごとく、リソースを付け加えたいのです。
mboxerがどのようなキーをトリガーにしてリソースに書き加えているのか、
あるいは1通メールをダウンロードするごとにファイルサイズから割り出して
いるのか?
Fromを頼りにメールを分割しようとすると、
ヘッダの中に入っている区切りではない部分のFromも拾ってしまいそうです。
改行の次のFromでと指定できれば良いかとも考えたのですが、
MT Search Position ではうまく指定できませんでした。

まさに以前先生が書かれていた
>これについては、1.1 の正式版までには、
>「リソースがなかった場合には、中身をスキャンして、
>先頭位置を割り出したうえで処理を行う」というのを実装する予定でいます。
をTanaka's osax 2.0 で実現したいのです。

私の説明不足で申し訳ありません。
でもmboxerでのconvert to filesの動きはよくわかりました。
ありがとうございます。

田中求之 さんからのコメント
( Wednesday, September 01, 2004 15:52:59 )

あ、そういうことでしたか。早とちりしてしまいました (^_^;;

UNIX mbox ファイルは、基本的には From で始まる行を目印にメールの区切りを
探していくしかないと思います。mbox の規格について書かれた本を自宅に
おいてきてあるので、はっきりとしたことはいえませんが。

で、確かに本文中に From で始まる行があるとメールの区切りだと誤認する
可能性はあるのですが、From がヘッダの先頭にある(=つまり次の行は
Return-Path ヘッダや Received ヘッダという SMTP のサーバが標準的に
付加するヘッダになっているはず)かどうかをもとに判断すると、かなり
うまく行くはずです。もちろん、これでもメールの本文中にヘッダのコピー
が入ったものなんかがあるとアウトですけど。

ファイルを1行ずつ読み込んでいって、チェックしていくという、けっこう
泥臭い処理をすることになりますね。

だいとう さんからのコメント
( Monday, September 06, 2004 00:37:45 )

いろいろやってみたのですが、Jeditをスクリプトから動かすのが、
今後の汎用性もあり、得策と思いました(正規表現が使える)。
\rFromと指定して切り出して、分割保存して、そのフォルダーをUVJで指定し、
移行先のサーバにメールを配信するようにしよう思います。
ヘッダを引用していたりなんかすると誤動作しそうですが、
移行時期にはユーザーに促して、多少のリスクは覚悟してもらおうと思います。