第22章 メール配送フィルタとメールボックスアクセス(Sieve/Dovecot)
LPIC-2 211.2〜211.3 相当
前章ではPostfixによる送信の基本を扱いました。ここでは受信したメールをどう振り分けるか(Sieve)、そしてユーザーがメールボックスにアクセスするための仕組み(Dovecot)を掘り下げて扱います。
Dovecotの役割
Dovecotは、ユーザーがメールクライアントからメールボックスを閲覧するためのIMAP/POP3サーバーです。Postfixが受け取ったメールをメールボックスに配送し、Dovecotがそれをユーザーに届けるという分担になります。
$ sudo systemctl status dovecot
● dovecot.service - Dovecot IMAP/POP3 email server
Loaded: loaded (/lib/systemd/system/dovecot.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-08-21 09:15:02 JST; 2h 30min ago
Process: 4210 ExecStartPre=/usr/sbin/dovecot -F -c /etc/dovecot/dovecot.conf (code=exited, status=0/SUCCESS)
Main PID: 4218 (dovecot)
Tasks: 5 (limit: 4649)
Memory: 12.3M
CPU: 340ms
CGroup: /system.slice/dovecot.service
├─4218 /usr/sbin/dovecot
├─4220 dovecot/anvil
├─4221 dovecot/log
└─4222 dovecot/config
$ doveconf -n # 現在有効な設定を表示
# 2.3.21 (7e8b9aa6f4)
# OS: Linux 6.6.32-1 x86_64 Ubuntu 24.04.1 LTS
mail_location = maildir:~/Maildir
protocols = imap pop3 lmtp
ssl = required
ssl_cert = </etc/ssl/certs/mail.crt
ssl_key = </etc/ssl/private/mail.key
この行のこの値に注目: systemctl statusのCGroupに列挙されているdovecot/anvil・dovecot/log・dovecot/configは、Dovecotがマスタープロセスから機能ごとに分離した子プロセスを起動するアーキテクチャを採用していることを示します。doveconf -nの出力は、doveconf -nという名前の通り「既定値から変更された設定だけ」に絞られているため、この行数だけを見れば実際にどこをカスタマイズしたのかが一目瞭然になります。
メールボックスの保存形式には、伝統的なmbox(1ファイルにすべてのメールを連結して格納)と、より新しいMaildir(1メール1ファイルとしてディレクトリに格納)があります。Maildir形式は、複数プロセスが同時にアクセスしてもファイルロックの競合が起きにくく、メールの一部が壊れても他のメールに影響しないという利点があるため、現在の新規構築ではMaildirが選ばれることがほとんどです。
| プロトコル | 特徴 |
|---|---|
| POP3 | メールをクライアント側にダウンロードして削除するのが基本の動作。1台の端末だけでメールを読む場合に単純 |
| IMAP | メールはサーバー側に置いたまま操作する。複数端末(スマートフォンとPCなど)で同じメールボックスを参照する場合に適している |
Dovecotの設定ファイル構成
Dovecotの設定は/etc/dovecot/以下に分割されたファイル群で構成されます。メインのdovecot.confからconf.d/以下の機能ごとのファイルが!includeで読み込まれる構造です。主要なファイルの内容を、コメント付きの完全な例として示します。
/etc/dovecot/dovecot.conf
protocols = imap pop3 lmtp # 有効にするプロトコル(IMAP・POP3・ローカル配送用のLMTP)
!include conf.d/*.conf # conf.d以下の全設定ファイルを読み込む
/etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:~/Maildir # Maildir形式、各ユーザーのホーム配下に保存
# mbox形式の場合は mail_location = mbox:~/mail:INBOX=/var/mail/%u のように書式が異なる
/etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = yes # TLSで保護されていない平文認証を拒否する
auth_mechanisms = plain login # 許可する認証方式(TLS保護下でのみplain/loginを許可)
!include auth-system.conf.ext # PAM等、システム標準の認証設定を読み込む
/etc/dovecot/conf.d/10-ssl.conf
ssl = required # 暗号化されていない接続を拒否する
ssl_cert = </etc/ssl/certs/mail.crt # 証明書(<はDovecot独自の「ファイル内容を読み込む」構文)
ssl_key = </etc/ssl/private/mail.key # 秘密鍵
ssl_min_protocol = TLSv1.2 # 許可する最低限のTLSバージョン
/etc/dovecot/conf.d/10-master.conf(抜粋)
service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
ssl = yes
}
}
service pop3-login {
inet_listener pop3 {
port = 110
}
inet_listener pop3s {
port = 995
ssl = yes
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
service auth内のunix_listenerが、前章のPostfixのsmtpd_sasl_path = private/authに対応する、Postfix用のSASL認証ソケットの定義です。ここでPostfixユーザー・グループに読み書き権限を与えることで、PostfixがこのソケットごしにDovecotへ認証を委譲できるようになります。
/etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
mail_plugins = $mail_plugins
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
LMTP(Local Mail Transfer Protocol)は、PostfixからDovecotへメールを受け渡すための、SMTPに似た軽量なプロトコルです。伝統的なUnixのlocal配送に比べ、1回の接続で複数の宛先をまとめて処理できるなど効率面で優れており、現在のDovecot連携では標準的な選択肢になっています。
doveconf -nとdoveconf -aの違い
| コマンド | 用途 |
|---|---|
doveconf -n | 既定値と異なる(管理者が変更した)設定のみを表示する。設定の見通しがよく、サポートへの報告時にもよく使われる |
doveconf -a | 既定値も含めた全設定項目を表示する。特定パラメータの現在の実効値を細部まで確認したい場合に使う |
$ doveconf -n | grep ssl
ssl = required
ssl_cert = </etc/ssl/certs/mail.crt
ssl_min_protocol = TLSv1.2
doveadmの主要サブコマンド
| サブコマンド | 用途 |
|---|---|
doveadm user <user> | 指定ユーザーのuserdb情報(メールボックスの場所、UID/GIDなど)を確認する |
doveadm auth test <user> | 指定ユーザーの認証(パスワード)が正しく通るかをテストする |
doveadm mailbox list -u <user> | 指定ユーザーが持つメールボックス(フォルダ)の一覧を表示する |
doveadm search | 条件を指定してメールを検索する |
doveadm fetch | 検索条件に一致したメールの内容やヘッダーを取得する |
doveadm expunge | 検索条件に一致したメールを完全に削除する |
doveadm quota get -u <user> | 指定ユーザーのメールボックス使用量・クォータ状況を確認する |
$ doveadm user alice
field value
uid 5001
gid 5001
home /home/alice
mail maildir:~/Maildir
$ doveadm auth test alice
Password:
passdb: alice auth succeeded
$ doveadm mailbox list -u alice
INBOX
Sent
Trash
Newsletters
$ doveadm search -u alice mailbox INBOX seen
box=INBOX uid=1023
box=INBOX uid=1024
box=INBOX uid=1030
$ doveadm expunge -u alice mailbox Trash before 30d # ゴミ箱内の30日より古いメールを削除(正常時は無出力)
$ doveadm quota get -u alice
Quota name Type Value Limit %
STORAGE STORAGE 128000 512000 25
この行のこの値に注目: doveadm searchの出力にあるuid=は、そのメールボックス内でのメール固有の番号(IMAP UID)で、この番号を使ってdoveadm fetchで個別のメール内容を取得できます。doveadm quota getの%列(この例では25%)が100に近づいている場合、そのユーザーのメールボックスがクォータ上限に近づいていることを示し、新着メールの受信拒否につながる前に容量整理や上限緩和を検討する目安になります。
Dovecotのユーザー認証(passdb/userdb)
Dovecotは、ユーザーが誰であるかを確認する「passdb」(パスワード確認)と、そのユーザーのメールボックスの場所やUID/GIDを決める「userdb」(ユーザー情報)という、2つの独立した仕組みでユーザーを扱います。
/etc/dovecot/conf.d/10-auth.conf などの一部
passdb {
driver = pam
}
userdb {
driver = passwd
}
| driver | 用途 |
|---|---|
pam | Linuxのシステムアカウント(PAM経由)で認証する |
passwd-file | Dovecot専用のパスワードファイルで認証する(システムアカウントと分離したい場合) |
ldap | LDAPサーバーに問い合わせて認証する |
sql | MySQLなどのデータベースに問い合わせて認証する(大規模なホスティング環境向け) |
passdbとuserdbは異なるdriverを組み合わせることも可能です(例:認証はLDAPで行うが、メールボックスの場所は固定のルールで決めるなど)。この分離により、認証方式を変更してもメールボックスの管理方法には影響を与えない、柔軟な構成が可能になります。
Sieveとは何か
Sieveは、受信したメールを条件に応じて自動的に振り分けるための、標準化(RFC 5228)されたスクリプト言語です。DovecotではPigeonholeというプラグインを通じてSieveを実行できます。
procmailというツールが同様のメールフィルタリング用途で広く使われていました。procmailの独自ルール言語は事実上任意の外部コマンドへメールをパイプできる強力さを持つ一方、Sieveは意図的に「Turing完全ではない」言語として設計されています。ループ構文や任意プログラムの実行手段を持たないため、無限ループやリソース枯渇を起こすスクリプトを書くこと自体ができません。この安全性の高さゆえに、Sieveはエンドユーザー自身にWebメールやSieveエディタから直接ルールを編集させても、サーバー側のリスクが小さく済みます。
DovecotでのSieveの有効化
Sieveを使うには、メール配送を担うプロトコル(ldaまたはlmtp)にsieveプラグインを追加します。
/etc/dovecot/conf.d/20-lmtp.conf または 90-sieve.conf
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
protocol lda {
mail_plugins = $mail_plugins sieve
}
ユーザーが現在有効にしているSieveスクリプトは~/.dovecot.sieve(実体はシンボリックリンクで、~/sieve/配下の実際のスクリプトファイルを指すことが多い)です。管理者が全ユーザー共通で適用したいルールがある場合は、ユーザー自身のスクリプトの前後に、管理者管理のグローバルスクリプトを挟み込めます。
90-sieve.conf での設定
sieve_before = /etc/dovecot/sieve/before.d/ # ユーザーのスクリプトより前に必ず実行(例:明らかなスパムの隔離)
sieve_after = /etc/dovecot/sieve/after.d/ # ユーザーのスクリプトの後に実行(例:フォールバック処理)
WebメールやメールクライアントのプラグインからシェルアクセスなしにSieveスクリプトを編集・アップロードできるようにする、ManageSieveプロトコル(RFC 5804、既定ポート4190)用のサービスも用意されています。
conf.d/20-managesieve.conf
service managesieve-login {
inet_listener sieve {
port = 4190
}
}
Sieveの基本構文
スクリプトの先頭ではrequireで使用する拡張機能を宣言し、if/elsif/elseで条件分岐を書きます。
基本構文の骨格
require ["fileinto", "envelope", "reject", "vacation"];
if header :contains "subject" "[SPAM]" {
fileinto "Junk";
} elsif address :is "from" "boss@example.com" {
fileinto "Important";
} else {
keep;
}
| 条件(テスト) | 意味 |
|---|---|
header | 指定したヘッダーフィールドの値を検査する |
address | From/Toなどのアドレス系ヘッダーから、アドレス部分だけを抜き出して検査する |
envelope | SMTPのエンベロープ情報(MAIL FROM/RCPT TOで実際にやり取りされた値)を検査する |
size | メール全体のサイズを検査する |
exists | 指定したヘッダーが存在するかどうかを検査する |
allof | 複数の条件をすべて満たすか(AND)を検査する |
anyof | 複数の条件のいずれかを満たすか(OR)を検査する |
not | 条件の結果を反転する |
| 比較演算子 | 意味 |
|---|---|
:is | 完全一致 |
:contains | 部分一致(指定した文字列を含むか) |
:matches | ワイルドカード(*・?)を使ったパターン一致 |
:over | サイズが指定値を超える(sizeテストで使用) |
:under | サイズが指定値未満(sizeテストで使用) |
| アクション | 意味 |
|---|---|
keep | 既定の受信トレイにそのまま保持する |
fileinto "フォルダ名" | 指定したフォルダへ移動する |
redirect "アドレス" | 別のメールアドレスへ転送する |
reject "理由" | 送信者にエラーを返して受信を拒否する |
discard | エラーを返さず、静かに破棄する |
stop | それ以降のルール評価を打ち切る |
addflag "フラグ" | メールに\Seenや\FlaggedなどのIMAPフラグを立てる |
実用的なフィルタ例
例1:件名に[SPAM]を含むものをJunkフォルダへ
require ["fileinto"];
if header :contains "subject" "[SPAM]" {
fileinto "Junk";
stop;
}
例2:特定の送信者からのメールをフォルダ分け
require ["fileinto"];
if address :is "from" "newsletter@example.com" {
fileinto "Newsletters";
} elsif address :contains "from" "@partner.example.com" {
fileinto "Partners";
}
例3:1MBを超えるメールを別フォルダへ
require ["fileinto"];
if size :over 1M {
fileinto "LargeMail";
}
例4:List-Idヘッダーでメーリングリストを振り分け
require ["fileinto"];
if header :contains "list-id" "<dev-list.example.com>" {
fileinto "Lists.Dev";
}
例5:不在通知(vacation)
require ["vacation"];
if not header :contains "subject" "[SPAM]" {
vacation
:days 7
:subject "休暇のため返信が遅れます"
:addresses ["alice@example.com", "alice.smith@example.com"]
"現在休暇をいただいております。緊急の場合はお電話にてご連絡ください。";
}
この行のこの値に注目::days 7は、同じ送信者に対しては7日間隔でしか自動返信を送らないという設定で、短期間に同じ相手へ何度も自動応答を送り続ける事態を防ぎます。:subjectは自動返信メール自体の件名を指定します。:addressesには、自分が受け取りうる複数のメールアドレス(エイリアスなど)を列挙しておく必要があります。これを指定し忘れると、エンベロープ宛先が主アドレスと一致しない場合にvacationが発動しないことがあります。
sievecによるコンパイルと構文チェック
sievecは、Sieveスクリプトを事前にバイナリ形式(.svbin)へコンパイルし、構文エラーがないかを静的にチェックするツールです。特に管理者がsieve_before/sieve_afterのようなグローバルスクリプトを配置する際、実運用中の配送処理でパースエラーが起きるリスクを事前に減らせます。
$ sievec /etc/dovecot/sieve/before.d/spam-check.sieve
# 構文エラーがなければ何も出力されず、同名の.svbinファイルが生成される
$ sievec broken.sieve
broken.sieve: line 5: error: unexpected token '}'
# 構文エラーがあれば、行番号付きでエラー内容が表示される
procmailの概要
procmailは、Sieve登場以前から使われてきた、正規表現ベースの独自ルールファイル(~/.procmailrc)によるメールフィルタリングツールです。レシピと呼ばれる単位でルールを記述します。
procmailのレシピ書式の例
:0 flags: lockfile
* ^Subject:.*SPAM
spam-folder
:0は新しいレシピの開始を示す記号です。flagsには、ヘッダーのみを検査対象にするH、本文も検査対象にするB、マッチしても以降のレシピの評価を継続するc(コピーを作る)などを指定できます。lockfileは、複数のprocmailプロセスが同時に同じメールボックスを操作しないよう排他制御に使うロックファイル名です(省略時は自動生成)。*で始まる行が条件(正規表現)で、複数行書くとすべての条件を満たす場合にのみマッチするAND条件になります。最後の行がアクションで、ディレクトリ/mboxファイルへのパスを書けば配送先指定、|で始めれば外部コマンドへのパイプになります。
.procmailrcを自由に編集できる環境では、暴走プロセスやリソース枯渇を招くリスクにもなります。標準化され、意図的に安全な言語として設計されたSieveの方が、これらの懸念が小さく済みます。新規構築では、特別な理由がない限りSieveを選ぶのが現在の主流です。
Courierについて
Dovecotとは別系統の歴史あるメールサーバー実装群として、Courier(Courier-IMAPやCourier-MTAなど)も存在します。LPIC-2の出題範囲では、Courierの詳細な設定手順まで問われることは多くありませんが、「DovecotやPostfix以外にもCourierという選択肢がある」という存在自体を知っておくと、実務や試験で名前が挙がった際に戸惑わずに済みます。現在の新規構築ではDovecot+Postfixの組み合わせが主流ですが、既存システムの引き継ぎ・移行作業などでCourierベースの環境に遭遇する可能性は残っています。