秀丸メール → Thunderbird 移行マクロ

私は8年ほど秀丸メール(元・鶴亀メール)を使っていました。ここ2、3年ほどはThunderbirdに移行したいと思いつつ面倒であきらめるというスパイラルを繰り返していましたが、ようやく重い腰を上げて移行してみることにしました。
メーラーの乗り換えはブラウザの乗り換えよりはるかに大変です。移行ツールなどお手軽な移行方法があればまだいいですが、秀丸メールThunderbird の移行ツールのようなものは見つけることができませんでした。
数十のフォルダに分かれた数万のメールを手作業で移行するのはありえないのでまずは移行ツールを作らないといけません。秀丸メールのマクロライブラリに「1アカウント丸ごとエクスポート」というマクロがあったのでこちらをベースに作ることにしました。

Thunderbirdのメールデータのディレクトリ構造は以下のようになっています。

  • メールフォルダごとに1つのファイル(Unix mbox形式)が作られる。
  • サブフォルダがある場合は「フォルダ名.sbd」という名前でディレクトリが作られる。

なお、「フォルダ名.msf」というファイルはメールの要約ファイルで、Thunderbirdが自動的に作ります。

秀丸メールには、メールをUnix mbox形式でエクスポートする機能があるので、ディレクトリ構造を作成しつつUnix mbox形式でフォルダごとにエクスポートすればよさそうです。先ほどのマクロを以下のように変更しました。

  • 1メール1ファイル(eml形式)でエクスポートするようになっているのを、1フォルダ1ファイル(Unix mbox形式)でエクスポートするように変更。
  • サブフォルダに「.sbd」を付けるように変更。
  • Thunderbirdに合うようにフォルダ名の変更。(受信→Inbox、未送信→Unsent Messages、送信済み→Sent)

コードを下に載せておきます。やっつけ仕事ですがたぶん1回しか使用しないので勘弁してください。もし使ってくださる場合は、無保証、自己責任でお願いします。
なお、メールの振り分けルール、アドレス帳などは移行できません。めんどくさいですが手動で移行してください。

使い方

  1. 下のマクロを適当なファイル名で保存してください。(例: turukame2thunderbird.mac)
  2. ファイルを開いて、エクスポート先ディレクトリを適当に変更してください。(デフォルトでは、C:\Temp\Mail\ 以下にエクスポートされます。)
  3. 秀丸メールを起動し、エクスポートしたいアカウントをマウスで選択してください。
  4. マクロメニューからマクロを起動してください。
  5. エクスポートされたファイルをThunderbirdのプロファイルフォルダの配下に移動してください。同名のファイルを上書きするとThunderbirdで受信済みのメールは消えてしまうのでご注意ください。
// turukame2thunderbird.mac
// 秀丸メール → Thunderbird エクスポートマクロ

// 2009-04-18 modified by K.CIMA 「1アカウント丸ごとエクスポートマクロ」を変更

loaddll "TKInfo.dll";

if ( !result )  endmacro;
if ( !dllfunc( "IsTuruKame" ) )  endmacro;

// エクスポート先のベースディレクトリ
// 適宜修正してください(最後に\\を付けること)
$base_dir = "C:\\Temp\\Mail\\";

// フォルダ名のマッピング
#nname = 3;
$tkname[0] = "受信";
$tkname[1] = "未送信";
$tkname[2] = "送信済み";
$tbname[0] = "Inbox";
$tbname[1] = "Unsent Messages";
$tbname[2] = "Sent";

// アカウント名を記録しておく
$currentAccount = dllfuncstr( "CurrentAccount" );
// アカウントの先頭に移動
#n = dllfunc( "SelectFolder", "", "" );

while (1) {
    #n = dllfunc( "ExpandFolder", 1 );
    #n = dllfunc("NextFolder");
    if (#n == 0) {
        message "エクスポート終了。";
        endmacro;
    }

    $account = dllfuncstr( "CurrentAccount" );
    if ($account != $currentAccount) {
        message "エクスポート終了。";
        endmacro;
    }

    $folder = dllfuncstr( "CurrentFolder" );
    // エクスポート対象外
    if ($folder == "未送信" || $folder == "草稿" || $folder == "ゴミ箱")  continue;

    call ExportAllMails;
}

endmacro;

