MH のどうでもいいような趣味の講座


「Mh中級者以上向け〜どうでもいい(笑)ような趣味の講座」


◎第5回: slocalを張ろう!・その1

From: hayashi@atlas10.kuic.kyoto-u.ac.jp (Haruhisa Hayashi)
Subject: Mh-guide#05
Organization: Industrial Chemistry, Kyoto University, Kyoto, Japan.
Date: Thu, 14 May 1992 13:41:44 GMT

メールが山のように降ってくるようになると、読む時間も ままならない(^^;;)。しかも、/var/spool/mail/$USERな どの自分のメールスプールが、ちょっと inc しないと膨 れあがり、破裂する(!)危険もある。そうでなくても、 /var が比較的小さい場合がおおい。また、xpbiffを立てて いる場合や、chsrcに、

「set mail=(60 /var/spool/mail/$USER)」

などと、設定してある場合は、「ぴっぴぴっぴ」と五月蝿い ことだろう。そこで、

『来たメールを自分のメールフォルダーに自動的に分類して放り込む』

ことが出来るのである。それは、mhook の slocal コマンドである。

# しかし、この slocal コマンドについての説明は、「man mhook」 する位しかない。しかも、ちょっと書き間違えると、メールが 「迷子」になったり、「ロスト」したりしてしまう、危険なコマン ドでもある。

## mh-6.8.X では man slocal で大丈夫:-)。

そこで、私の失敗と現在の設定とを、読んで貰うだけでも、何らかの 役には立つと思うので、書いておく。

「slocal」を用いるには、「~/.forward ファイルの書き換え」と、 「.maildelivery」の設定の2つの手順で行なわれる。

~/.forward ファイルの書き換え」
「そのアドレスに届いたメールを別のところに転送する、その アドレス」を書いたファイルである。 このファイル中に、shでコマンドを作動させることも可能である。 (参照、vacation コマンド)

~/.forward
::>> "| /usr/local/lib/mh/slocal -user hayashi"

こうすることで、来たメールを、「|」で slocal に喰わせることが 出来る。 (尚slocal起動の際、上述のようにオプションで user を指定しておくこと)

# 勿論、.maildelivery の設定後に変更すること!!。

slocal は、~/.maildelivery ファイルに記述してあるように動作する、


ちなみに slocal のファイルロックは甘いので、 「一度に大量のメールが来ると、メールがロストすることもある」 と言われていますので、気をつけましょう。

## 但し、残念(?)乍ら、私は今までに一度も経験したことはありませんが:-)
## 1日50〜100通位届くのが3年以上続いていますが。
## ちゃんと mail のログ(smtp connection)を tail -f で常時見てますし:-)
## まぁ、OSの flock/lockf の問題じゃないかと思いますが:-)
それと、.mh_sequence が勝手に:-)更新されるので、 mh等で未読メールを読んでいるのと、変にぶつかったりすることも、 稀にあるようです。


◎第6回: slocalを張ろう!・その2

From: hayashi@atlas10.kuic.kyoto-u.ac.jp (Haruhisa Hayashi)
Subject: Mh-guide#06
Organization: Industrial Chemistry, Kyoto University, Kyoto, Japan.
Date: Thu, 14 May 1992 14:33:13 GMT

「.maildeliverly ファイルの設定。」
このファイルの内容によって、その到着したメールを処理する。
「#」は、注釈行である。

.maildelivery ファイルの各行のフォーマットは、
field pattern action result string
である。それぞれの意味は…(man 参照)、

field:
この field のパターンをサーチする。
pattern:
その特定の field に、一致する文字列。
action:
メッセージ配送のために行う動作。
file or >:
この後に書いたファイルに、メッセージが追加される。 ファイルに書き込むとき、「Delivery-Date: date」と いう、ファイルに追加された日時を示す行が追加される。
pipe or |:
以後に続くコマンドに、メッセージを標準入力で pipe する。 (Bourne shellが起動される)
シェルに引き渡される前に、内蔵変数が展開される。
$(sender): メッセージの return address $(address): 受取人に配送するのに用いられた address $(size): メッセージの byte 数 $(reply-to): メッセージの "Reply-To:" か "From:" $(info): miscellaneous out-of-band information
qpipe or :
pipe に似ている。しかしシェルからの assistance なしに、 内部変数を展開後、コマンドを直接実行する。
destroy:
この動作は常に success する。
result:
どのように作動するべきなのかを、示している。
ということである。各行の解説は…、

