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 の検証や専用のフィルターと組み合わせます。

関連記事

お気軽にご相談ください

お見積りへ お問い合わせへ
▲