帝力何有於我哉

無職。汎用人型雑用兵器。型式番号: 高木 宏 ( Hiroshi Takagi )

Becky!2 → ThunderBird3 : mbox 構造調整スクリプト

Farewell to Becky!

長年使っているBecky!2がついに破綻して来た。

だいたい、機器の障害監視用のalert/notify メールはがんがん飛んでくるわ、お客さんは平気で数十Mbyteクラスのファイルを添付してMLにpost してくるわ、な環境では、Becky!のメッセージ管理のしくみでは、もう持たないのはBecky!のせいではない。
わたしのBecky!のフォルダは総計40GB以上、ひとつのフォルダに一万通以上のメッセージがあることもざらなのだから。

どうせ引っ越すなら、Windows とおさらばできるようにThunderBird 3 へ、ということでこの一週間、少しずつ引越しの準備を進めてきた。
なんとか簡単にできるようになったので、同じようなことを考えている人のために、移行方法のメモとスクリプトを残しておく。

How to export from Becky! and How to import to Thundirbird : research

ぐぐってみると意外にこの手の話題が少ない。

  1. http://smileart.sakura.ne.jp/wordpress/archives/45.html
  2. input.html

どちらも、CircleBeckyというBecky!プラグインで、(たいていの人はそうであろう)階層構造化しているBecky!のメールフォルダとメッセージを再帰的にエクスポートしている。違いは、

  1. は、eml 形式でエクスポート(1メッセージ1ファイル)
  2. は、mbox 形式でエクスポート

しているところにある。
さらに 1. は、Thunderbird 側にImportExportToolsという拡張機能を入れて、フォルダ階層にエクスポートされた eml ファイルをフォルダ階層を再現しつつ取り込んでいる。

ひとことでいうと、

  1. は、操作はとても簡単で、上のリンクにあるとおりの手順で終わる。ただし、メッセージがたくさんある人は、エクスポートもインポートもとんでもなく時間がかかる。
  2. は、エクスポートが早く。インポートの操作はない(フォルダにほうり込むだけ)が、Becky!がエクスポートするmbox のフォルダ階層とThunderbird のそれが違うことから、フォルダ構造とパス名の調整が手作業で必要になる。

フォルダあたりに万単位のメッセージをかかえていた私には、1.の方法は中規模のフォルダてちょっと時間を計測してみて使い物にならない、とあきらめた。小規模ののテストフォルダなら、とても楽なんだが。

また、仕事がら一日数千のメールと戦うために数百に達しているフォルダの階層構造は自分でも覚ええていないくらいの深い深い密林と化しているので 2. の「手作業によるmboxの調整」も現実性がない。

というわけで、エクスポートがとても早い 2. の移行戦略を取り、「手作業」の部分を ruby にやらせることにした。

How to convert mboxes exported from Becky! into Thunderbirds' style

2. のmboxの変換の部分はとてもよくまとまっているので、ちょっと無断転載。

Thunderbirdではファイル自体がひとつのメールフォルダとして認識されてしまうので、CircleBeckyからの出力をそのまま置くと、[元のフォルダ名].mbox という名前のフォルダとして見えてしまう。さらに悪いことには、サブフォルダは[サブフォルダ名].sbd という名前のディレクトリを作っておかないと認識されないので、CircleBeckyの出力をそのまま置くと、サブフォルダはまったく認識されないということになってしまう。

という訳で、CircleBeckyから出力されたファイルの位置とファイル名、ディレクトリ名を変更しなければならない。手順は以下のとおり。

1. [メールフォルダ名].mbox という名前のファイルをすべて一つ上のディレクトリに移動する。
2. 空になったディレクトリはすべて削除する。
3. メールフォルダの名前が付いたディレクトリ、サブディレクトリの名前をすべて [元の名前].sbd に変更する。
4. [メールフォルダ名].mbox というファイルの名前から .mbox という拡張子を削除する。

実は、rayman さんが、まとめている手順はひとつ抜けている点がある。
MUAをつかっていると、複数のフォルダをかかえるためだけのメッセージを持たないフォルダができる。この場合がうまくいかない。

例えば、

customers

    • customer_name1
    • customer_name2
    • customer_name3

という構成のBecky!フォルダがあり、customers には何もメッセージはなく、customer_name[1-3]には、実際の顧客のメッセージがある場合、まず Circle Becky は、以下のファイルをエクスポートする。

customers <-- directory

    • customer_name1 <-- directory
        • customer_name1.mbox <-- mbox file
    • customer_name2 <-- directory
        • customer_name2.mbox <-- mbox file
    • customer_name3 <-- directory
        • customer_name3.mbox <-- mbox file

これを上の手順で変換すると、

customers.sbd <-- directory
customer_name1 <-- mbox file
customer_name2 <-- mbox file
csutomer_name3 <-- mbox file

ができるが、これでは Thunderbird は、customer フォルダの存在を認識してくれない。同じディレクトリに、

customers

という mbox ファイル(空でよい)が必要になる。

上の手順にこの空のmbox を作る(touchする)ロジックを加えて、変換用のスクリプトを作成した。

ruby script for convert

以下は、変換にやっつけで作った、cvt.rb というスクリプト
例によってテストもエラー処理もぜんぜんやってない(すみません。)

$KCODE = "SJIS"

require 'jcode'
require 'fileutils'

def cvtB2mboxdir2thunderbird(t_dir)
  FileUtils.cd(t_dir)
  puts FileUtils.pwd

  subdir_found = false
  folder_contains_only_folders = true
  mbox_list = Array.new

  Dir.glob("*").each do |path|
    if /^(.+)\.mbox$/ =~ path
      FileUtils.mv(path, "../")
      mbox_list << path
      puts path

      if $1 == File.basename(t_dir)
        folder_contains_only_folders = false
      end
    end

    if FileTest.directory?(path)
      subdir_found = true
      cvtB2mboxdir2thunderbird(path)
    end
  end

  FileUtils.cd("..")
  puts FileUtils.pwd

  unless  subdir_found
    FileUtils.rmdir(t_dir)
  else
    FileUtils.mv(t_dir, "#{t_dir}.sbd")
  end

  mbox_list.each do |mbox_file|
    basename = File.basename(mbox_file, ".mbox")
    FileUtils.mv(mbox_file, basename)
  end

  if folder_contains_only_folders
    FileUtils.touch(File.basename(t_dir))
  end

  puts
end

cvtB2mboxdir2thunderbird(ARGV[0])

あっちこっちに、FileUtils.pwd を出力しているのは、どこまで変換が進んだかを見てないと退屈なのと、再帰的なロジックは昔から苦手なので、ようすをみたいから。

CircleBecky で mbox エクスポートしたフォルダをコマンドラインで指定して、

ruby -Ks cvt.rb C:\becky_exported\folder_top

で、ok。
あとは、変換された mbox ファイルとフォルダ群をThundirBird のデータフォルダに入れるだけ。

eml エクスポートの数十分の一の時間で移行できるので、仕事の合間に少しずつ、フォルダを移行できた。

このスクリプトを書いてみて、はじめて、FileUtils に touch なんてメソッドがあるのを知った。でも、FileUtils ってクラス名はいまいちいけてないなぁ、と思いません?

あとは、振り分けルールの変換かなぁ〜。変換するより、msgFilterRules.dat を簡単に生成するクラスでも書いておいて、コマンドラインから同形式のルールをばんばん作るほうが楽なような気がしてきたな。