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. 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();
}
};author's homepage is www.fml.org/home/fukachan/.
Also, visit nuinui's world :) at www.nuinui.net.
For questions about FML, e-mail <fml-bugs@fml.org>.