::>> # from postmaster
::>> From postmaster | A "/usr/local/lib/mh/rcvstore +Pm"
::>> To postmaster | A "/usr/local/lib/mh/rcvstore +Pm"

ヘッダの「From」行か「To」行が、「postmaster」だったら、 mh附属のrcvstoreというユーティリティーツールで、「Pm」という フォルダ(但し、.mh_profileで 「Path:Mail」としてあれば、 ~/Mail/Pm となる)に放り込む。

んで、「result」が「A」なので、このPmに放り込まれたメールは、 .maildelivery の他の検索項目に対し、「このメールは既に配送さ れた」という扱いになる。

::>> # for Maling List
::>> X-Ml-Name 98ml | A "/usr/local/lib/mh/rcvstore +98"

これも上記と同様。 ML(Mailimg List)から来るメールの場合は、メールヘッダに識別 し易い特別な「行」がつけてあることが多い。例の場合では、ヘッダ に「X-Ml-Name: 98ml」という行が付けられたメールが送られてくる から、ここをキーワードにして、検索を行なっている。

::>> # Personal
::>> From hal | ? "/usr/local/lib/mh/rcvstore +Hal"

さて、ここも同様。「hal」さんから来るメールは、ヘッダに 「From: ... hal ..」とついているので、これをキーワードにして 検索をしている。 しかし、「result」が「?」である。 これは、上の98mlに「hal」さんも加入しているので、98mlのメール のうち、「hal」さんの出したメールに、「From: ... hal ...」と ついてしまっている場合、ここも「A」としておくと、98mlの「hal」 さんのメールも、「Hal」に放り込まれてしまうのである。 (つまり届いた1通が2つのフォルダーに放り込まれる)

そこで、「?」にしておくと、「配送されていないメールについてのみ、 動作を行なう」のであるから、98mlでのメールは「Hal」には放り込まれ ないで、「Hal」さんからの直接のメールのみが、放り込まれるのである。

::>> # default
::>> default - | ? "/usr/local/lib/mh/rcvstore +inbox"

設定に最低限必要なのは、最後の1行だけである。 つまり上記以外のメールは、「inbox」に放り込む、という設定である。

# 注意すべきは、パイプで起動されるのが「bourne shell」であり、 コマンドやファイルなどには、きっちり絶対パスを書いておかないといけない、 ってことと、届いたメールは標準入力として渡される、ということ である。

ということでこの.maildelivery ファイルを上手に利用すれば、 届いたメールに対してさまざまなactionをすることが可能である。

もちろん例で説明した以外にも、メールの差出人によって、「お返 事メールを自動的に出す」とか、「全然読まずに捨ててしまう:-P」 とか、「メールフォルダーに放り込まずに、ファイルとして落す」 とかが出来ます。いろいろ試してみて下さい。

# で、この.maildelivery ファイルを間違って書いていると、メール がロストとしたりするので、テストの間は、~/.forwardを

::>> \hayashi, "| /usr/local/lib/mh/slocal -user hayashi"
と、普通に配送するのと、Mhに喰わすのと、2つにフォワードして テストを行なうとよい。

--
/* はやし☆はるひさ (hayashi@kuic.kyoto-u.ac.jp) 京大・分子・中西研 */
多少改定 10May1995 by はやし はるひさ hayashi あっとまーく chem.eng.himeji-tech.ac.jp


えーと、.maildelivery が合っているかどうか判らないうちに、 .forward を書き換えてしまうのは非常に危険です。 まず、.maildelivery を書いて、コマンドラインから

% cat メールファイル | /usr/local/lib/mh/slocal -verbose -user hayashi

して試しましょう。verbose オプションをつけると、詳細情報が帰ってきます。

また、気をつけねばならないのは、.forward で プログラム(slocal)に メールを喰わせている、という点です。これにより、 sendmail.cf 中の ローカル配送指定の Mlocal でなくて、Mprog の行が使用されます。

