[PREVIOUS CHAPTER] [NEXT CHAPTER]
3 事例集

3.1	Reply-To: が携帯電話のあどれすで困る

Q: 携帯電話から送られるメールで Reply-To: が携帯電話のアドレスのために
配送されたメールが Reply-To: MLになりません。

A: 『常に強制的に Reply-To: MLにしてしまう』ことで解決になるのなら

/var/spool/ml/elena/cf (PATHは適当によみかえてください) の 
LOCAL_CONFIG という行の後に

   &DEFINE_FIELD_FORCED('reply-to', $MAIL_LIST);

と書いて config.ph を作り直して下さい。作り直すのは例えば
   % cd /var/spool/ml/elena/cf
   % makefml update-config.ph elena


3.2	fmlでのwelcomeメールのsubjectを日本語にする


fml-support: 07219

MLのHOMEにあるcfというファイルの最後(LOCAL_CONFIGという行より後)に

$START_HOOK = q#

	&use('MIME');
	$WELCOME_STATEMENT  = "ようこそここへ、うふふ";
	$WELCOME_STATEMENT  = &STR2EUC($WELCOME_STATEMENT);
	$WELCOME_STATEMENT  = &mimeencode($WELCOME_STATEMENT);

#;

と呪文を書いておいて、その場所で

make config.ph

で config.ph をつくりなおす


3.3	登録のconfirmationメールのsubjectをいじる

   "Subscribe confirmation request $ML_FN";

のような subject を自由にカスタマイズするのはちょっと面倒です。という
のは状態によってさまざまなsubjectに変わるので、それは今関数のなかに埋
め込まれてしまっています。

XXX 本来は messages/$LANGUAGE/ に押し出して外のファイルから定義を
XXX 変更できるようににするべきでしょうね。外側からそのてのフレーズをい
XXX じれるようにする作業はエラーとかは一通り終ってるけどそれ以外は...

例: 現状ではたぶんこんなんをかかないといけないす( not tested )

$CONFIRM_REPLAY_SUBJECT_FUNCTION = 'myGenConfirmReplySubject';

sub myGenConfirmReplySubject
{
    local(*e, *cf, $mode) = @_;
    local($s);

    if ($debug_confirm) {
	local(@c) = caller;
	&Log("GenConfirmReplySubject<$c[2]>: $mode") if $mode ne 'Default';
    }

    if ($mode eq 'Default') {
	$s = "Subscribe request result $ML_FN";
    }
    elsif ($mode eq 'Confirm::Confirmed') {
	$s = $CONFIRMATION_WELCOME_STATEMENT || $WELCOME_STATEMENT;
	# $s = "Newly added $From_address $ML_FN";
    }
    elsif ($mode eq 'Confirm::Error') {
	$s = "Subscribe with confirmation error $ML_FN";
    }
    elsif ($mode eq 'Confirm::GenPreamble') {
	$s = "$ML_FN登録の確認";
	$s = &STR2EUC($s);
	# $s = "Subscribe confirmation request $ML_FN";
    }
    elsif ($mode eq 'IdCheck::syntax_error') {
	$s = "Subscribe confirmation errror $ML_FN";
    }
    elsif ($mode eq 'Confirm::expired') {
	$s = "Subscribe confirmation expired $ML_FN";
    }
    elsif ($mode eq 'BufferSyntax::Error') {
	$s = "Subscribe confirmation errror $ML_FN";
    }
    elsif ($mode eq 'BufferSyntax::InvalidAddr') {
	$s = "Subscribe confirmation errror $ML_FN";
    }
    else {
	&Log("GenConfirmReplySubject: unknown mode [$mode]") if $debug_confirm;
	"Subscribe request result $ML_FN";
    }
}


3.4	Received: を残す

FML 2.2 以降では

    $SKIP_FIELDS  = 'Return-Receipt-To';

です。makefml configのメニューにあります(中身はこれ)。
#2.1 では子文字じゃないとだめかも unshift(@HdrFieldsOrder, 'received');
#この場合一行だけ Received ではなく received になってしまってちょっ
#と情けないかも知れませんが…
#RFC822 としては大文字小文字は関係ないので問題はない。カッコ悪いだけ;-)


