Home > Latest topics

Latest topics > Thunderbirdでメールの本文を文字列として取得する

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Thunderbirdでメールの本文を文字列として取得する - Feb 06, 2008

nsIMsgDBHdrとnsIMsgFolderからメールの本文を文字列として取得する方法をあれこれ試してみてこんな感じのところに辿り着きましたとさ。

// とりあえず現在選択してるメールを処理対象にしてみる。
var hdr = gDBView.db.GetMsgHdrForKey(gDBView.keyForFirstSelectedMessage);
var folder = gDBView.msgFolder;


// ストリームを取得して、読み取り開始位置をセット
var stream = folder.getOfflineFileStream(hdr.messageKey, {}, {})
  .QueryInterface(Components.interfaces.nsISeekableStream)
  .QueryInterface(Components.interfaces.nsILineInputStream);
stream.seek(stream.NS_SEEK_SET, hdr.messageOffset);

var multipart = false;
var boundary = '';
var charset = null;

var charsetRegExp = /Content-Type:[^;]+;.*charset=['"]?([^'";\s]+)/;

// read header
// 一行単位で読み込み
var line = {};
while (stream.readLine(line))
{
  if (!charset && charsetRegExp.test(line.value)) {
    charset = RegExp.$1;
  }
  if (line.value.indexOf('multipart/') || line.value.indexOf('message/')) {
    multipart = true;
  }
  // マルチパートのパートごとの区切り文字を取得
  if (!boundary && line.value.indexOf('boundary=') > -1) {
    boundary = line.value.substring(line.value.indexOf('"')+1);
    boundary = '--' + boundary.substring(0, boundary.indexOf('"'));
  }
  if (!line.value) break; // 改行が連続したらヘッダの終わり
}

// read body
var msg = [];
var count  = hdr.lineCount; // 本文の行数はnsIMsgDBHdr.lineCountで取れる
for (var i = 0; i < count; i++)
{
  if (!stream.readLine(line)) break;
  msg.push(line.value);
}

stream.close(); // クローズを忘れずに。

var UConv = Components
  .classes['@mozilla.org/intl/scriptableunicodeconverter']
  .getService(Components.interfaces.nsIScriptableUnicodeConverter);

msg = msg.join('\n');
if (multipart && boundary) {
  var parts = msg.split(boundary+'\n');
  msg = [];
  for (var i in parts)
  {
    parts[i] = parts[i].split('\n\n');
    if (parts[i][0].indexOf('Content-Type: text/') < 0) continue;
    charsetRegExp.test(parts[i][0]);
    parts[i].splice(0, 1);
    var body = parts[i].join('\n\n');
    if (RegExp.$1) {
      UConv.charset = RegExp.$1;
      body = UConv.ConvertToUnicode(body);
    }
    msg.push(body);
  }

  msg = msg.join('\n\n');
}
else if (charset) {
  UConv.charset = charset;
  msg = UConv.ConvertToUnicode(msg);
}


alert(msg);

nsMsgBodyHandler.cppとかThunderbirdのメッセージ検索まわりのコードを辿りまくってヒントを集めて、どうにかここまで辿り着いた。この時点でもう力尽きたので、Bodyを読んでから先はテケトーです。Base64エンコードされたパートのデコードとかちゃんとしないと多分実用にはならないか。

これで読み込んだ内容をMozStorageに保存しておいてそれに対して正規表現を……というやり方でXUL/Migemoでのメール本文検索をやろうとしてるんだけど、よく考えたらこれって、メールボックスをまるごとMozStorageにコピーしてるってことですよねぇ。うわー。なんという壮大な無駄。

分類:Mozilla > XUL, , , , , , 時刻:20:11 | Comments/Trackbacks (3) | Edit

Comments/Trackbacks

no title

今のXUL/Migemoがどういう実装になっているかは知りませんが、場合によってはこれが応用できるんじゃないですかね。
http://ja.wikipedia.org/wiki/シグネチャ法
C/Migemoのように極限まで切り詰めた正規表現ではなく、昔のXUL/Migemoのような単純な正規表現だったら、要するに単語の羅列なわけで。

Commented by plus7 at 2008/02/07 (Thu) 00:12:39

no title

紹介していただいた資料とか見て検討してみたんですが、そのまま使うのは無理ぽですね。XUL/Migemoの場合は単語リストだけじゃなくて、ローマ字→ひらがな・カタカナに変換された文字列もあるので、検索に漏れが発生してしまう……ページ内検索で漏れがあっては困る。

でも本文まるごと持ち続けるのはやっぱり無駄が大きすぎですよね。単語リスト部分は紹介していただいた方法で、ローマ字から変換して生成された部分は一文字単位で分割してから同じ方法で、という風にすればうまくいくでしょうか?(後で試してみるつもり)

あと、どっかで見たような話だなと思ったらこれを思い出しました。
http://wiki.livedoor.jp/mala__/d/Mozilla%2024

Commented by Piro at 2008/02/09 (Sat) 21:06:44

Thunderbird のアドオンを作ってみる(Ubuntu) Part 4

前回、DOM Inspector を紹介してからずいぶん経ってしまいましたが、
今回はIDEの紹介でも。

いま私はこれを使っています。
Spket IDE

ページの上...

Trackback from 青い海プロジェクト at 2009/03/02 (Mon) 00:51:43

TrackBack ping me at


の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2008-02-06_thunderbird-message-body.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2020年11月30日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき