	HOOK を使ったカスタマイズ(カスタマイズ上級編)

------------------------------------------------------------
1	HOOKの概要

2	ユーザがHOOKなどで安全に使える関数 
2.1	ヘッダ関係の操作
2.2	%Envelope の操作
2.3	ファイルを読む
2.4	これらの関数を使う例 (本文へ注意をつけたす)

3	フックの一覧
3.1	$START_HOOK
3.2	$HEADER_ADD_HOOK
3.3	$DISTRIBUTE_START_HOOK
3.4	$SMTP_OPEN_HOOK
3.5	$DISTRIBUTE_CLOSE_HOOK (SMTP_CLOSE_HOOK)
3.6	$FML_EXIT_HOOK
3.7	$FML_EXIT_PROG
3.8	$MSEND_START_HOOK
3.9	$MSEND_HEADER_HOOK
3.10	$MSEND_OPT_HOOK
3.11	$REPORT_HEADER_CONFIG_HOOK
3.12	$COMMAND_HOOK (obsolete on to add new commands technique)
3.13	$MODE_BIFURCATE_HOOK
3.14	$COMMAND_FILTER_HOOK
3.15	$REJECT_COMMAND_FILTER_HOOK
3.16	$DISTRIBUTE_SUMMARY_HOOK
------------------------------------------------------------


1	HOOKの概要

HOOK (つりあげるもの)は fml の処理過程のあちこちに仕込まれているしかけ
です。これを使うことで、単なる変数で「◯◯をする／しない」を越えた
特殊な処理をすることができます。
＃業界によってはマクロというとわかる？

ようするに「割り込む」という行儀の悪いことをするわけです。
こういう例外的なことをするために

	perl で直接プログラムを書きます。
	fml の内部構造にある程度つうじていないといけません

ことが必要です。

HOOK 一覧は 3

HOOK で使うとよい関数 		2
	上級編(fml 内部関数) 	internals 10

ここでは主に HOOK とは何か？についてのリファレンスです。
いまのチュートリアルは各テーマごとに分かれているので、できるだけ
各テーマの中でHOOKの事例は研究することにします。

2	ユーザがHOOKなどで安全に使える関数 

2.1	ヘッダ関係の操作

GET_HEADER_FIELD_VALUE( header_field )

	現在の値を取り出す。

GET_ORIGINAL_HEADER_FIELD_VALUE( header_field )

	fml が最初にメールを受けとった時の元々の値を取り出す。

SET_HEADER_FIELD_VALUE( header_field , value )

	前述の GET_HEADER_FILED_VALUE() の対称性のために作った関数。
	ヘッダフィールドの値を特定にものにする。

	ようは DEFINE_FIELD_FORCED() と一緒だけど
	もうちょっと汎用的

2.2	%Envelope の操作

GET_ENVELOPE_VALUE( hash_key )

	%Envelope ハッシュのあるキーの値を取り出す

SET_ENVELOPE_VALUE( hash_key, value )

	%Envelope ハッシュのあるキーの値を設定する or 上書きする。

ENVELOPE_APPEND( hash_key, value )

	%Envelope ハッシュのあるキーに値をつけたす。
	つまり現在の内容の後にいれる。

ENVELOPE_PREPEND( hash_key, value )

	%Envelope ハッシュのあるキーに値をつけたすが、現在の内容の
	直前に挿入する。

2.3	ファイルを読む

GET_BUFFER_FROM_FILE( file )

	ファイルを読んで来てその値を返す。
	大きなファイルは読まない方がいいとおもうぞ

	$s = &GET_BUFFER_FROM_FILE( "$DIR/xxx" );

2.4	これらの関数を使う例 (本文へ注意をつけたす)

(2000/06/05 以降の fml-current)

$START_HOOK = q#
	my ($s) = &GET_BUFFER_FROM_FILE("$DIR/info");
	&ENVELOPE_APPEND('Body', &STR2JIS($s));
#;

ここで $DIR/info は /var/spool/ml/elena/info に展開される。
/var/spool/ml/elena/info というファイルを作りこの中に
    ◯◯◯ ＭＬの抜け方は ……… です。

などと書いておきます。過去のリリース、fml-stable および 2000/06 以前の 
current では %Envelope を直接いじってください。
3	フックの一覧

インタプリタなので(例えば config.ph に)フックを定義すれば適当な場所で
そのHOOKは評価され実行されます。

そのフックでちょっと複雑な設定やダイナミックなサーバの挙動の変更をした
りできます。config.ph で定義するのでMLが複数あってもMLごとに変更できる
わけです。一方 sitedef.ph で行なえばML共通のHOOKを仕掛けることができま
す。

3.1	$START_HOOK

評価されるタイミングは、
	ヘッダの各フィールドの切り出しは終っている。
	が、配送orコマンド本体を行なう前
である。

例: 配送前にもし #ではじまらない行が８行以上あれば、たとえ#ではじまる
行があっても普通のメールとおもうようにする。

$START_HOOK =q%
    if ($Envelope{'nlines'} - $Envelope{'nclines'} >= 8) {
	undef $Envelope{'mode:uip'};
    }
%;

3.2	$HEADER_ADD_HOOK

ヘッダに”新たに”つけくわえるフィールドをかいてカスタマイズするための
フック。

現在では $body という変数はこのためだけに使われる。
＃注意：昔は違った

例(昔のやり方):

    $HEADER_ADD_HOOK = q#
	$body .= "X-Baycity-Weather: Mizumaki\n";
    #;

ヘッダに X-Baycity-Weather: Mizumaki とつけくわえる(意味不明(笑))
現在では同じことは例えば 

	&DEFINE_FIELD_FORCED("X-Baycity-Weather","Mizumaki");