歴史的に「サーバで受けたところまではOKなんだから、管理者が責任を持って、
ユーザにはMLサーバからユーザまでの配送分を見せれば十分だろう(余計なも
のは見せてもらわない方が幸せだろう)」という思想に基づき、デフォールト
では Received: はつけていません。またそれは too many hops によるエラー
を避けるためにも有効です。

念のためログを取るためには

	&DEFINE_MODE("stdinlog");

というモード指定があります。これは入力を日毎にログファイル(var/logの下)
に残しておきます(溜る一方なので注意してね)。

なお Posted: (user が出した時間)と Date: (サーバが配送した時間) の違い
を見るとサーバにたどり着くまでの時間差(Network 的にどのくらい遠いか?)
がわかります。
3.5
3.5

FYI: fml-support's ML Count: 01816, 01821 for the discussion

3.5	Date: Type ($DATE_TYPE)

fml 2.2 の $DATE_TYPE のデフォールト値は original-date 、
fml 2.1 は received-date です。

	未定義ならそのまま(互換性のため) received-date と同じになる

	original-date
		Date:	
		Posted: なし

	received-date
	received-date+posted
		Date:	FMLがメールを受けとった時間
		Posted:	元のメールそのままのDate:

	received-date+x-posted
		Date:	FMLがメールを受けとった時間
		X-Posted:	元のメールそのままのDate:

	received-date+x-original-date
		Date:	FMLがメールを受けとった時間
		X-Original-Date: 元のメールそのままのDate:

	distribute-date
	distribute-date+posted
		Date:	FMLがメール配送を始めた時間
		Posted:	元のメールそのままのDate:

	distribute-date+x-posted
		Date:	FMLがメール配送を始めた時間
		X-Posted:	元のメールそのままのDate:

	distribute-date+x-original-date
		Date:	FMLがメール配送を始めた時間
		X-Original-Date:	元のメールそのままのDate:


distribute-date は Date: と X-Mail-Count: が同じ順番になるためのもので
す。ださいMUAでソートする時だけは便利という説があります。

3.6	コマンドの結果やユーザへのメッセージのヘッダのカスタマイズ
../internals 7.0

コマンドの結果やユーザへのメッセージのメールヘッダは

	$Envelope{'GH:field:'} 

で変更できます。GH というキーワードなのは SMTP Library の 
GenerateHeader() という関数内で使われるためです。ヘッダフィールドの並
び順は @HdrFieldsOrder の順番です。

Example:

コマンドの結果のメールの From: を特定のアドレス(および signatureつき等)
に変えたい場合。なお通常は From: は $MAINTAINER です。

	$Envelope{'GH:From:'} = "uja@aoi.chan.panic (AOICHAN PANIC)";

From: $MAINTAINER に限っては $MAINTAINER_SIGNATURE で signature をつけ
ることはできますが、まぁ形を気にするなら↑の方法で直接定義した方がより
よいでしょう。Dynamic に補正する必要がある場合は 
$REPORT_HEADER_CONFIG_HOOKで定義するとよい。
../hooks 3.11

3.7	コマンドメールの結果のメールの Reply-To: を変更する


	&DEFINE_FIELD_OF_REPORT_MAIL('Reply-To', "Your Reply-To Address");

は次の設定と同じです。@HdrFieldsOrder 内で定義されているフィールドに対
して設定できます。

	$Envelope{'GH:Reply-To:'} = "Your Reply-To Address";

where the field is one of fields defined in @HdrFieldsOrder.
Backward compatibility で残っている変数が

	$FORCE_COMMAND_REPLY_TO = "address-you-want-to-use";

です。実際には $Envelope{'GH:Reply-To:'} への代入と全く同じです。

3.8	Subject Tags; Subject: に (Elena 100) などのタグをつける

FMLのデフォールトのデザインポリシーは「Subject: はいじらない。本来メー
ルソフトが好きな形にフォーマットするものをサーバ側でフォーマットを押付
けるべきではない」「有効に使いもしないのに Subject:の本体の情報を減ら
すタグはつけるべきではない」というものです。
#注意:この問題は本来はメールインターフェイスプログラムが賢いか?
#否か?という問題に還元されるべきものです。

