fml8 のフィルタシステムで利用可能なフィルタは
/usr/local/etc/fml//defaults/$VERSION/default_config.cf.jaを読むと分かります。
この内蔵フィルタで実装されていない内容のフィルタは article_post_verify_request_end_hook article_filter_start_hook article_filter_end_hook article_post_run_start_hook のいづれかの HOOK でおこなえばよいでしょう。
$article_filter_start_hook = q{ my $header = $curproc->incoming_message_header(); my $body = $curproc->incoming_message_body(); if (条件) { $curproc->policy_reject_this_message(); } };のように書けば良いとおもいます。 フィルタの書き方についてはソースコード本体や、 以下のレシピも参照して下さい。
たとえば、 特定のドメイン(\S+\@example.co.jp)を全て拒否するフィルタのことです。 内蔵フィルタの一部として実装しようと考えていますが、 残念ながら未実装です _o_
mime component filter で「message/partial * reject」を設定して下さい。
[/usr/local/etc/fml/mime_component_filter] # allow only text/plain messages. message/partial * reject text/plain * permit text/html * reject multipart/* !text/plain reject
注意: このフィルタは全MLに反映されます。
fml8 は、 あらかじめ入力されたメッセージを解析し、 メモリ上に鎖状の Mail::Message オブジェクトの形で持っています。 そこで、 MIME/Multipart の各部分のヘッダを取り出して、正規表現で順に確認すればよいだけです。
HOOK でなんとかする/ごまかす例は次の通りです。 どちらの例でも、 マッチした場合、stop_this_process() 命令で、 それ以上の処理を止めています。 また、 この例では何もエラーメッセージを返そうとしていないため、 結果として、このメッセージは無視されて終りになっています。
返事をしてあげたいなら、 reply_message() で、何か返事を返してあげてください。 ただ、こういったメールはウィルスなどの可能性が高いので、 返事をしないほうが良いでしょう。
.exe など特定のファイル拡張子にマッチするか?を調べる例。 昔の fml8 (2004/12/08 以前)なら、こんな感じ。
$distribute_verify_request_start_hook = q{ my $msg = $curproc->incoming_message() || undef; for (my $m = $msg; $m ; $m = $m->{ next } ) { my $hs = $m->message_fields() || ''; if ($hs =~ /filename=.*\.(com|vbs|vbe|wsh|wse|js|exe|doc|rtf)/o) { $curproc->log("attachment \.$1 found"); $curproc->stop_this_process(); } } };2004/12/08 以降の fml8 なら、こんなかんじ。
$distribute_verify_request_start_hook = q{ my $msg = $curproc->incoming_message() || undef; my $list = $msg->message_chain_as_array_ref(); for my $m (@$list) { my $hs = $m->message_fields() || ''; if ($hs =~ /filename=.*\.(com|vbs|vbe|wsh|wse|js|exe|doc|rtf)/o) { $curproc->log("[new] attachment \.$1 found"); $curproc->stop_this_process(); } } };
別解としては、
Content-Disposition: attachment;という表示になることを前提に、これを引っかけるという案もあります。
$distribute_verify_request_start_hook = q{ my $msg = $curproc->incoming_message() || undef; for (my $m = $msg; $m ; $m = $m->{ next } ) { my $hs = $m->message_fields() || ''; if ($hs =~ /Content-Disposition:.*attachment;/o) { $curproc->log("attachment \.$1 found"); $curproc->stop_this_process(); } } };2004/12/08 の fml8 以降なら、こんなかんじ。
$distribute_verify_request_start_hook = q{ my $msg = $curproc->incoming_message() || undef; my $list = $msg->message_chain_as_array_ref(); for my $m (@$list) { my $hs = $m->message_fields() || ''; if ($hs =~ /Content-Disposition:.*attachment;/o) { $curproc->log("[new] attachment \.$1 found"); $curproc->stop_this_process(); } } };
デフォルトでは
use_article_filter_reject_notice = yes article_filter_reject_notice_recipient = maintainer senderとなっています。 つまり、 (1) エラーメールを返し(yes)、 (2) 返す先はMLの管理者と送信者の両方(maintainer sender) です。
返送する先を送信者( From: のアドレス )"のみ"にするには
article_filter_reject_notice_recipient = senderとしてください。
MLの管理者と送信者( From: のアドレス )の両方に返すには
article_filter_reject_notice_recipient = maintainer senderとしてください。
そもそもエラーメールを返さないようにするには、
use_article_filter_reject_notice = noとしてください。
Caution |
そもそも spamassassin をよびだす内蔵フィルタがあるのですが、 それをあえて使わない例です。 |
1. 内蔵フィルタの設定例です。
use_article_spam_filter = yes article_spam_filter_drivers = spamassassin
2. 上と同様に spamassassi を呼び出すのですが、 それを HOOK でなんとかする/ごまかす例は次の通りです。
$distribute_verify_request_end_hook = q{ my $spamassassin = '/usr/pkg/bin/spamc -c'; use FileHandle; my $wh = new FileHandle "| $spamassassin"; if (defined $wh) { $wh->autoflush(1); my $msg = $curproc->incoming_message(); $msg->print($wh); $wh->close(); if ($?) { $curproc->log("spam: (code = $?)"); $curproc->stop_this_process(); } } };
$distribute_verify_request_end_hook = q{ my $spamassassin = '/usr/pkg/bin/spamc -c'; use FileHandle; my $wh = new FileHandle "| $spamassassin"; if (defined $wh) { $wh->autoflush(1); my $msg = $curproc->incoming_message(); $msg->print($wh); $wh->close(); if ($?) { $curproc->log("spam: (code = $?)"); my $hdr = $curproc->incoming_message_header(); $hdr->add('X-Spam-Status', 'Yes'); } } };
ちょっとトリッキーですが、動きます。
HOOK で行なうなら次のようになります。
$article_filter_end_hook = q{ my $header = $curproc->incoming_message_header(); my $addr = $config->{ article_post_address }; my $to = $header->get('To') || ''; my $cc = $header->get('Cc') || ''; my $to_cc = "$to, $cc"; my $found = 0; use Mail::Address; my (@addrlist) = Mail::Address->parse($to_cc); for my $a (@addrlist) { my $_addr = $a->address(); if ($_addr =~ /^$addr$/i) { $found = 1; } } if ($found) { $curproc->log("article_post_address found in header"); } else { $curproc->log("article_post_address not found in header"); $curproc->policy_reject_this_message(); } };
Copyright (C) 1993-2025 Ken'ichi Fukamachi mail:< fukachan at fml.org >