namazu で全文検索サービスを作ってみよう

Latest Update 2003/8/12

メーリングリストアーカイブの全文検索

これも、元は参考にした本に載っていた話題で、メーリングリストの記事を HTML に変換し、namazu に食べさせてみようというもので、実用性が高くお薦めです。メールから HTML を作るのに MHonARC というフリーソフトを利用します。

ただし、書籍の宿命で情報がかなり古くなっており、MHonArc に関する情報はもはや obsolete と言わざるをえません。また古い MHonARC (2.6.2以前) には XSS 問題があり、特にインターネットに公開する場合は最新バージョンをつかうことが必要です。

私は Takashi P.KATOH 氏の Web ページを大いに参考にさせていただきました。恐らく最新の MHonARC での日本語処理については一番の情報源でしょう。

まずは、メールを UNIX で受け取らなければいけません。すでに MHonARC で作業しようというマシンが直接(まあ FireWall 越しでもいいけど、NAT/NAPT なしで)Internet に接続されているなら話は簡単です。ですが。現在私のところは ADSL ルータで IPCP による動的IP割り当てで、プロバイダの POP3 アカウントがあるだけで、UNIX へはそのままではフィードできません。

UNIX で POP3 でメールを取るためには、私の知っている限り、
  1. mh でそれなりに設定して inc
  2. popclient というプログラムをつかう
  3. fetchmail をつかう
の3つくらいあります。このうち、(2) の popclient はもう開発終了しているとのこと。私は簡単そうな (3) を選びました。

fetchmail の設定は、メールを読み取りたいユーザの $HOME に .fetchmailrc という設定ファイルを作ります。

                                                                         
% cat .fetchmailrc
defaults
        no mimedecode
        no rewrite
        mda "/usr/sbin/sendmail -oem %s"

poll mail.example.ne.jp
        username myname
        password naisho
        is otherone


としています。一目瞭然の分かりやすいファイルですが、パスワードを平文で記載していることに注意が必要です。パーミッションは 600 にしておかなければなりません。

また、Webで見つかる多くの文献では、mda に mail.local をつかっていますが、FreeBSD QandA 303 にあるように、FreeBSD では mail.local の suid-root が外されたため動作しません。後述する procmail をいきなり使うのでもよいですが、とりあえず受信の確認ぐらいはしたかったので、sendmail に渡すようにしてあります。

それと、is otherone と書いた行は、そのメールサーバから受け取ったメールを他人のスプールに書きこむ設定です。Web サーバで、普段自分が使っているアカウントとは別の ID で MHonARC の処理をしたい場合が多いと思うので、今の場合は適当なアカウントを指定しておきます。念のためここで書いた otherone は vipw で passwd 欄を * にして直接ログインできないようにし、いつも root から su して作業をするようにしています。

それから、sendmail.cf の設定もしておきましょう。公開Webサーバであれば、最低限自前のメールが受け取れるようにしておきます。必要がなければ外部への port 25 は開けなくてもかまいません。ただし、コマンドメールをメーリングリストサーバへ送って受け取るのなら、それが正しくメーリングリストサーバに届き、このサーバ、または fetchmail でアクセスできるアドレスへ返事が帰って来るように留意しておく必要があります。

あと、メールを POP3 サーバに残しておきたい場合には、fetchmail -k のように実行します。

次に、otherone ユーザがメールを受け取った時に処理する procmail の設定をします。当然、otherone ユーザで操作します。

procmail そのものは特にコンパイルに凝ったことをしなくてよいので packages で入れてしまいました。

procmail の設定は $HOME/.procmailrc に記述します。

                                                                         
 1: LOGFILE=$HOME/procmail.log
 2: LOCKFILE=$HOME/.procmail_lock
 3: MAILDIR=/var/mail
 4: DEFAULT=/dev/null
 5: :0
 6: *^X-ML-Name: Zakky-ML
 7: | /usr/local/bin/mhonarc -umask 022 -add -modtime -rcfile \
 8: $HOME/mhonarc_zakky.rc -outdir /usr/local/apache/htdocs/mail/zakky --
 9: 
10: :0
11: *^X-ML-Name: zakky
12: | /usr/local/bin/mhonarc -umask 022 -add -modtime -rcfile \
13: $HOME/mhonarc_zakky.rc -outdir /usr/local/apache/htdocs/mail/zakky --
14: 
15: :0
16: *^X-ML-Name: RamRam
17: | /usr/local/bin/mhonarc -umask 022 -add -modtime -rcfile \
18: $HOME/mhonarc_ramram.rc -outdir /usr/local/apache/htdocs/mail/ramram --
19: 
20: :0
21: *^X-ML-Name: ramram
22: | /usr/local/bin/mhonarc -umask 022 -add -modtime -rcfile \
23: $HOME/mhonarc_ramram.rc -outdir /usr/local/apache/htdocs/mail/ramram --