Subject: にタグをつける時は$SUBJECT_TAG_TYPE という変数にタイプを設定
します。ちなみに makefml config で設定できます。

  $SUBJECT_TAG_TYPE		Subject: での形

	TYPE    Subject Example

		Subject: 	 	(DEFAULT, FML recommends this)
	(:)	Subject: (Elena:100)
	[:]	Subject: [Elena:100]	(hml 1.6 compatibility)
	( )	Subject: (Elena 100)
	[ ]	Subject: [Elena 100]
	(,)	Subject: (Elena,100)
	[,]	Subject: [Elena,100]
	()	Subject: (Elena)
	[]	Subject: [Elena]
	(ID)	Subject: (100)
	[ID]	Subject: [100]

[解説]
設定すると config.ph の中では次のような形に設定されています

	$SUBJECT_FREE_FORM = 1;
	$BEGIN_BRACKET     = '(';
	$BRACKET           = 'Elena';
	$BRACKET_SEPARATOR = ' ';
	$END_BRACKET       = ')';
	$SUBJECT_FREE_FORM_REGEXP = "\\($BRACKET \\d+\\)";

と定義すると (Elena 100) の形になり、Reply のメールの (Elena 99) をは
ずし新しい (Elena 100) をつけるようになります。

Another example: Subject: [Elena 100]

	$SUBJECT_FREE_FORM = 1;
	$BEGIN_BRACKET     = '[';
	$BRACKET           = 'Elena';
	$BRACKET_SEPARATOR = ' ';
	$END_BRACKET       = ']';
	$SUBJECT_FREE_FORM_REGEXP = "\\[$BRACKET \\d+\\]";

[捕捉]
$CFVersion 3 以前にあった $SUBJECT_HML_FORM は config.ph が CFVersion
3 以前のものだと判定された場合は内部で$SUBJECT_TAG_TYPE = "[:]"; へ変
換されます。現在の設定ではすでに無効な変数です。

3.9	Subject: の成形 ([Elena:ID] フォーマットを抜く) [obsolete]

[backward compatible, obsolete]
歴史的意味しかないので古いconfig.phを使っているならともかく、
新たに使うことはないはずです(使わないように)。

	$STRIP_BRACKETS = 1;

とすると Subjectから [ML:fukachan] みたいな部分をカットする。これは 
Subject: [Elena:ID] の形で配送するための前処理です。

3.10	TAGの [Elena:00001] の五桁の数字をN桁に変更

	$SUBJECT_FORM_LONG_ID (5; the number > 1)

はSubject:のTAGの数字部分の桁数を定義する。5(桁)がデフォールトだが 
$SUBJECT_FORM_LONG_ID 桁にする。$SUBJECT_FREE_FORM 使用時に有効な変数。
2 以上

注意:
かつて

	5桁がデフォールトだが $HML_FORM_LONG_ID 桁にする。
	$SUBJECT_HML_FORM = 1; の時にのみ有効。

という設定もありました。現在では $SUBJECT_FORM_LONG_ID を使うべき。
$CFVersion 3 以前にあった $HML_FORM_LONG_ID は config.ph が CFVersion
3 以前のものだと判定された場合は内部で $SUBJECT_FREE_FORM_LONG_ID; へ
代入変換されます。現在の設定ではすでに無効な変数です。

3.11	TAGの [Elena:00001] の 0 パディングをなくす

	$SUBJECT_FORM_LONG_ID = -1;

[注意] 昔は
	$HML_FORM_LONG_ID = -1;
も有効でしたが、今はありません。

3.12	元々の Message-ID を配送に使う

	$USE_ORIGINAL_MESSAGE_ID = 1; (default)

とすると元々メールにあった Message-ID を保存してヘッダにつけます。
これがデフォールトの挙動です。

References: fml-support ML's Count: 02687 あたりを参照

References: fml-support: 02687

original で妙な pattern の Message-ID を使われてて、ちゃんと detect で
きないとかあると嫌ね#そうそうあるとはおもえないのだが

という可能性もある一方 #ばぐってるperlとかね〜

fml 自体がつける場合、キャッシュテーブルの有効な大きさが半分になってし
まふというのがあるので、元々を使う方が有効な大きさは増える。
ループが発生する場合にどのくらい未来まで世界線をたどればいいのかは不明
なので統計的な議論はできない。

