2026年5月30日
2026年5月30日
Postfixのheader_checks・body_checksの設定方法|書式・アクション・テストの仕方
header_checks と body_checks は、Postfix に組み込まれた簡易的な内容検査の仕組みです。メールのヘッダーや本文の1行ずつを正規表現のパターンと照らし合わせ、一致したら拒否する、ログに記録する、書き換える、といった処理を行います。
Postfix の公式マニュアル(header_checks(5))は、この仕組みを「ワームやウイルスの大量送信を止めるためのもの」と位置づけ、添付ファイルの展開やデコードはしないと明記しています。本格的な迷惑メール対策には SpamAssassin や rspamd などの専用ソフトが向いています。この記事では、header_checks・body_checks の書式とアクション、テストの仕方、WordPress から送るメールの差出人を変える方法を説明します。
内容は2026年10月時点の Postfix 3.x の公式マニュアルに基づいています。パスやパッケージ名は Ubuntu / Debian の例です。
設定できる検査の種類
/etc/postfix/main.cf で、検査の種類ごとにルールのファイルを指定します。
| パラメーター | 検査する対象 | 検査のタイミング |
|---|---|---|
header_checks |
メールの最初のヘッダー(Subject:・From: など) |
受け取ってキューに入れる前(cleanup) |
mime_header_checks |
MIME 関連のヘッダー(Content-Type: など)。既定は $header_checks と同じ |
同上 |
nested_header_checks |
添付されたメールのヘッダー。既定は $header_checks と同じ |
同上 |
body_checks |
本文の各行(マルチパートの境界の行も含む) | 同上 |
smtp_header_checks・smtp_body_checks |
外部へ配送するときのヘッダー・本文 | SMTP で配送するとき(Postfix 2.5 以降) |
header_checks と body_checks は、外部から受け取るメールにも、WordPress などサーバー上のプログラムが送るメールにも、Postfix を通るすべてのメールにかかります。
検査の単位について、マニュアルには次の制限が書かれています。
- ヘッダーは「論理的な1ヘッダー」ずつ(折り返された複数行のヘッダーは1つにまとめて)、本文は1行ずつ調べる。ある行の判定は次の行に引き継がれない
- 本文が Base64 や quoted-printable で符号化されている場合、パターンは符号化された形に対して書く必要がある
- ヘッダーが RFC 2047 で符号化されている場合も同様
- cleanup 自身が補ったヘッダー(元のメールに無かった
From:・Date:・Message-ID:など)は検査されない - 本文の検査は各パートの先頭から
body_checks_size_limit(既定 51200 バイト)まで
日本語の件名は =?UTF-8?B?...?= のように符号化されているのが普通なので、/^Subject:.*当選/ のような日本語のパターンは一致しません。HTML メールの本文も Base64 で送られることが多く、その場合 body_checks で HTML のタグや文言を探しても一致しません。
regexpとpcreの違い
ルールのファイルは、正規表現の表(regexp: か pcre:)として指定します。
| 形式 | 正規表現の種類 | 備考 |
|---|---|---|
regexp: |
POSIX 正規表現 | 追加のパッケージなしで使える |
pcre: |
Perl 互換正規表現 | マニュアルでは通常こちらが速いとされる。Debian / Ubuntu では postfix-pcre パッケージが必要 |
自分の環境で使える形式は postconf -m で確認できます。pcre が無ければ、Ubuntu / Debian では次のように入れます。
postconf -m
sudo apt install postfix-pcre
どちらの形式も、既定で大文字・小文字を区別しません。区別の有無はパターンの後ろに付けるフラグ i で切り替えます(/pattern/i と書くと、逆に区別するようになります)。Perl の (?i) のような書き方は POSIX 正規表現(regexp:)では使えず、パターンのエラーになります。既定で区別しないので、付ける必要もありません。
regexp: と pcre: のファイルは postmap で変換する必要はありません(.db ファイルを作るのは hash: などの形式だけです)。
ルールファイルの書式
1行に「パターン」と「アクション」を書きます。
/パターン/フラグ アクション 任意のメッセージ
#で始まる行と空行は無視されます- 空白で始まる行は、前の行の続きとして扱われます(長いルールを折り返して書ける)
- パターンは上から順に照らし合わされ、最初に一致したルールのアクションが実行されます
!/パターン/は「一致しないとき」、if /パターン/~endifで条件のまとまりを書けます
アクションの $1、$2 は、パターンの中の ( ) で囲んだ部分に一致した文字列に置き換わります。( ) が無いパターンで $1 を使っても、置き換わる文字列はありません。
主なアクション
| アクション | 動作 |
|---|---|
REJECT 文言 |
メール全体を拒否する。文言を付けないと既定のエラー文になり、状態コードは既定で 5.7.1 |
WARN 文言 |
ログに warning: を記録して次の行へ進む。パターンを試すときに使う |
INFO 文言 |
ログに info: を記録して次の行へ進む(Postfix 2.8 以降) |
HOLD 文言 |
メールを保留キューに入れる。postsuper で解放・削除する |
DISCARD 文言 |
配送したことにして黙って捨てる |
IGNORE |
その行(ヘッダー)を削除する。ログに残す STRIP もある(3.2 以降) |
PREPEND 文字列 |
一致した行の直前に1行足す。ヘッダーの場合は正しいヘッダー名で始める |
REPLACE 文字列 |
一致した行を置き換える。ヘッダーの場合は正しいヘッダー名で始める |
REDIRECT アドレス |
本来の宛先ではなく指定したアドレスへ送る |
BCC アドレス |
BCC の宛先を追加する(3.0 以降) |
REJECT・HOLD・DISCARD・REDIRECT・BCC などは、配送時の smtp_header_checks・smtp_body_checks では使えません。配送時に使えるのは WARN・INFO・IGNORE・PREPEND・REPLACE などです。
header_checksを設定する
ここでは pcre: を使います。main.cf に検査のファイルを指定します。
sudo postconf -e "header_checks = pcre:/etc/postfix/header_checks.pcre"
/etc/postfix/header_checks.pcre を作り、ルールを書きます。最初はすべて WARN にして、正当なメールが一致しないかをログで確かめます。
# 件名に特定の英単語を含むメール(大文字・小文字は区別しない)
/^Subject:.*\b(free money|casino bonus)\b/ WARN spam keyword in subject
# 件名に $$$ を含むメール($ は記号として扱うため \ を付ける)
/^Subject:.*\$\$\$/ WARN dollar signs in subject
# 特定のドメインからの差出人
/^From:.*@spam-domain\.example\b/ WARN blocked sender domain
# 特定のメーラー名
/^X-Mailer:.*\bmass mailer\b/ WARN mass mailer
ログを見て問題がなければ、WARN を REJECT に書き換えます。REJECT では、メッセージの先頭に状態コードを付けることもできます(例: REJECT 5.7.1 Message rejected)。
body_checksを設定する
sudo postconf -e "body_checks = pcre:/etc/postfix/body_checks.pcre"
# 本文の行に IP アドレス直書きの URL がある
/https?:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\// WARN URL with IP address
# アスタリスクが10個以上続く行
/\*{10,}/ WARN many asterisks
body_checks は1行ずつの検査なので、複数行にまたがる文章や、符号化されたパートの中身は判定できません。本文の検査はメールの数だけ全行に正規表現をかけるため、ルールを増やしすぎると処理が重くなる点にも注意してください。
反映する前にテストする
postmap -q で、文字列がどのルールに一致するかを確かめられます。表示されたのが一致したアクションで、何も出なければ一致していません。
# 1つの文字列を試す
postmap -q "Subject: FREE MONEY for you" pcre:/etc/postfix/header_checks.pcre
# → WARN spam keyword in subject
# 保存したメール(.eml)のヘッダー全体を試す
postmap -hmq - pcre:/etc/postfix/header_checks.pcre < sample.eml
# 本文を試す
postmap -bmq - pcre:/etc/postfix/body_checks.pcre < sample.eml
-h はヘッダー、-b は本文として入力を処理し、-m は MIME の解析を有効にします。
反映して確認する
# 設定ファイルの全体的な検査
sudo postfix check
# 現在の値の確認(-d は既定値の表示なので、ここでは使わない)
postconf header_checks body_checks
# 反映
sudo postfix reload
postconf -d header_checks は Postfix の既定値(空)を表示するだけで、設定した値の確認にはなりません。設定した値は postconf header_checks、既定から変えた項目の一覧は postconf -n で見ます。
ルールに一致すると、ログ(Ubuntu / Debian では /var/log/mail.log。RHEL 系では /var/log/maillog か journalctl -u postfix)に cleanup の行として記録されます。
sudo grep -E "(warning|reject|info): (header|body) " /var/log/mail.log | tail -n 20
warning: header Subject: ... や reject: header Subject: ... のように、アクション名・検査の種類・一致した行・最後に指定した文言が並びます。
WordPressから送るメールの差出人を変える
WordPress の wp_mail() は、既定で差出人を wordpress@サイトのドメイン(先頭の www. は除く)にします。これを変えたい場合は、Postfix で書き換えるより、WordPress 側で指定するほうが分かりやすく、影響もそのサイトのメールに限られます。
<?php
// テーマの functions.php や独自プラグインに書く
add_filter( 'wp_mail_from', function ( $from ) {
return 'noreply@example.com';
} );
add_filter( 'wp_mail_from_name', function ( $name ) {
return 'Example Site';
} );
複数のサイトやプログラムが同じサーバーから送っていて、サーバー側でまとめて変えたい場合は、Postfix の sender_canonical_maps を使います。たとえば、Web サーバーの実行ユーザー(Ubuntu では www-data)が封筒の差出人(Return-Path)になっているメールを書き換えるには、次のようにします。
sudo postconf -e "sender_canonical_maps = pcre:/etc/postfix/sender_canonical.pcre"
# /etc/postfix/sender_canonical.pcre
/^www-data@.*$/ noreply@example.com
sudo postfix reload
sender_canonical_maps は、既定で封筒の差出人とヘッダーの差出人の両方を書き換えます。ほかの方法としては、header_checks の REPLACE でヘッダーを書き換えることもできます。( ) で取り出した部分を $1 で使う例です。
# 件名の先頭の [Old Name] を [New Name] に置き換える(ASCII の件名のみ一致)
/^Subject:\s*\[Old Name\]\s*(.*)$/ REPLACE Subject: [New Name] $1
header_checks は外部から受け取るメールにもかかるため、書き換えのルールは対象を狭く書きます。また、DKIM で署名したあとにヘッダーを書き換えると署名が合わなくなります。配送時の smtp_header_checks で署名済みのヘッダー(From:・Subject: など)を書き換えるのは避けてください。
運用の注意
- 新しいルールは
WARNで入れ、ログで誤判定がないことを確かめてからREJECTにします。正当なメールを拒否すると、送信者に差し戻され、取引先とのやり取りが止まることがあります。 - ルールのファイルを変えたら
postmap -qで試してからpostfix reloadします。 - 迷惑メールの判定を本格的に行うなら、header_checks だけで対応しようとせず、SPF・DKIM・DMARC の検証や専用のフィルターと組み合わせます。