1,2 はログファイル、ロックファイルの設定。おかしいときはログファイルを確認。おかしいのにログファイルがなければ、メールが受け取れていないということになります。この時には fetchmail のログや /var/log/maillog (FreeBSD の場合) で sendmail が吐くログを確認してください。

3 は sendmail 経由でメールを受け取るため。mh のフォルダなどから読む場合や、qmail を使う場合は変更してください。

4 は、あとで指定する検索条件にひっかからなかったメールは捨てるという指定です。これも適宜変更してください。

5,10,15,20 で、ここから検索条件を指定します。決まり事だと思ってください。

6,11,16,21 で、具体的な検索条件を書きます。ここでは、X-ML-Name ヘッダを指定していますが、実情に合わせて変更してください。大文字・小文字も区別されます(16,21)。

7,12,17,22 では、パイプ記号で後ろに繋げる処理を書くことができます。実はそれまで nkf -m でデコードしてから渡していたのですが、namazu で検索した結果表示の際に利用する

<!--X-Subject: [RamRam:00001] テスト

という部分が文字化けしてしまうため、別の方法を取りました(後述)。

それが終わったら、MHonARC をコンパイルしましょう。2003/8/11 現在で最新は 2.6.7 です。

                                                                         
% cd /usr/local/src
% tar xvzf /somewhere/MHonARC2.6.7.tar.gz
% cd MHonARC2.6.7
% su
# perl install.me
Checking dependencies:
	Fcntl ......................... ok
	File::Basename ................ ok
	Getopt::Long .................. ok
	Symbol ........................ ok
	Time::Local ................... ok
Pathname of perl executable: ("/usr/bin/perl") 
Directory to install executables: ("/usr/local/bin") 
Directory to install library files: ("/usr/local/lib/perl5/site_perl/5.005") 
Directory to install documentation: ("/usr/doc/MHonArc") 
"/usr/doc/MHonArc" does not exist.  Create ['y'] y
Directory to install manpages: ("/usr/local/man") 
You have specified the following:
	Perl path: /usr/bin/perl
	Bin directory: /usr/local/bin
	Lib directory: /usr/local/lib/perl5/site_perl/5.005
	Doc directory: /usr/doc/MHonArc
	Man directory: /usr/local/man
Is this correct? ['y'] 
(/usr/bin/perl)
Installing programs to "/usr/local/bin":
(以下略)


いくつか質問されるので、自分の環境に合わせて答えます。

インストールが終わると、リソースファイルを作成するのですが、リソースファイルの型式もすでに図書のものとは大きく変更されています。私は vfr さんの「MHonARC 徹底解剖」を参考にさせていただきました。mhonarc を実行するユーザの $HOME に作ってみましょう(当たり前ですが、$HOME/.procmailrc で指定したファイル名に合わせてください)。サンプルは、ソースを展開したディレクトリの ./examples 以下にあります。私は vfr 氏のサイトにあったサンプルを改造して使いました。Next page とかの表示を日本語にしてもいいのですが、中途半端にしか日本語にならないのが頭の痛いところです。

                                           
<!--
  -- MHonArc Resource File for Zakky ML
  --   Created by Toru Morimoto <too@os.gulf.or.jp>
  --   Refering to http://www15.xdsl.ne.jp/~vfr/debian/namazu/create-mhonarc.html
  --   Thanks a lot.
--!>

<!-- ヘッダのMIMEデコードを指定。 -->
<DECODEHEADS>

<!-- JST の処理。サイトによっては入れていないところもあるみたい -->
<TIMEZONES>
JST:-0900
</TIMEZONES>

<!-- デフォルトで本文は ISO-2022-JP とみなします -->
<DEFCHARSET>
iso-2022-jp
</DEFCHARSET>

<!-- p-kato 氏の http://www.shiratori.riec.tohoku.ac.jp/~p-katoh/Hack/Docs/mhonarc-jp/
mhonarc-jp-2_6-draft.html を参照。ただし、plain 以下の行もないと一部ヘッダの処理で文字化けします
 -->
<CHARSETCONVERTERS>
iso-2022-jp; iso_2022_jp::str2html; iso2022jp.pl
plain; iso_2022_jp::str2html; iso2022jp.pl
</CHARSETCONVERTERS>

<!-- Mail アドレスに mailto タグをつけません。MLでは<NOMAILTO>を指定するよう推奨されているのと、
文字化け対策にもなっている -->
<NOMAILTO>