つまり、届いたメールを jis から euc に変換しているサイト等では、 ローカル配送の際に、漢字コード変換 filter を噛ませているのですが、 slocal を使用しつつ、そういう操作を必要とする場合は、なんらかの フィルターを自分で slocal の前に噛ます様に工夫して下さい。

例えばうち(今のとこね:-))の場合、日本語 Solaris2.3 に 日本語Openwindows 3.3 で、日本語 vi を使う人が居る(;_;)ので、ローカル配送は、j2email という jis->euc 変換フィルタ+個別配送プログラムを使用しています。 しかし、slocal はプログラム起動ですので、下の Mprog 行、つまり /bin/sh が起動されます。(のでslocalでのメールは jis のまま届きます)

## 私一人、X11R6+twm+kterm+mule+mh だもんなぁ…(愚痴)。


◎第7回: slocalを張ろう!・その3

From: hayashi@atlas10.kuic.kyoto-u.ac.jp (Haruhisa Hayashi)
Subject: Mh-guide#07
Organization: Industrial Chemistry, Kyoto University, Kyoto, Japan.
Date: Thu, 14 May 1992 14:56:39 GMT

ってことで、slocalが張れてしまいました(笑)。
これで届いたメールは自動的に分類され、メール フォルダーに放り込まれるんだな。

で、これで、/var/spool/mail の個人メールスプール は、常に 0 のままで、/var の容量に影響を与えないで 良いのだけれど、こんどは、自分のディレクトリが 増えていきます。勿論このことはよ〜く気をつけるように。

で、届いたのはいいものの、さて、どうやって 「メールが届いた」ことを知ることが出来るんだろうか…。

そこで、.mh_profile に設定した 「Unseen-Sequence: unseen」 がここで効いてくるのである。これを設定すると、各フォルダー の .mh_sequences に、

::>> unseen: 1-6

とかいうように、未開封のメールを記録してくれるんだな。 こいつを grep してやれば、いいわけだ。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- um.sh

#!/bin/csh -f
#
#	um.sh -- scaning Unseen Mails.
#	   Original: by Haruhisa Hayashi 
#	   Modified: by Katsumi Ohta 
#
onintr brk

# public setting
set fname_pth=`mhpath +`
set fname_dir=`folders -fast`
set fname_seq=.mh_sequences
set seq_name=`grep Unseen-Sequence: $HOME/.mh_profile | sed -e 's/^.*: //'`
#
set mhform_inbox="unseen2.form"
set mhform_other="unseen1.form"

@ unseen_num = 0

foreach folder ($fname_dir)
    grep $seq_name $fname_pth/$folder/$fname_seq >& /dev/null
    if ($status == 0) then
	echo "<< Unseen Mail >> in +"$folder
	if ($folder == "inbox") then
	    set mhform = $mhform_inbox
	else
	    set mhform = $mhform_other
	endif
	scan +$folder $seq_name -form $mhform | tee -a /tmp/scan.$$
    endif
end

if (-f /tmp/scan.$$) set unseen_num = `wc -l < /tmp/scan.$$`

switch ($unseen_num)
    case 0:
        echo " You've already seen all of your mail."
        breaksw
    case 1:
        echo " You have only one unseen mail."
        breaksw
    default:
        echo " You have $unseen_num unseen mails."
	breaksw
endsw
brk:
rm -f /tmp/scan.$$
exit 0;
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

um.sh は、私が書き殴って(笑)、某友人が汎用に書き直してくれた シェルプログラムである(→ um.sh を get )。 未開封メールが、どのフォルダーに何通あるか表示してくれる。

grep するんだが、その前に……、

::>> set fname_pth=`mhpath +`

で、Mhのメールパス(つまり .mh_profileで指定した「Path」)を 環境変数としてgetしている。

::>> set fname_dir=`folders -fast`

これは、メールフォルダーの名前を get している。

::>> set seq_name=`grep Unseen-Sequence: $HOME/.mh_profile | sed -e 's/^.*: //'`

ここでは、Unseen-Sequence として、何の文字を使用しているかを getしている。(私の場合、「unseen」である)

# このように一般性を持たせると、実行速度が遅くなるので、 最初から判っているものは、直接与えておくほうが速い。

::>> # private setting
::>> set fname_pth=/home/usr2/hayashi/Mail
::>> set fname_dir=( inbox 98ml Hal Postmaster )
::>> set seq_name=unseen