自分が自分に送るとかそういうのなら一瞬でループにはいるのでまず間違いな
く検出するはずという場合が多いという仮定が正しいならどちらのやり方でも
大差はないはず

という論理になるような気がする。

true ?

3.13	ML 独自の Message-ID フォーマット
../hooks 3.2

これは
	&DEFINE_FIELD_FORCED('Message-Id', "適当なID");
で解決ですが。HOOKを使うやり方も書いておきます。

Message-ID: uja@aoi.chan.panic は次のように config.ph にでも書けば 
$body の内容が @HdrFieldsOrder 中の : body: で展開されます。そのため
HOOKを使うなら @HdrFieldsOrder 中の : body: を切ってはいけません。

&DEFINE_FIELD_FORCED('Message-Id', "uja$$\@aoi.chan.panic");

は次と同じ

$HEADER_ADD_HOOK = q#
   $body .= "Message-ID: uja@aoi.chan.panic\n";
#;

Another Example:
Message-ID: <19950518.01905.Elena.Lolobrigita@Baycity.jp>

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

3.14	宇宙歴 (外国TVシリーズMLで使ってます:-)

config.ph で $APPEND_STARDATE = 1; とすると宇宙歴がつきます:-)

	Date: Fri, 19 May 95 22:31:09  JST
	From: "No.6 Fukachan" <fukachan@phys.titech.ac.jp>
	Subject: Re: Nantonaku Leonard Nimoy 
	To: enterprise@phys.titech.ac.jp (Foreign TV Series ML)
	X-ML-Name: Prisoner
	X-Stardate: [-31]5697.8164 

	…body…

みたいになります。スタートレックFAQ に C program がのっていますが、
libstardate.pl はその perl 版です。


3.15	一つのメーリングリストに複数の投稿用アドレス

何の意味があるのかは聞かないでください(笑)
例:
Elena@phys.titech.ac.jp というMLで

	Elena@phys.titech.ac.jp
	Anna@phys.titech.ac.jp

の両方を投稿可能にする。設定したいアドレスを config.ph で 
@MAIL_LIST_ALIASES という配列にずらずら書いて下さい。

  @MAIL_LIST_ALIASES = ('Elena@phys.titech.ac.jp', 
			'Anna@phys.titech.ac.jp'
		    );

なおHOOKの設定はもう必要ありません。&FixHeaders の中で書き換えは行なわ
れます。

その複数のアドレスを(ループチェックに使うために) @MAIL_LIST_ALIASES が
必要です。配列の先頭は $MAIL_LIST です。

こうすると Elena になげても Anna に投げても同じMLと見なし、

	$MAIL_LIST 

をその投げた方のアドレスに設定します。その副作用として

	To: と Reply-To:

がそのアドレスになります。

注意: @PLAY_TO, $Playing_to は昔の変数名です。この変数は 
compatibility のため自動的に @MAIL_LIST_ALIASES に代入されます。
# libcompat.pl にBackward compatibility のためのコードがありますが…

3.16	X-ML-Info: の内容を指定する

	&DEFINE_FIELD_FORCED('x-ml-info', "書きたいこと");

で強制的に指定すれば良いでしょう。一応昔風に変数

	$X_ML_INFO_MESSAGE

で指定した内容を優先して X-ML-Info: につけて配送できるようにもなってい
ます。そうでない場合はモードによって適当に作られた user friendly な内
容が付け加えられます。

3.17	To: の Rewriting 処理

2.1A の途中(config.ph CFVersion: 3.2)から To: Cc: は元のメールをそのま
ま通しています。2.2 のデフォールトは素通しです。

可読性のため、To: フィールドは $MAIL_LIST が展開され、常にMLのアドレ
スが出るようにすることもできます。makefml config ML で変更できます。

本来は書く人が気をつけるべきものであってMLサーバが気にするべきもので
はないでしょう。でも世の中わけ分からん人が多いので、apparent-to: になっ
ていて見辛いとか一体どうしてこのMLに来たメールなの?とかよくわからな
いメールのために常に To: $MAIL_LIST をつけることが可読性のためにもよい
とおもいますが…