<!-- ファイルのタイムスタンプをメールの Date: ヘッダに合わせる。なぜか筆者の環境では ML サーバが
送り返す実際の時間になってしまう(投稿された時間ではない)  -->
<MODTIME>

<!-- MHonARC に処理させないヘッダを指定する。通常メーリングリストの場合 To などは決まり切っている
ので不要 -->
<EXCS>
To
Delivered-to
Mail-followup-to
Mailing-list
</EXCS>

<!-- Main index, Thread index を作成します。まあ必須でしょうね -->
<Main>
<Thread>

<!-- 複数ページのindexを作成(1ページ50件) -->
<MultiPG>
<IdxSize>
50
</IdxSize>

<!-- 各メッセージファイルのヘッダで表示するもの -->
<MsgPgBegin>
<!doctype html public "-//W3C//DTD HTML//EN">
<html>
<head>
<title>$SUBJECTNA$</title>
<link rev="made" href="mailto:$FROMADDR$">
</head>
<body>
</MsgPgBegin>

<!-- 表示するメールヘッダの指定 -->
<FieldOrder>
to
from
date
</FieldOrder>

<!-- 日付順にソートします -->
<Sort>

<!-- indexファイル名をindex.htmlに apache の設定とあわせてください -->
<IdxFname>
index.html
</IdxFname>

<!-- 各記事のリスト書式を Subject FromAddressに -->
<LiTemplate>
  <li><b>$SUBJECT$</b> 
      <i>$FROM$</i>
</LiTemplate>

<!-- 前ページ、次ページ定義 -->
<PrevPgLink chop>
[<a href="$PG(PREV)$">Prev page</a>]
</PrevPgLink>
<NextPgLink chop>
[<a href="$PG(NEXT)$">Next page</a>]
</NextPgLink>

<!-- index.htmlのヘッダで表示するもの -->
<!-- 参考にさせていただいた vfr氏 のページでは外部変数を取り込んで処理しておられたが-->
<!-- 私がやると普段の行いが悪いのかうまくいかないので、結局埋めこみました-->