と、上記の部分を置き換えている。

あとは、

::>> set mhform_inbox="unseen2.form"
::>> set mhform_other="unseen1.form"

では、「inbox」を見る時と、他のフォルダーを見る時では、 使用するmh-formatファイルを変更しているだけである。 (別に同じものでもいいし、さらに拡張しても可能である。)

# ま、適当に改良してね(^^;;)。

さてさて、これで slocal も張れたことだし、ま、一通りのことは 出来るとおもうけどね。 あとは、色々自分で試して下さい。

--
/* はやし☆はるひさ (hayashi@kuic.kyoto-u.ac.jp) 京大・分子・中西研 */
多少改定 10May1995 by はやし はるひさ hayashi あっとまーく chem.eng.himeji-tech.ac.jp


ということで:-)、上記した um.sh は、友人の手によって perl に書き直されました。この方が速いです(→ um.pl を get )。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- um.pl

#!/usr/local/bin/perl
#	um -- scanning Unseen Mails.
#	   Original: by Haruhisa Hayashi 
#	   Modified: by Katsumi Ohta 
#	um.pl
#	   Original: by KAWAMOTO Yosihisa 
$HOME = $ENV{'HOME'};
$MH   = $ENV{'MH'};
# private setting
 $path       = "$HOME/Mail";
 $unseen     = 'unseen';
 @folders    = split(/ /, 'inbox News Postmaster 98ML');
 $ignores    = ' alt comp fj jp ku rec ';
 $form_inbox = 'unseen2.form_mime';
 $form_other = 'unseen1.form_mime';
# public setting
$MH = "$HOME/.mh_profile" if ($MH eq '');
if ($path eq '' || $unseen eq '') {
    open MH || die "Do you use MH??\n";
    while () {
	$path   = "$HOME/$1" if ($path eq '' && /^Path: (.*)$/i);
	$unseen = $1 if ($unseen eq '' && /^Unseen-Sequence: (.*)$/i);
    }
}

@folders = grep(-d && s/.*\///, <$path/*>) if (0+@folders == 0);
$mh_seq  = '.mh_sequences';
$unseen_num = 0;
foreach $folder (@folders) {
    next if ($ignores =~ / $folder / || ! -d "$path/$folder");
    open(MH_SEQ, "$path/$folder/$mh_seq") || next;
    @_ = ;
    if (0+grep(/^$unseen: /, @_) > 0) {
	print "<< Unseen Mail >> in +$folder\n";
	if ($folder eq 'inbox') {
	    $form = $form_inbox;
	} else {
	    $form = $form_other;
	}
	$scan = "scan +$folder $unseen";
	$scan .= " -form $form" if ($form ne '');
	if (open(SCAN, "$scan |")) {
	    while () {
		print;
		$unseen_num++;
	    }
	    close(SCAN);
	}
    }
    close(MH_SEQ);
}
if ($unseen_num == 0) {
    print " You've already seen all of your mail.\n";
} elsif ($unseen_num == 1) {
    print " You have only one unseen mail.\n";
} else {
    print " You have $unseen_num unseen mails.\n";
}
exit 0;
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

単に folder を探して(.mh_profile にある Path: オプションの ディレクトリの下を全部掘ります。時間がかかるので、$ignores に 指定すれば、そのメールフォルダは無視します)、それぞれのメール フォルダについて、.mh_sequence から unseen を見つけ、 inbox フォルダなら unseen2.form_mime で、 他のフォルダーなら unseen1.form_mime (共に Path: のディレクトリに。) という mh-format ファイルで scan しているだけです。

um.sh と同じく、一般性を持たせると、実行速度が遅くなるので、 最初から判っているものは、直接与えておくほうが速い。 つまり、public setting を全部コメントアウトし、 @folders に、調べたいメールフォルダを全部記述しておくとよい。


[29Feb1996] .maildelivery のデバッグについて

ってな手法があります(参照 MH FAQ 07.05)。色々試してみて下さい。
目次へ 第1回へ 第3回へ 第5回へ
© Haruhisa Hayashi 1992,1995
改訂(文章の大幅書換+frame化)版 [21Mar1997]は こちら
by はやし はるひさ hayashi あっとまーく laic.u-hyogo.学術.日本