現在は $REWRITE_TO が
	値	挙動
	0 	素通し (FML 2.2 default)

	1 	To: に $MAIL_LIST が含まれていればOK
		To: には $MAIL_LIST が含まれていない場合は
			To: $MAIL_LIST,
			    元の To: 

		にする (FML 2.1 default)。

	2 	To: $MAIL_LIST に強制する。
		To: の元々の内容は失われる。

To: Cc: というのは人間がメールを書く時の単なる便宜上のもので、配送手段
の SMTP としてはなんら区別はしていません。ですから、情報を落さず、To: 
は可読性のために $MAIL_LIST としています。

[蛇足] なお、To: Cc: の中に重複して現れるアドレスには普通それらを一つ
にまとめて一通分のみが配送されます。だから複数あっても気にしないでね

#注意:なお、$NOT_REWRITE_CC は obsolete にしました

3.18	NIFTY対策をするか?(参加者にNIFの人もいる, OBSOLETE?)

注意: もう必要ないらしい

	$USE_ERRORS_TO = 1;

とすると Errors-To: をつけます。$AGAINST_NIFTY も同じ意味でしたが 
$CFVersion 3 ではなくなりました。

NIFTY は非常識にも、Errors-to という時代おくれの部分しかみてないので;_;、
config.ph あたりで

	$AGAINST_NIFTY = 1

とするとメール本文に

	Errors-To: $MAINTAINER

がつきます。これで NIFTY からのエラーメールが $MAINTAINER に返るように
なってくれます。後向きな解決法ですが;_;。
前向きなのは、みんなで文句をいって直させることです。
#でも、僕はアカウントをもってない;_;。アカウントを持ってる人が一年く
らいいいつづけないとだめなんだろうなぁ(はぁ)

なお、$ERRORS_TO で Errors-To: の部分は $MAINTAINER から変更できます。

3.19	Errors-To:をつける

RFC1123 に逆らって Erros-To: をつけるなら $USE_ERRORS_TO = 1; 
$USE_ERRORS_TO = 1; if you append Errors-To:.

3.20	Replyのメールのサブジェクトを新しくする際にブラケットを外さない

例: (Elena 100) Re:(Elena 99) xxxxxx のままにしてしまう

$SUBJECT_TAG_TYPE を使わず、なおかつ $SUBJECT_FREE_FORM_REGEXP = $NULL;

	$SUBJECT_TAG_TYPE = "";
        $SUBJECT_FREE_FORM = 1;
        $BEGIN_BRACKET     = '(';
        $BRACKET           = 'Elena';
        $BRACKET_SEPARATOR = ' ';
        $END_BRACKET       = ')';
	$SUBJECT_FREE_FORM_REGEXP = $NULL;


と定義しておくと外す動作ではずせなくなる。
#正確には(Elena 100)にマッチしなくなるだけなので、ちょっと違う

もしくは全然違う正規表現にしてマッチしないようにしておいても同様です。

注意としては $SUBJECT_TAG_TYPE も併用して差分だけ書いてはいけません。
$SUBJECT_TAG_TYPEを定義するとはfml が起動して config.ph をよんだ後に動
的に上の設定をしているので config.ph の設定では単純に上書きできません。


3.21	Reply-To: を From: + $MAIL_LIST に設定する   

$START_HOOK = q#
      &DEFINE_FIELD_FORCED("reply-to", "$From_address, $MAIL_LIST");
#;

You need to use a hook since From: address is dynamic variable, so
cannot define static setting in config.ph.

3.22	Reply-To: を From: + $MAIL_LIST に設定する(2)   

fml-support: 06240

○ やりたいこと

   if メンバー以外からの投稿
	Reply-To: From:のアドレス, メーリングリスト
   else
	Reply-To: メーリングリスト	

○ config.phの書き換えだけでうまくいくのでしょうか?

変数のon/offという意味なら no です。
HOOKを書いていいなら yes です。

config.ph は単なるperlのプログラムです。fmlのあちこちには hook をはし
らせることができます。複雑な操作を全部変数にしているときりがないので
ある程度以上はHOOKでおこなうことで、設定ファイルをfml本体とは分けて保
守するというというデザインになっています。
#Emacs みたいなもんだとおもってくれればOK