<IdxPgBegin>
<!doctype html public "-//W3C//DTD HTML//EN">
<html>
<head>
<title>Zakky ML Archives</title>
<link rev="made" href="mailto:$FROMADDR$">
</head>
<body>
<div align="left">
<font size=+3>
Zakky ML Archives
</font>
</div>
<div align="right">
[<a href="$FIRSTPG$">First page</a>][<a href="$LASTPG$">Last page</a>]
$PREVPGLINK$$NEXTPGLINK$[<a href="threads.html">Thread Index</a>][<a href="
../index.html">Index</a>]
</div>
</IdxPgBegin>

<!-- リストの頭の指定 -->
<ListBegin>
<hr noshade>
</ListBegin>

<!-- リスト書式のおわり -->
<ListEnd>
<hr noshade>
</ListEnd>

<!-- mhonarc footer -->
<!-- NODOC を有効にすると表示しなくなります -->
<!-- <NODOC> -->

<!-- index.html のおわり -->
<!-- address タグの中はお好みで変えてください -->
<IdxPgEnd>
</body>
<div align="right">
[<a href="$FIRSTPG$">First page</a>][<a href="$LASTPG$">Last page</a>]
$PREVPGLINK$$NEXTPGLINK$[<a href="threads.html">Thread Index</a>][<a href="
../index.html">Index</a>]
<address>MHonARC Configured by too@.os.gulf.or.jp</address>
</div>
</html>
</IdxPgEnd>

<!-- Main index Rayout -->

<!-- Thread index Rayout -->
<!-- 日付の若い順にソート -->
<TSort>
<!-- <TReverse> -->

<!-- Thread の深さ -->
<TLevels>
10
</TLevels>

<!-- 前ページ、次ページ定義 -->
<TPrevPgLink chop>
[<a href="$PG(TPREV)$">Next page</a>]
</TPrevPgLink>
<TNextPgLink chop>
[<a href="$PG(TNEXT)$">Prev page</a>]
</TNextPgLink>

<!-- threads.htmlのヘッダで表示するもの -->
<TIdxPgBegin>
<!doctype html public "-//W3C//DTD HTML//EN">
<html>
<head>
<title>Zakky ML Archives</title>
<link rev="made" href="mailto:$FROMADDR$">
</head>
<body>
<div align="left">
<font size=+3>
Zakky ML Archives
</font>
</div>
<div align="right">
[<a href="$TFIRSTPG$">First page</a>][<a href="$TLASTPG$">Last page</a>]
$TPREVPGLINK$$TNEXTPGLINK$[<a href="index.html">Date Index</a>][<a href="
../index.html">Index</a>]
</div>
</TIdxPgBegin>

<!-- リストの頭の指定 -->
<THead>
<hr noshade>
<ul>
</THead>

<!-- Subject毎にリスト化 -->
<TTopBegin>
<p>
<li>
<!-- リストの先頭に [Zakky 123456] などだけ表示されても見にくいのでやめた -->
<!-- <font color="#708898"><b>$SUBJECTNA$</b></font><br> -->
<b>$SUBJECT$</b> 
<i>$FROM$</i>
</TTopBegin>

<!-- Possible follow-upsの記述 -->
<!-- 全部見たわけではないですが、うちではうまく動いていないようです -->
<!-- vfr氏のサンプルでは無効にしておられます。その方がよいかも -->
<TSubjectBeg>
<li><たぶん…関連記事gt;</li>
</TSubjectBeg>


<!-- 各記事のリスト書式を Subject FromAddressに -->
<TLiTxt>
<li><b>$SUBJECT$</b> 
<i>$FROM$</i>
</TLiTxt>

<!-- Subject毎のおわり -->
<TTopEnd>
</p>
</TTopEnd>

<!-- スレッドの無い記事の扱い -->
<TSingleTxt>
<p>
<li>
<!-- 上で書いたのと同じ理由で無効にしています -->
<!-- <font color="#708898"><b>$SUBJECTNA$</b></font><br> -->
<b>$SUBJECT$</b> 
<i>$FROM$</i>
</p>
</TSingleTxt>

<!-- リスト書式のおわり -->
<TFoot>
</ul>
<hr noshade>
</TFoot>

<!-- threads.html のおわり -->
<TIdxPgEnd>
</body>
<div align="right">
[<a href="$TFIRSTPG$">First page</a>][<a href="$TLASTPG$">Last page</a>]
$TPREVPGLINK$$TNEXTPGLINK$[<a href="index.html">Date Index</a>][<a href="
../index.html">Index</a>]
<address>by too@os.gulf.or.jp</address>
</div>
</html>
</TIdxPgEnd>
<!-- Thread index Rayout -->





ここまで準備ができれば、いよいよメールを流してみます。

うまくいけば $HOME/.procmailrc で指定した outdir に *.html ファイルが貯まっていくはずです。index.html ファイルをブラウザで見て、思った通りのソートになっていればOKです。

失敗したりで、アーカイブから削除したい場合には、outdir へ cd してから mhonarc -rmm [番号] で削除できます。この時の番号は、outdir でファイル名に付けられている連番です(メーリングリストのヘッダに振られている連番と必ずしも一致するとは限りません)。一番簡単なのは、ブラウザ上で削除したい文書へのリンク先を確認して、番号部分を指定すればよいみたいです。番号には 1-100 のような連続指定もできます。



HTML 化が完了すれば namazu のインデックスを作成します。namazu は MHonARC との連携機能があり、スレッド表示のためのファイルなどは自動的に検索対象から外してくれます。が、その前にMIMEヘッダデコードの不具合を解消するため、namazu についてくる mhonarc.pl を最新のものに更新しておきましょう。

アドレスが長いですが、この cvs-web へアクセスしてください。上のほうに download というのがあるので、ここからファイルを取って来ます。念のため、元の mhonarc.pl も残しておいてください。


準備ができたら、インデックスを作成する場所と権限に気をつけて(私の場合、/usr/local/apache/var/index の下に ml_zakky とかを作りました)、mknmz を実行します。

検索ページを前の例にならって作り、実行してみます。うまくいったでしょうか? メーリングリストが複数ある場合には、前のページでやった「複数インデックスでユーザにチェックボックスによりインデックスを選択」させるようなページを作ると効果的でしょう。

また、非公開型メーリングリスト(このサンプルで取り上げている zakky, ramram ML もそうです)の場合、過去のログが自由に Web から見えてしまったのでは不都合です。apache の BASIC 認証を組み合わせるというやり方が「zeSea-Bird Web Pages」の中で述べられています。この場合、MHonARC で生成した HTML ファイルと同じ場所に検索用HTMLを配しておくとよいと思います。


■ MHonARC 関係で参考にさせていただいたページ ■

・MHonARC 本家 http://www.mhonarc.org/

・MHonARC の日本語化 http://www.shiratori.riec.tohoku.ac.jp/~p-katoh/Hack/Docs/mhonarc-jp/index.html

・MHonARC 徹底解剖 http://www15.xdsl.ne.jp/~vfr/debian/namazu/howto-mhonarc.html

・procmail と MHonARC と kakasi と namazu でメーリングリストをWeb公開&検索 http://w3.itoh.net/namazu.html (procmail の設定について)

・Instration of sendmail http://griffon.gwits.net/freebsd/sendmail_dialup.html (fetchmail の設定について)

ページ作成者の方々に感謝いたします。

FreeBSD目次へ戻る