// 現在選択されているフォルダの、全てのメールをエクスポートするサブルーチン
ExportAllMails:
    ##n = dllfunc( "GetFolderMailCount", "", "", "all");
    if (##n == 0)  return;

    ##n = dllfunc("SetViewArea", 0);
    ##n = sendmessage( hidemaruhandle(0), 0x0111, 40008, 0); // すべて選択

    $$folder = dllfuncstr( "CurrentFolder" );
    //message $$folder;
    call FixDirectoryName $$folder;
    $$folder = $$return;
    //message $$folder;

    call DirName $$folder;
    $$subfolder = $$return;
    call BaseName $$folder;
    $$mbox = $$return;

    //message $$subfolder + ", " + $$mbox;
    call CreateDirectory $base_dir + $$subfolder;

    ##n = dllfunc("Export", $base_dir + $$subfolder + $$mbox, "mbox", "encode-attach", "orikaeshi");

    return;

// 渡されたパスのディレクトリを作成するサブルーチン
// MakeSureDirectoryPathExists関数と同じ
CreateDirectory:
    $$dir = $$1;
    $$mkdir = "";

    ##i = 0;
    while (##i < #nname) {
        ##pos = strstr($$basename, $tkname[##i]);
        if ( ##pos == 0 ) {
            $$basename = $tbname[##i] + rightstr($$basename, strstr($$basename, "\\"));
            break;
        }
        ##i = ##i + 1;
    }

    ##pos = strstr($$dir, "\\");
    while (##pos >= 0) {
        if (strlen($$mkdir) > 0)  $$mkdir = $$mkdir + "\\";
        $$mkdir = $$mkdir + leftstr($$dir, ##pos);
        $$dir = rightstr($$dir, strlen($$dir) - ##pos - 1);
        ##n = dllfunc("Bypass_CreateDirectory", $$mkdir);

        ##pos = strstr($$dir, "\\");
    }

    if (strlen($$dir) > 0 ) {
        if (strlen($$mkdir) > 0)  $$mkdir = $$mkdir + "\\";
        $$mkdir = $$mkdir + $$dir;
        ##n = dllfunc("Bypass_CreateDirectory", $$mkdir);
    }

    return;

// ディレクトリ名をThunderbirdの形式に変換する
FixDirectoryName:
    $$basename = $$1;
    $$dirname  = "";

    ##pos = strstr($$basename, "\\");
    if ( ##pos >= 0 ) {
        $$topdir = leftstr($$basename, ##pos);
        $$temp   = "\\" + rightstr($$basename, strlen($$basename) - ##pos - 1);
    }
    else {
        $$topdir = $$basename;
    }

    // ディレクトリ名置換
    ##i = 0;
    while (##i < #nname) {
        if ( $$topdir == $tkname[##i] ) {
            $$topdir = $tbname[##i];
            break;
        }
        ##i = ##i + 1;
    }
    $$basename = $$topdir + $$temp;

    // ディレクトリ名に".sbd"を付ける
    ##pos = strstr($$basename, "\\");
    while (##pos >= 0) {
        $$dirname  = $$dirname + leftstr($$basename, ##pos) + ".sbd\\";
        $$basename = rightstr($$basename, strlen($$basename) - ##pos - 1);

        ##pos = strstr($$basename, "\\");
    }

    return $$dirname + $$basename;

// 渡されたパスからファイル名部分を取り出す
BaseName:
    $$basename = $$1;
    $$dirname  = "";

    ##pos = strstr($$basename, "\\");
    while (##pos >= 0) {
        if (strlen($$dirname) > 0)  $$dirname = $$dirname + "\\";

        $$dirname  = $$dirname + leftstr($$basename, ##pos);
        $$basename = rightstr($$basename, strlen($$basename) - ##pos - 1);

        ##pos = strstr($$basename, "\\");
    }

    return $$basename;

// 渡されたパスからディレクトリ名部分を取り出す
DirName:
    $$basename = $$1;
    $$dirname  = "";

    ##pos = strstr($$basename, "\\");
    while (##pos >= 0) {
        if (strlen($$dirname) > 0)  $$dirname = $$dirname + "\\";

        $$dirname  = $$dirname + leftstr($$basename, ##pos);
        $$basename = rightstr($$basename, strlen($$basename) - ##pos - 1);

        ##pos = strstr($$basename, "\\");
    }

    return $$dirname + "\\";

Thunderbirdに移行してみてまず、秀丸メールの軽快さは異常だと思いました。秀丸メールは1万通超のメールを移動、削除しても数秒で終わりますが、Thunderbirdだと秒間100通も処理できていないように見えます。しかもかなりの確率でフリーズするようです。
今のところ秀丸メールの優秀さを改めて実感するという結果になってしまっていますが、試してみたい機能などはいろいろあるので使い続けてみようと思います。