のような関数でできる。

例２:

Message-ID: <19950518.01905.Elena.Lolobrigita@Baycity.asia>

$HEADER_ADD_HOOK = q#
   $body .= "Message-ID: ".
	sprintf("<%4d%02d%02d.%05d.%s>\n", 1900 + $year, $mon + 1, $mday, $ID, 
	"Elena.Lolobrigita@Baycity.asia");
#;

3.3	$DISTRIBUTE_START_HOOK

配送を始める関数に入った時に最初に評価されるHOOK

3.4	$SMTP_OPEN_HOOK

配送時にはこのフックの後 Sendmail へ渡すヘッダの処理が始まります。ここ
で強制的かつダイナミックにヘッダの内容を変えたりすると効果的です。単に
ヘッダの各フィールドを書き換えるのなら &DEFINE_FIELDうじゃうじゃ 関数
シリーズが用意されています。そちらを使うのがよいでしょう。
SMTPという名前がついていますがSMTP汎用ではありません。歴史的な名前です。
See also: header_rewrite 5.1 header_rewrite 5.2 

例:	Reply-To: フィールドをML自体へ強制書き換え
	&DEFINE_FIELD_うじゃうじゃ以外にも別解はいくつかあるが解1

$SMTP_OPEN_HOOK = q#
	$Envelope{'fh:reply-to:'} = $MAIL_LIST; 	
#;

例2:	Precedence: を bulk へ

$SMTP_OPEN_HOOK = q#
	$Envelope{'h:Precedence:'} = 'bulk';
#;

Precedence: に関しては実は config.ph で $PRECEDENCE = 'bulk'; でＯＫで
す。

3.5	$DISTRIBUTE_CLOSE_HOOK (SMTP_CLOSE_HOOK)

$DISTRIBUTE_CLOSE_HOOK は配送が終った後でかつまだロックされている状態
で実行されます。具体的には &Distribute; を離れる直前に実行されます。
$SMTP_CLOSE_HOOK は昔の名前です。

3.6	$FML_EXIT_HOOK

fml.pl が最後に実行する フック。このときすでに 『排他制御の lock が解
除されている』いることに注意して下さい。

3.7	$FML_EXIT_PROG

In the last of fml.pl, FML starts $FML_EXIT_PROG as a new process by
exec(2) system call (precisely speaking via exec(3)).

3.8	$MSEND_START_HOOK

After msend.pl is initialized, msend.pl evaluates this hook in the
begging of the main function. See msend.pl internal.

3.9	$MSEND_HEADER_HOOK

In the header generation when sending digest mail creation time.

3.10	$MSEND_OPT_HOOK

msend.pl evaluates $MSEND_OPT_HOOK in the &MSendInit.

例:
デフォールトでは、まとめおくり や mget の時の Subject は

Subject: Matomete Send [PLAINTEXT(UNIX FROM)] (1/1) (Elena Lolobrigita ML)

のようになります。が    ↑↑↑↑ここのところの文章がきにいらないので
OVERWRITE したいときは、

$MSEND_OPT_HOOK = q%
    $MSendOpt{'#uf'} = "#Overwritten... $MSendOpt{'#uf'}";
%;

このように、
		$MSEND_OPT_HOOK 
に 連想配列の 

	#モード の値が #説明の文章

のようにかいてください。なにをやってるのかは、libutils.pl の中の
sub MSendModeSet  という関数を見るとわかるとおもいます。
See also: digest 2.6 

3.11	$REPORT_HEADER_CONFIG_HOOK

SMTP 配送ライブラリへ渡す直前に評価されるフック。

3.12	$COMMAND_HOOK (obsolete on to add new commands technique)

現在のfmlでは %Procedure に登録していない関数を実行しようとするとエラー
になります。そのため $COMMAND_HOOK によるコマンドの実行はできません。

3.13	$MODE_BIFURCATE_HOOK

モードが分岐する関数の中で呼ばれるHOOK。ほとんど先頭で呼ばれる。実際に
は sub ModeBifurcate を見ないと何だか分からないだろう。

3.14	$COMMAND_FILTER_HOOK
See also: filter 4.1 

3.15	$REJECT_COMMAND_FILTER_HOOK
See also: filter 4.1 

3.16	$DISTRIBUTE_SUMMARY_HOOK

$DISTRIBUTE_SUMMARY_HOOK = q#
	&Append2(sprintf("%s [%d:%s] %s", 
			 $Now, $ID, substr($From_address, 0, 15), $s),
		 $SUMMARY_FILE);
#;

このHOOKが評価される時 $s は subject になっています。


		INDEX

$COMMAND_FILTER_HOOK                       ...   3.14 
$COMMAND_HOOK                              ...   3.12 
$DISTRIBUTE_CLOSE_HOOK                     ...   3.5 
$DISTRIBUTE_START_HOOK                     ...   3.3 
$DISTRIBUTE_SUMMARY_HOOK                   ...   3.16 
$FML_EXIT_HOOK                             ...   3.6 
$FML_EXIT_PROG                             ...   3.7 
$HEADER_ADD_HOOK                           ...   3.2 
$MODE_BIFURCATE_HOOK                       ...   3.13 
$MSEND_HEADER_HOOK                         ...   3.9 
$MSEND_OPT_HOOK                            ...   3.10 
$MSEND_START_HOOK                          ...   3.8 
$REJECT_COMMAND_FILTER_HOOK                ...   3.15 
$REPORT_HEADER_CONFIG_HOOK                 ...   3.11 
$SMTP_CLOSE_HOOK                           ...   3.5 
$SMTP_OPEN_HOOK                            ...   3.4 
$START_HOOK                                ...   3.1 
コマンドのカスタマイズ                     ...   3.12 