$START_HOOK =q%
   if (&MailListMemberP($From_address)) {
	&DEFINE_FIELD_FORCED("reply-to", $MAIL_LIST);
   }
   else {
	&DEFINE_FIELD_FORCED("reply-to", "$From_address, $MAIL_LIST");
   }
%;

3.23	サポート用のML

Q:

このMLで、問い合わせへの返事+スタッフ間の連絡で兼用
しています。

(1) 誰でも投稿できる(投稿だけ)。
(2) 配信されたメールに対して、
   (A)「ML加入者への返信」と
   (B)「問い合わせた人+ML加入者への返信」
  を簡単に使い分けられるようにします。

そこで Reply-To を残したまま CC: に元メールの From: をいれておきたい。
そうすると(名称はメールソフトによるが)「ふつうに返信」で (A)、「全員に
返信」で (B) が実現できる。

答え:

$SMTP_OPEN_HOOK = q#
    if ($Envelope{'h:Cc:'}) {
        &DEFINE_FIELD_FORCED('Cc', 
		$Envelope{'h:Cc:'}. ", ". $From_address );
    } else {
        &DEFINE_FIELD_FORCED('Cc', $From_address);
    }
#;

注意: この場合のポイントは HOOK を使うことです。使わずに書くと 
      config.ph が評価される時に $From_address の値がまだ不定なのです。


3.24	毎日 TAG をリセットしたい(一日のMail数が 一目でも分かるように)

例えば0:00を境に
   Subject: [elena 00100] の番号を自動的に 
   Subject: [elena 00000] にしたい

/var/spool/ml/elena 以下の seq, summary, log, spool などを全部初期かし
てしまうしかないです。

解答例: このプログラム(shell script)を毎日夜12時にまわす

   #!/bin/sh

   ml=elena
   date=`date -u +%C%y%m%d`

   /usr/local/fml/makefml lock $ml 60 &

   cd /var/spool/ml/$ml || exit 1

   for file in seq spool summary log
   do
       if [ -f $file ];then
          # mv $file $file.$date
          cp  $file $file.$data
         cp /dev/null $file
       fi
   done

3.25	投稿された記事 Received: を X-Received: に

Q: 	投稿された記事 Received: を X-Received: に
	そしてコピーしてその元の Received: は消す。

A:

	&COPY_FIELD('Received', 'X-Received');
	$SKIP_FIELDS = 'Received|Return-Receipt-To';


[結果]

 Received: by hikari.fml.org (8.9.3/3.4W6+Hikari-2.1) with ESMTP id XAA17996 for <fukachan@sapporo.iij.ad.jp>; Wed, 6 Oct 1999 23:29:52 +0900 (JST)
 Received: from beth.fml.org (localhost.sapporo.iij.ad.jp [127.0.0.1])
 	by beth.fml.org (Postfix) with ESMTP id 1CE0EA6837
 	for <fukachan@fml.org>; Wed,  6 Oct 1999 23:29:52 +0900 (JST)
 X-Received: by hikari.fml.org (8.9.3/3.4W6+Hikari-2.1) with ESMTP id XAA17981 for <fukachan@sapporo.iij.ad.jp>; Wed, 6 Oct 1999 23:29:30 +0900 (JST)
 X-Received: by beth.fml.org (Postfix)
 	id 465B4A6838; Wed,  6 Oct 1999 23:29:30 +0900 (JST)
 X-Received: by beth.fml.org (Postfix, from userid 1106)
 	id 0DB1EA6837; Wed,  6 Oct 1999 23:29:29 +0900 (JST)
 Date: Wed,  6 Oct 1999 23:29:29 +0900 (JST)
 From: fukachan@fml.org (Ken'ichi Fukamachi)
 Reply-To: elena@fml.org
 To: fukachan@fml.org
 Message-Id: <19991006142929.0DB1EA6837@beth.fml.org>
 X-ML-Name: elena
 X-Mail-Count: 00207
 X-MLServer: fml 2.2; post only (only members can post)
 X-ML-Info: If you have a question, send e-mail with the body
 	"help" (without quotes) to the address elena-ctl@fml.org;
 	help=<mailto:elena-ctl@fml.org?body=help>
 Precedence: bulk
 Lines: 2

 test

 -- fukachan


[PREVIOUS CHAPTER] [NEXT CHAPTER]