第10章 sendmail から qmail への移行 - qmail で作る快適メールサーバー

佐藤 文優 <https://fumiyas.github.io/>
2001年12月17日 更新, 2001年8月 以来
FIXME: /etc/mail/local-host-name

目次

10.1 sendmail と qmail の違い
10.1.1 プロセスの構成
10.1.2 機能
10.1.3 設定ファイル
10.1.4 メールボックスの形式
10.2 sendmail からの移行の手順
10.2.1 sendmail デーモンの停止
10.2.2 未配送メールの処理 (キューの掃き出し)
10.2.3 sendmail の無効化
10.2.4 メールボックスの移行
10.2.5 POP/IMAP サーバーの移行
10.2.6 メールクライアントの設定変更
10.2.7 エイリアスと転送設定の移行
10.2.8 qmail デーモンの稼働
10.3 sendmail 互換環境を作る
10.3.1 qmail の sendmail 互換コマンドインターフェイス
10.3.2 /etc/aliases によるエイリアス設定
10.3.3 ~/.forward によるメールの転送
10.3.4 sendmail と同じメールボックスへの配送
10.3.5 必要なヘッダーフィールドが付けられていないメールの矯正
10.3.6 宛先ユーザー不明によるバウンスを管理者に通知する
付録
参考文献
更新履歴

10.1 sendmail と qmail の違い

sendmail に関する詳細な情報はほかの専門書に譲りますが、 ここでは sendmail と qmail の主な違いを挙げます。 移行作業と移行後の運用を円滑に行うには、違いだけでなく、 双方の本質を理解することも重要だということを付け加えておきます。

qmail の付属文書ファイル SENDMAIL には、 一般ユーザーから見た sendmail と qmail の違いについて記述されています。

10.1.1 プロセスの構成

sendmail はメール配送エージェントとしてのほぼすべての機能を 「sendmail」という名前のプロセス (コマンド) が担当しています。 そのため sendmail プロセスは巨大かつ複雑です。 しかも、1つで様々な権限が必要な役割りを負うため、 sendmail デーモンプロセスは root 権限で動作し、 しかも sendmail コマンドの実行ファイルは root 権限に setuid されています。 配送に関する処理を細分化し、 各処理ごとに必要最低限な実効権限のみを与えられている qmail とは大きく異なります。

qmail のプロセスは、 ある処理に特化された複数のプロセスで構成されています。 これらはまるで、 旧来からある UNIX の小粋で柔軟性の高いコマンド群のようです。 実際 qmail によるメール配送処理はシェルプログラムのようであり、 環境変数による動作の制御や情報の受け渡し、データのパイプライン、 コマンドの終了コードによる条件分岐といった動作をします。

MTA としての役割りと処理するプロセスの違い
役割り sendmail qmail
SMTP によるメール受信 sendmail qmail-smtpd
コマンドラインからのメール送信(受信) qmail-inject
メールをキューに登録 qmail-queue
キューの掃除 qmail-clean
キューに溜っているメールの送信 qmail-send
リモートユーザーへのメール送信 qmail-rspawn + qmail-remote
ローカルユーザーへのメール送信 mail.local qmail-lspawn + qmail-local
... ... ...

qmail は一つ1つのプロセスが小さく単純です。 しかも、ソースコードは sendmail の数分の一しかありません。 サイトを運用・管理する上で、 ソースコードに目を通し実装をより深く理解する必要に迫られることもあるので、 これは大きな利点です。

10.1.2 機能

「機能主義」に走り、 メールに関するあらゆる機能を取り入れている sendmail に対し、 qmail は純粋な MTA としての機能しか有していません。 qmail にはない sendmail の代表的な機能としては、 To:/From: フィールドのアドレス書き換えや補完、 複雑なメール配送の制御といったものがあります。 qmail と同じような目的の機能でも、 sendmail ではより柔軟な条件指定と制御が可能です。

sendmail は、 誤った動作をするクライアントに寛容という特徴もあります。 例えば、 SMTP 通信におけるコマンドやデータの 1行は CR (Carriage-Return, ASCII コードで 0x0D) と LF (LineFeed, 0x0A) で終っていなければならないと定められていますが、 これに従わず行末に LF だけを送信するクライアントがあります。 sendmail はそのような行も受け付けますが、 qmail (qmail-smtpd) は処理を中断します。 また、 メールクライアントが付加すべき Date:/Message-ID: といったヘッダーフィールドがメールに含まれていない場合、 sendmail は生成して付加しますが、 qmail はそのようなことはしません。

sendmail 特有の機能・振舞いに依存しているサイトから qmail へ移行するには、

  1. 同等の機能を実現する追加のソフトウェアをインストールし、利用する。
  2. 同等の機能を実現するパッチを qmail ソースに適用し、 そのソースから作成した qmail バイナリを利用する。
  3. 別の手段で同等の目的を実現 (あるいは同等の問題を回避) できないか検討し、 それを利用する。
  4. 1 + 2, 1 + 3, 2 + 3, あるいは 1 + 2 + 3
  5. しかたないと諦める。

と、少しばかり厄介です。 どれも不可であれば、 残念ながら qmail に移行することを諦め、 sendmail を使い続けることになります ただ筆者の経験では、 sendmail でなければならない場面に遭遇したことはありません。

10.1.3 設定ファイル

sendmail の設定は、 その難解さで有名な「sendmail.cf」という名前のファイルに記述します。 ご覧になったことがない方は、 sendmail がインスールされたシステムの /etc/sendmail.cf (あるいは /etc/mail/sendmail.cf) に目を通してみてください。 おおよそ、 人が読んで理解することを前提としていないことがわかるでしょう。 通常、sendmail.cf ファイルを直接編集することはせず、 sendmail 付属のツール cf や、 WIDE Project の中村素典氏により作成された CF (現在は開発停止) などを利用して、 より簡単なメタファイルから sendmail.cf を生成します。

cf や CF のメタファイルと比較しても、 qmail の設定ファイルは単純明解です。 設定項目ごとに設定ファイルが分離しており、 そのほとんどはたった 1行記述するだけで機能します。 qmail 付属のマニュアル qmail-control(5) を読めば、 どの設定ファイルがどの処理 (プロセス) に影響するか一目瞭然です。

時々「qmail は設定ファイルがたくさんあってわかりにくい」 といった声が聞かれますが、 sendmail.cf を理解するのと比較するとどうでしょうか。

10.1.4 メールボックスの形式

sendmail 標準のメールボックスは、 誰でも読み書きできる共有ディレクトリ (ただし /tmp のように他人のファイルは削除できない) 内の「mbox 形式」と呼ばれるファイルです。 mbox 形式のメールボックスファイルはユーザーごとに 1ファイルあり、 ファイル名はユーザーのログイン名となっています。 共有ディレクトリは、 一般的には /var/mail あるいは /var/spool/mail です。

mbox 形式のメールボックスは、 1つのファイルに複数のメールを保持するのも特徴です。 各メールは次のような行で始まり、最後に空白行が付きます。

From 送信者アドレス タイムスタンプ

sendmail 標準のメールボックスには、 次ような非常に悩ましい問題があります。

変種がいくつも存在する
qmail 付属のマニュアル mbox(5) で触れられているように、 少なくとも mboxrd, mboxo, mboxcl, mboxcl2 の 4種類のフォーマットが存在する。
ロックの方法が規定されていない
flock(2 or 3), lockf(3) によるロック, ロックファイルの作成のいずれか、 もしくはそれらの組み合わせで行なわれる。
NFS による共有は危険
旧来の NFS は flock(2 or 3), lockf(3) によるロックに対応していない。 ロックに対応している NFS の実装でも、安定していないと専らの評判である。
共有ディレクトリは危険
誰でも書き込めるディレクトリは、 しばしば DoS 攻撃 (Denial of Service, サービスを使用不能に陥れる攻撃) の標的にされる。

通常 qmail では、 各ユーザーのホームディレクトリにメールボックスを保持します。 上記のように扱い難い mbox 形式にも対応していますが、 より安全で信頼性の高い maildir 形式が利用できます。 maildir 形式は qmail 付属のマニュアル maildir(5) で解説されています。


10.2 sendmail からの移行の手順

この節では、 sendmail の停止から qmail に移行するまでの手順について解説します。 qmail 付属文書ファイル REMOVE.sendmail にも同様の解説がありますので、そちらも参考にするとよいでしょう。

より安全・確実に移行を実施したい場合は、 システムをシングルユーザーモードにして作業することをお勧めします。 シングルユーザーモードであれば、 メールサービスを利用する可能性のあるほかのサービス (POP3 サーバー、cron など) は 稼働しておらず、また、一般ユーザーはログインしていない状態になります。

もしくは、移行用に別のマシンを用意するとよいでしょう。 そちらに qmail を導入し、メールサービスを段階的に移行しましょう。 (ただしこの方法は本書では解説しません)

10.2.1 sendmail デーモンの停止

sendmail をインストールし利用しているなら、 システムのブート時に sendmail デーモンが起動し、 常駐するように設定されていることでしょう。 sendmail デーモンは、 SMTP 接続の待ち受けと定期的なキューの処理を行っています。 まずは sendmail デーモンのプロセスを停止し、 SMTP 経由でメール着信しないようにします (キューの扱いについては次節)。

sendmail デーモンプロセスを停止するには、 root で次のようにします。 ここで使用している ps コマンドは、 種類によってオプションや表示が異なることがあるのでご注意ください。

sendmail デーモンのプロセス ID の調査と停止 (BSD 系 ps):
# ps ax | grep sendmail
   291 ?        S  3:18 /usr/sbin/sendmail -bd -q15m
 26556 pts/12   S  0:00 grep sendmail
# kill 291
sendmail デーモンのプロセス ID の調査と停止 (System V 系 ps):
# ps -ef | grep sendmail
    root   291     1  0   Apr 25 ?        3:18 /usr/sbin/sendmail -bd -q15m
  fumiya 28199 28112  0 02:29:35 pts/12   0:00 grep sendmail
# kill 291

System V 系の起動スクリプトを採用しているシステムでは、 /etc/init.d (古い Red Hat Linux などでは /etc/rc.d/init.d) にある制御スクリプトを利用してもよいでしょう。

sendmail サービスの停止 (init スクリプト):
# /etc/init.d/sendmail stop

10.2.2 未配送メールの処理 (キューの掃き出し)

sendmail を無効にする前に、 sendmail のメールキューに滞留しているメールを配送させることを忘れないように注意してください。 qmail は sendmail のキューに関知しないため、 これを怠ると、sendmail のキューのメールは紛失したのと同然です。

sendmail キューの処理は sendmail -q コマンドで実行し、 キューの状態は mailq コマンドで確認します。

キューの掃き出しと確認:
# sendmail -q
# mailq
/var/spool/mqueue is empty

10.2.3 sendmail の無効化

sendmail をアンインストールする場合

なんらかのパッケージ管理システムにより sendmail がインストールされているなら、 それに従い適切な方法でアンインストールしてください。

しかし、 sendmail のようにシステムの標準的なサービスを提供するパッケージは、 ほかのパッケージに依存されいることでしょう。 パッケージ管理システムは、 sendmail がほかのパッケージに必要とされるため、 通常の方法では sendmail をアンインストールすることを拒否します。

次の例は、 logcheck パッケージが「smtpdaemon」に依存しているため、 それを提供している sendmail パッケージの削除が中断されています。

パッケージの依存関係によりアンインストールできない例 (RPM):
# rpm -e sendmail
error: removing these packages would break dependencies:
        smtpdaemon is needed by logcheck-1.1.1-2

qmail で sendmail の代替ができるのであれば、 依存関係を無視するオプションを指定して sendmail パッケージを強制的に削除しても問題ありません。 しかし、以下のような場合には注意が必要です。

sendmail 特有の仕様に依存しているパッケージがある場合
sendmail コマンドの特殊なオプションを利用するもの。 qmail には sendmail コマンド互換のインターフェイス (10.3.1 節を参照のこと) が用意されているが、 100% 互換性があるわけではない。
一昔前は sendmail が事実上標準の MTA であったため、 同じ時代に生れ育ってきたメールクライアントのいくつかは、 sendmail の持つインターフェイスや振舞いを前提として作成される。 例えば、メールの形式や送信方法といった仕様は、 本来なら RFC (RFC 2821 「Simple Mail Transfer Protocol」, RFC 2822 「Internet Message Format」) に準拠すべきだが、 「sendmail で問題ないからよし」と手を抜いて誤った動作をする実装がある。
qmail をパッケージ管理システム下に置かない場合
パッケージ管理システムは qmail の存在を知らないため、 システムには MTA がインストールされていないと判断する。 MTA を要求するパッケージを操作するたびに文句を言われることになるだろう。
面倒でも、お使いのパッケージ管理システムに合った qmail パッケージを作成したほうがよい。

sendmail をアンインストールしない場合

アンインストールしない場合は、 sendmail を介してのメールの送受信がされないようにします。 sendmail は以下のように利用されます。

  1. sendmail デーモンが提供する SMTP サーバーによる受信
  2. sendmail コマンドによるメール送信
  3. sendmail デーモンもしくは定期的な sendmail コマンド起動によるキューの処理
sendmail デーモンの無効化

ブート時のデーモンの起動設定はシステムの種類により異なり、 ブートスクリプト /etc/rc 中 (BSD 系、あるいは /etc/rc.local など) か、 /etc/rc?.d (あるいは /etc/rc.d/rc?.d) ディレクトリ中の sendmail スクリプト (System V 系) によって実現されています。

/etc/rc スクリプトの場合は、 スクリプト中の sendmail デーモンを起動する箇所をコメントアウトします。 例えば、FreeBSD 4.3 の /etc/rc スクリプト内には、 次のような箇所があります。 この部分の各行の行頭に、シェルスクリプトのコメントを表す 「#」を付けます。

sendmail デーモンの起動箇所 (FreeBSD 4.3 の /etc/rc):
case ${sendmail_enable} in
[Yy][Ee][Ss])
    if [ -r /etc/mail/sendmail.cf ]; then
        echo -n ' sendmail'; /usr/sbin/sendmail ${sendmail_flags}
    fi
    ;;
esac
sendmail デーモン起動の無効化 (FreeBSD 4.3 の /etc/rc):
#case ${sendmail_enable} in
#[Yy][Ee][Ss])
#    if [ -r /etc/mail/sendmail.cf ]; then
#        echo -n ' sendmail'; /usr/sbin/sendmail ${sendmail_flags}
#    fi
#    ;;
#esac

FreeBSD 4.0 以降の場合、 sendmail デーモンの起動を /etc/rc.conf ファイルの記述で制御することができます (詳しくはマニュアル rc.conf(5) を参照のこと)。 このように、標準的な方法はシステムにより異なることがありますのでご注意ください (後述の System V の場合も同様)。

System V 系では、 sendmail デーモンの起動スクリプトが /etc/rc?.d/SNNsendmail (あるいは /etc/init.d/rc?.d/SNNsendmail, ? は英数字, NN は 2桁の数字) に置かれています。 それらは /etc/init.d/sendmail (/etc/rc.d/init.d/sendmail) とのハードリンクもしくはシンボリックリンクなっています。 これを削除ないしは移動することで無効化します。

sendmail デーモンの無効化 (System V 系, _SNNsendmail に移動する場合):
# cd /etc
# for r in rc?.d; do (cd $r && eval 's=`ls S??sendmail`' && mv $s _$s); done

Red Hat Linux あるいはその派生システムでは、 「chkconfig --del sendmail」で システムブート時の sendmail デーモンの起動を無効にすることができます。

定期的な sendmail コマンド起動の無効化

SMTP サービスを提供しないシステムでは sendmail デーモンは稼働せず、 送信キューに滞留しているメールを処理するため、 定期的に sendmail コマンドを起動するように設定されています。 定期的な処理は cron デーモンを利用します。

root の cron テーブル (crontab -e で編集)、 あるいは /etc/cron.d/etc/cron.hourly ディレクトリ内のスクリプトで 「sendmail -q」を実行している箇所がないか調べ、 無効にしてください。

sendmail コマンドの無効化

Windows で動作するメールクライアントは、 メールの送信に SMTP サーバーを利用するのが一般的です。 一方、UNIX で動作するメールクライアントは、 メール送信用のコマンドを利用するものがあります。 代表的なメール送信用コマンドとしては mail コマンドや mailx コマンドが一般的ですが、 sendmail コマンドもその中の一つです。

mail, mailx コマンドはメールクライアントの一種で、 その内部では sendmail コマンドを利用してメールの送信を行います。 このため sendmail コマンドが利用できないと sendmail コマンドを利用しているメールクライアントはもちろん、 mail, mailx コマンドによるメール送信もできなくなってしまいます。 この問題は 「10.3.1 qmail の sendmail 互換コマンドインターフェイス」 の節で紹介する qmail 付属の sendmail コマンドを利用して回避します。

sendmail コマンドは、 /usr/sbin/sendmail /usr/bin/sendmail, /usr/lib/sendmail といった場所にあるので、 これを実行できないようにしましょう。 いずれかがシンボリックリンクになっていることがありますのでご注意ください。

sendmail コマンドの無効化:
# cd /usr/sbin
# ls -l sendmail
-r-sr-xr-x  1 root  other  316348 Aug 19  2000 sendmail
# mv sendmail sendmail.dist
# chmod 0 sendmail.dist
# ls -l sendmail.dist
----------  1 root  other  316348 Aug 19  2000 sendmail.dist

sendmail コマンドは元に戻せるように削除はせず、 移動だけします。 また、移動した sendmail コマンドが誤って実行されないように、 アクセス許可をすべて落すことをお勧めします。 sendmail コマンドは root に setuid されて実行されるため、 ローカルユーザーによって sendmail のセキュリティホールを突かれる恐れがあります。

以上の sendmail コマンド無効化の手順は、 FreeBSD 4.0 以降には適用できません。 FreeBSD 4.0 以降の /usr/sbin/sendmail コマンドはラッパーで、 mailer.conf(5) により実際に起動されるコマンドを切り換えるようになっています。

sendmail をアンインストールしない場合の注意点

sendmail パッケージをアンインストールせずに qmail を導入した場合は、 システムのアップグレードやパッチを適用する際に注意が必要です。 例えば、「10.3 sendmail 互換環境を作る」 で紹介している qmail 付属の sendmail コマンドや fastforward 付属の newalias コマンドを sendmail のものと置き換えていると、 アップグレードやパッチを適用した際に、 新しい sendmail パッケージのコマンドに上書きされてしまう恐れがあります。 無効にした sendmail デーモンの起動が復活して、 qmail-smtpd と衝突することも考えられます。

10.2.4 メールボックスの移行

qmail の標準では、 各ユーザーのホームディレクトリ内 に、 mbox 形式か maildir 形式のメールボックスにメールを配送します。 sendmail 時代のメールボックスは、 誰でも読み書きできる共有ディレクトリ内に mbox 形式で保持されていますので、 これを qmail が扱うメールボックスに移行しなければなりません。

qmail (qmail-local) がメールボックスへのメール配送に procmail や mail.local コマンドなど使用するように設定され、 sendmail と同じパス/同じ形式のファイルのメールボックスに配送するのであれば、 この作業は必要ありません。 (10.3.4 節)

maildir 形式のメールボックスへの移行

sendmail の mbox 形式のメールボックスから qmail 標準の maildir 形式のメールボックスに変換するには、 mbox2maildir コマンドを利用します。 mbox2maildir は qmail には付属していないため、別途入手してください。 いくつかの変種がありますが、代表的なものは以下から入手できます。 このコマンドは Perl スクリプトですので、 別途 Perl が必要です。

mbox2maildir コマンドの所在
http://www9.jp.qmail.org/mbox2maildir (ミラー)
http://www.qmail.org/mbox2maildir

このコマンドは変換元と変換先のメールボックスを環境変数で指定します。 以下に実行例を示します。 sendmail 標準の mbox 形式のメールボックスファイルは、 共有メールスプールディレクトリ /var/mail (もしくは /var/spool/mail) 以下にあります。 ファイル名はユーザーのログイン名です。

mbox2maildir によるメールボックス形式の変換:
$ MAIL=/var/mail/fumiya
$ MAILDIR=$HOME/Maildir
$ export MAIL MAILDIR
$ mbox2maildir

この mbox2maildir コマンドには次のような問題があり、 あまり柔軟性はありません。 そのままでは特定の場面でしか利用できません。 qmail への移行の段階で、メールサービスを停止して変換作業を行うのであれば、 2. は問題とはなりません。

  1. mbox 形式の変種に対応していない
  2. mbox 形式のメールボックスのアクセス時にロック処理をしない
  3. 変換元の mbox 形式のメールボックスを削除してしまう

mbox2maildir コマンドと同じような目的のコマンドは多数存在します。 mbox2maildir に満足できないのであれば、 別途、目的に合ったコマンドを探してみてください。 それでも満足できるものがなければ、それらを参考にして、 ご自分の mbox2maildir コマンドを作成しましょう。

Google (http://www.google.com/) でキーワード「mbox2maildir」で検索してみたところ、 次のような変換ツールを見つけることができました。 しかし、 mbox 形式の変種に対応しているものは見つけることができませんでした。

そのほかの変換ツールの所在
http://www.nm.net/pub/qmail/yammc.pl
http://www.myrddin.demon.co.uk/scripts.html
http://archives.neohapsis.com/archives/postfix/1999-q4/1477.html

ホームディレクトリ 内の mbox 形式メールボックスへの移行

qmail (qmail-local) は、 mbox 形式のメールボックスへの配送に対応していますが、 sendmail のような共有メールスプールディレクトリではなく、 各ユーザーのホームディレクトリ内に保持します。

sendmail 時代に利用していた IMAP/POP サーバーやメールクライアントに対応するため、 共有メールスプールから各ユーザーのメールボックスへシンボリックリンクを作成するとよいでしょう。 もちろん、 各 IMAP/POP サーバーとメールクライアントのほうで対応することもできますが、 シンボリックリンクにより旧来と同じパスでメールボックスを参照できるようにするほうが手間がかかりません。

次に作業の例を示します。 この例では共有メールスプールは /var/mail になっていますが、 システムにより適宜読み換えてください (/var/spool/mail など)。 この作業は、既存のユーザーのメールボックスのことだけを考慮しています。 新規にユーザーを追加した場合、同様の作業を行うのを忘れないようにしてください。

ホームディレクトリのメールボックスを sendmail 時代のパスで参照できるようにする:
# cd /home
# for n in *; [ -d $n ] && ln -s /home/$n/Mailbox /var/mail/$n; done

maildir 形式から mbox 形式への変換

主なメールクライアントは、正式あるいはパッチによって maildir 対応がなされています。 しかしいくつかのメールクライアント、特にユーザーが少ないものや古いもの、 そして開発が停止しているものは、maildir に対応していません。 そんな時に助けになるのが qmail 付属の maildir2mbox コマンドです。

maildir 形式に対応していないメールクライアントを利用しているユーザーは、 maildir2mbox を利用して、 定期的に maildir から mbox への変換するようにします。

maildir2mbox は、次の環境変数を介してメールボックスの位置を知ります。 いずれも絶対パスを指定しなければなりません。

MAILDIR
変換元の maildir 形式のメールボックスディレクトリのパス名
MAIL
変換先の mbox 形式のメールボックスファイルのパス名
MAILTMP
変換処理中に使用する mbox 形式メールボックスファイルのパス名
MAIL に指定したパスと同じファイルシステム内のパスでなければならない (変換処理終了後に MAIL で指定された名前にリネームするため)

例として、 ユーザーが簡単にメールボックスの変換を行えるスクリプト maildir2mbox.sh を用意しました。 mbox 形式のメールボックスが必要なユーザーは、 適宜このスクリプトを起動するか、 ユーザー自身の crontab(5) に記述して定期的に実行するように設定するとよいでしょう。

maildir2mbox を利用したメールボックス変換スクリプトの例 (maildir2mbox.sh):
#!/bin/sh

if [ -z "$HOME" ]; then
    echo "HOME not set"
    exit 1
fi

MAILDIR=$HOME/Maildir
MAIL=$HOME/Mailbox
MAILTMP=$HOME/.maildir2mbox.$$.tmp
export MAILDIR MAIL MAILTMP

/var/qmail/bin/maildir2mbox
メールボックス変換スクリプトをユーザー自身の cron テーブルに登録:
0 * * * * /usr/local/bin/maildir2mbox.sh

10.2.5 POP/IMAP サーバーの移行

POP サーバーや IMAP サーバーを利用しているなら、 ホームディレクトリのメールボックスを参照するように設定変更してください。 mbox 形式であってもホームディレクトリ内のメールボックスに対応していなかったり、 maildir 形式に対応していない POP/IMAP サーバーもあります。 コンパイル時オプションやソースにパッチに適用するなどして再コンパイル、 インストールするか、別のソフトウェアに乗り換えてください。

qmail (qmail-local) がメールボックスへのメール配送に procmail や mail.local コマンドなど使用するように設定され、 sendmail と同じパス/同じ形式のファイルのメールボックスに配送するのであれば、 この作業は必要ありません。 (10.3.4 節)

10.2.6 メールクライアントの設定変更

IMAP や POP サーバーを利用せずに直接メールボックスを参照するメールクライアントは、 設定を変更して maildir 形式のメールボックスを参照するようにします。 方法はメールクライアントによって異なりますので、 詳細はお使いのメールクライアントのマニュアルなどを参照してください。

mbox 形式のメールボックスに配送しているのであれば、環境変数 MAIL を変更してホームディレクトリ内のメールボックスを指すようにしましょう。 MAIL環境変数は mbox 形式のメールボックスを指示するもので、 /bin/mail などのいくつかの UNIX のメールクライアントが参照します。 これに従わないメールクライアントもありますのでご注意ください。

メールボックスの場所の指定 - Bourne shell 系の場合 (/etc/profile に追加):
MAIL=$HOME/Mailbox
export MAIL
メールボックスの場所の指定 - C shell 系の場合 (/etc/csh.cshrc に追加):
setenv MAIL $HOME/Mailbox

maildir に対応していないメールクライアントの救済については、 10.2.4 節 の「maildir 形式から mbox 形式への変換」の節を参照してください。

10.2.7 エイリアスと転送設定の移行

エイリアスの移行

sendmail の /etc/aliases ファイル (あるいは /etc/mail/aliases) のエイリアスの設定を、 qmail の users/assign と エイリアス用ユーザー alias の .qmail ファイルに移行します。

qmail はユーザー root 宛のメールの配送は行ないません。 ~alias/.qmail-root ファイルを用意して、 ユーザー alias で受け取るか別のアドレスに転送するようにしてください。 これを怠ると、root 宛のメールが紛失してしまいますのでご注意ください。

sendmail のエイリアスには、 伝統的に「nobody」というテスト用の名前が定義されています。 この定義により nobody 宛のメールを受信しますが、 そのまま /dev/null に捨てるようになっています。 これを qmail で実現するには、.qmail ファイルにコメントだけを記述します。

エイリアス nobody の定義:
# cd /var/qmail/alias
# echo '#' > .qmail-nobody
# chmod 644 .qmail-nobody

qmail で sendmail の /etc/aliases ファイルを利用する方法については、 「10.3.2 /etc/aliases によるエイリアス設定」を参照のこと。

ユーザーごとの転送設定の移行

sendmail のユーザーごとの転送設定である ~/.forward ファイルを qmail の ~/.qmail に移行します。 移行の際には次の表を参考にしてください。 表中の preline, forward は qmail 付属のコマンドです。 .qmail については qmail 付属のマニュアル dot-qmail(5) に記述されています。 「第7章 .qmail ファイルの利用」も参照のこと。

.forward と .qmail の転送先指定の記述の違い
転送先の種類 sendmail + .forward qmail (qmail-local) + .qmail
コメント # comment # comment
アドレスへ転送 username@example.com &username@example.com
ローカルユーザーへ転送 username 未対応
代替案: |forward "username@$HOST"
代替案: &username (control/envnoathost に依存)
ローカルコピー 自分のユーザー名を記述 自分のメールボックスのパスを記述
例: ./Maildir/
mbox 形式メールボックスへ出力 /path/to/outputfile /path/to/outputfile
.forward 用コマンドの利用 "|/path/to/command args" |preline /path/to/command args
転送先リストの取り込み :include:/path/to/listfile 未対応
代替案: |forward `cat /path/to/listfile`
複数の転送先 それぞれ別の行に記述
1行にカンマ区切りで列挙可
それぞれ別の行に記述

qmail で sendmail の ~/.forward ファイルを利用する方法については、 「10.3.3 ~/.forward によるメールの転送」 を参照のこと。

10.2.8 qmail デーモンの稼働

ここまで来れば、快適な qmail の世界まであと少しです。 最後に qmail のデーモンを稼働させ動作を確認したら、 いよいよサービススタートしましょう。

おめでとうございます。 ようこそ、qmail の世界へ!


10.3 sendmail 互換環境を作る

この節では、 追加のソフトウェアをインストールしたり qmail の設定に手を加えることで、 sendmail と同じような機能・振舞いを実現する方法を紹介します。 次のような場合に有用です。

sendmail 互換とすることにより、 qmail の長所が生かされないことがあります。 また、互換環境を実現するための仕掛けがトリッキーなものがあり、 環境が複雑になってしまいます。 原理はもちろん、利点・欠点をよく理解の上、導入するようにしてください。

10.3.1 qmail の sendmail 互換コマンドインターフェイス

10.2.3 節 の 「sendmail コマンドの無効化」で触れたように、 メールの送信を sendmail コマンドで実行するメールクライアントが存在します。 CGI や何らかの通知システムなどが 直接 sendmail コマンドを利用してメールを送信することもあります。 qmail ではこれに対応するため、 その名もずばり「sendmail」という名前の sendmail 互換のコマンドが付属しています。

qmail の sendmail 互換コマンドは、 通常のインストール形態では /var/qmail/bin/sendmail に置かれています。 これを本物の sendmail が置かれていたパスから参照できるように、 シンボリックリンクを作成しましょう。 sendmail コマンドは /usr/sbin/sendmail, /usr/bin/sendmail, /usr/lib/sendmail といった場所にあるので、 そこから /var/qmail/bin/sendmail へのシンボリックリンクを作成します。

qmail の sendmail 互換コマンドを一般的なパスで参照できるようにする:
# ln -s /var/qmail/bin/sendmail /usr/sbin/sendmail

10.3.2 /etc/aliases によるエイリアス設定

sendmail では、エイリアスアドレスの設定を /etc/aliases ファイルで指定します。 qmail には、sendmail の aliases ファイルを利用するための fastforward というソフトウェアがあります。 fastforward は、qmail と同じく D. J. Bernstein 氏による作品です。

fastforward の Web サイト
http://cr.yp.to/fastforward.html
http://www.jp.qmail.org/tools/fastforward.html (ミラー)

fastforward のインストール

fastforward のコンパイルとインストールの手順は qmail とほぼ同様です。 実行バイナリとマニュアルも qmail と同じく /var/qmail 以下にインストールされます。

fastforward のソースの所在
http://cr.yp.to/software/fastforward-0.51.tar.gz
ftp://ftp.jp.qmail.org/qmail/fastforward-0.51.tar.gz (ミラー)
fastforward のコンパイルとインストール:
$ gzip -dc fastforward-0.51.tar.gz | tar xf -
$ cd fastforward-0.51
$ make it install instcheck 2>&1| tee make.out
… バイナリなどのコンパイル状況 …
$ su
Password: root のパスワード
# make setup
./install
# make check
./instcheck

fastforward には「newaliases」という名前のコマンドが付属しています。 このコマンドは sendmail の newaliases コマンドと同じ目的のもので、 実行すると、 テキスト形式の aliases ファイルからバイナリのエイリアスデータベースファイルを生成します (双方のデータベースに互換性はありません)。 必要であれば、 qmail の newaliases コマンドを sendmail のものと同じパスで参照できるようにしてください。

qmail の newaliases コマンドは /etc/aliases ファイルを参照しますが、 最近の sendmail のエイリアスファイルは /etc/mail/aliases にあります。 これも調整しておくと便利です。 最初から /etc/aliases から /etc/mail/aliases にシンボリックリンクが張られているシステムもあります。

newaliases コマンドと aliases ファイルのパスの調整:
# ln -s /var/qmail/bin/newaliases /usr/sbin/newaliases
# ln -s /etc/mail/aliases /etc/aliases

fastforward の各種バイナリ/ソースパッケージ

バイナリ/ソース RPM パッケージ (Red Hat Linux など)
http://www.webideal.de/qmail/ (SRPM)
http://untroubled.org/rpms/fastforward/ (SRPM, 少し古い)
http://www.rpmfind.net/linux/rpm2html/search.php?query=fastforward (Mandrake Linux 向け)
Debian GNU/Linux
「fastforward-src」というパッケージをインストールし、 build-fastforward コマンドを実行してバイナリパッケージを作成する
FreeBSD など
FreeBSD の「qmail-contrib」という port に含まれている

fastforward を qmail 環境へ組込む

まず始めに、 /etc/aliases ファイルからエイリアスのデータベースファイル /etc/aliases.cdb を作成しておきます。 この作業は aliases ファイルを更新する度に実行する必要があります。

エイリアスデータベースの更新:
# /var/qmail/bin/newaliases

fastforward は、 qmail のエイリアス処理用のユーザー alias の .qmail-default ファイルに組込みます。

7.2 拡張メールアドレス」で解説しているように、 .qmail による拡張アドレス定義 .qmail-default ファイルは特別で、 ほかの拡張アドレスに一致しない場合には .qmail-default ファイルの設定に従いメール配送されます。 これと同様に、 ユーザー alias の .qmail-default ファイルもワイルドカードアドレスとして働きます。 つまり、既存のユーザーとエイリアスのどれにも一致していない場合にデフォルトの配送指定として ~alias/.qmail-default が評価されます。

というわけで、~alias/.qmail-default に fastforward コマンドを起動する記述をします。 fastforward のコマンドライン引数には、 エイリアスデータベースファイルのパスを指定します。

fastforward の qmail への組込み:
# cd /var/qmail/alias
# echo '|fastforward /etc/aliases.cdb' > .qmail-default
# chmod 644 .qmail-default

fastforward の互換性

qmail + fastforward によるエイリアスの動作は、 sendmail の動作とはいくつか異なります。

ファイルへの出力には対応していない

エイリアスアドレス宛に届いたメールをファイルに出力させることはできません。 ユーザー alias の .qmail ファイルを利用してください。

:include: 構文でインクルードされるファイルの扱い

:include: 構文でインクルードされる外部のアドレスリストファイルは、 直接参照されません。 事前に newinclude コマンドを使用して、 バイナリファイルを生成しておかねばなりません。 詳細は newinclude(1) を参照のこと。

/etc/aliases は一番最後に評価される

qmail は、 自ホスト宛のメールの配送先を以下のような順番で評価し、決定します。 いずれかの段階で宛先アドレスに対応する配送先が見つかれば、 それ移行の評価は行いません。

  1. users/assign による宛先アドレスとユーザーの対応表
  2. 宛先アドレスのローカル部と一致している UNIX ユーザー
  3. ~alias/.qmail-aliasname によるエイリアス設定

この中でもエイリアスのワイルドカードである ~alias/.qmail-default ファイルは、 一番最後に評価されます。 このため、 fastforward による /etc/aliases ファイルのエイリアス指定は、 ローカルユーザーへのメール配送を制御 (上書き) することはできません。

sendmail は、 /etc/aliases の指定をローカルユーザーより先に評価します。

10.3.3 ~/.forward によるメールの転送

sendmail では、ユーザーごとのメールの転送設定を .forward ファイルで指定します。 qmail には .forward ファイルを利用するための dot-forward というソフトウェアがあります。 dot-forward は、qmail と同じく D. J. Bernstein 氏による作品です。

dot-forward の Web サイト
http://cr.yp.to/dot-forward.html

dot-forward のインストール

dot-forward のコンパイルとインストールの手順は qmail とほぼ同様です。 実行バイナリとマニュアルも qmail と同じく /var/qmail 以下にインストールされます。

dot-forward のソースの所在
http://cr.yp.to/software/dot-forward-0.71.tar.gz
ftp://ftp.jp.qmail.org/qmail/dot-forward-0.71.tar.gz (ミラー)
dot-forward のコンパイルとインストール:
$ gzip -dc dot-forward-0.71.tar.gz | tar xf -
$ cd dot-forward-0.71
$ make it install instcheck 2>&1| tee make.out
… バイナリなどのコンパイル状況 …
$ su
Password: root のパスワード
# make setup
./install
# make check
./instcheck

dot-forword の各種バイナリ/ソースパッケージ

バイナリ/ソース RPM パッケージ (Red Hat Linux など)
http://untroubled.org/rpms/dot-forward/ (少し古い)
http://www.rpmfind.net/linux/rpm2html/search.php?query=dot-forward (Mandrake Linux 向け)
Debian GNU/Linux
「dot-forward-src」というパッケージをインストールし、 build-fastforward コマンドを実行してバイナリパッケージを作成する
FreeBSD など
FreeBSD の「qmail-contrib」という port に含まれている

dot-forward を qmail 環境へ組込む

dot-forward は、 qmail のメール配送エージェントのスタートアップコマンド qmail-start に「デフォルトの配送方法の指定」引数として指定します。 この引数は qmail-lspawn を介して qmail-local に渡され、 宛先メールアドレスのローカル部に対応する .qmail ファイルがない場合のデフォルトの配送方法となります。

qmail-start のコマンドラインは qmail によるメール配送のスタートアップスクリプト /var/qmail/rc に記述されているので、 このスクリプトを書き換えます (独自のスタートアップスクリプトを使用しているなら、 もちろんそちらを書き換える必要があります)。 スタートアップスクリプトを /var/qmail/boot/home からコピーして用意した場合、その中身は次のようになっています (コメントは省略)。

デフォルトで ~/Mailbox へ配送するためのスタートアップスクリプト (/var/qmail/rc):
#!/bin/sh
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start ./Mailbox splogger qmail

この状態では qmail-start の第1引数(デフォルトの配送方法の指定)に 「./Mailbox」が指定されており、 デフォルトではホームディレクトリの mbox 形式のメールボックスに配送されることがわかります。 これに dot-forward を組み込むと、次のようになります (実は /var/qmail/boot/home+df と同一)。

dot-forward を組み込んだスタートアップスクリプト (/var/qmail/rc):
#!/bin/sh
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start '|dot-forward .forward
./Mailbox' splogger qmail

少しわかりにくいですが、qmail-start の第1引数は 「|dot-forward .forward」 + 改行 + 「./Mailbox」 となります (シングルクォート「'」で括られている部分)。 これを見てわかるように、 qmail-start (qmail-local) のデフォルトの配送方法指定の形式は、 .qmail ファイルに記述する形式とまったく同じです。 (→「第7章 .qmail ファイルの利用」)

dot-forward は標準入力からメールを受け取り、 コマンドライン引数で指定されたファイル (この例では .forward) に従いメールを転送し、配送の成功を示す終了コード 99 を返します。 .forward ファイルが存在しない場合はなにも実行しませんが、 続く配送指定の実行を促すために終了コード 0 を返します。 また、 転送先に自分自身のユーザー名かメールアドレスが指定されていた場合も終了コード 0 を返します。 このため、前者の場合は転送処理だけ実行されますが、 後者の場合は qmail-local により「./Mailbox」への配送も実行されます。 .qmail から起動するコマンドの終了コードの意味と qmail-local の動作についてはマニュアル qmail-command(8) に解説されていますので、そちらをご覧ください。 (→「7.3 コマンドによるメールの処理」)

dot-forward の互換性

qmail + dot-forward による転送の動作は、 sendmail の動作とはいくつか異なります。 以下に代表的な違いを紹介しますが、 詳細はマニュアル dot-forward(1) を参照してください。

ファイルへの出力には対応していない

メールをファイルに出力させることはできません。 .qmail ファイルを利用してください。

ユーザー名の先頭に付けたバックスラッシュは無効

sendmail では、 .forward ファイルで指定された転送先のユーザー名は、 エイリアスの設定 (/etc/aliases) で評価されます。 また、転送先のユーザーが .forward ファイルを持っているなら、 その指定に従って転送します。 この動作は、 ユーザー名の頭にバックスラッシュ「\」を付けることで抑制することができます。

qmail (dot-forward) では、バックスラッシュはなにも意味を持ちません。 バックスラッシュが付いていても、付いていないのと同じように評価され、 動作にはなんら影響しません。

転送先のユーザー名が自分自身の場合は、 エイリアスも(当然)転送の設定も無視され、 ローカルのメールボックスに配送されます。 転送先がほかのユーザー名あるいはメールアドレスの場合、 qmail-inject と同じ規則でアットマークやドメイン名が付加され、 送信キューに登録されます。

転送先の種類の解釈の違い

sendmail は転送先の種類を以下のように判別します。

縦線「|」で始まっている
コマンド
「|」を除いたものをコマンドとして起動し、メールを標準入力に渡す
スラッシュ「/」で始まっている
パス名
メールをこのパスのファイルへ出力する (mbox 形式)
元の宛先アドレスのローカル部と同一
コピーの指示
デフォルトのメールボックスへ配送する
そのほか
メールアドレス
このメールアドレスへ転送する

一方、qmail (dot-forward) では、以下の順番で判別を試みます。

元の宛先アドレスのローカル部と同一
元の宛先アドレスと同一
コピーの指示
デフォルトのメールボックスへ配送する
クォートされていないアットマーク「@」が含まれる
メールアドレス
このメールアドレスへ転送する
縦線「|」で始まっている
コマンド
「|」を除いたものをコマンドとして起動し、メールを標準入力に渡す
そのほか
メールアドレス
このメールアドレスへ転送する

10.3.4 sendmail と同じメールボックスへの配送

qmail の安全性の高いホームディレクトリへの配送を捨てて、 sendmail と同じ共有スプールディレクトリへの配送を実現する方法を紹介します。 maildir 形式と比較すると、信頼性も失われることを認識しておいてください。 qmail の付属文書ファイル INSTALL.vsm にも同様の解説があります。

sendmail のローカルメーラー

sendmail は自ホスト宛のメールをメールボックスに配送するときに、 「ローカルメーラー」あるいは「MDA (Mail Delivery Agent)」 と呼ばれる外部コマンドに依頼します。 sendmail とローカルメーラーは sendmail.cf で指定された手順で通信します。 ローカルメーラーとの通信の手順を制御する細かいオプションが多数用意されていますが、 おおまかに分類すると代表的な通信手順は以下の 2種類に分けられます。

  1. コマンドライン引数で宛先のユーザーを指示し、標準入力にメールを渡す
  2. 標準入出力を介して SMTP のような手順 (LMTP, RFC 2033 「Local Mail Transfer Protocol」) で宛先のユーザーとメールを渡す

この中で、1. のような通信をサポートするローカルメーラーであれば、 qmail (qmail-local) から利用することできます。

sendmail のローカルメーラーを qmail 環境へ組込む

qmail は自ホスト宛のメールの配送に qmail-local を使用します。 qmail-local は、 qmail-start を介して指定されたデフォルトの配送方法に従って配送しますので、 qmail-start を起動するスタートアップスクリプトを変更し、 qmail-local が sendmail のローカルメーラーを使用して配送するようにします。 手順は 10.3.3 節 の dot-forward の組み込むと同様ですので、 合わせてそちらも参照しておくと理解できるでしょう。

sendmail のローカルメーラーは、 標準では /usr/libexec/mail.local, /bin/mail といったものが利用されます。 これらはコマンド名が同じでも置かれているパスや仕様がシステムによって異なるため、 ここで全てを紹介することはできません。 そこで本書では、Solaris 8 における例を紹介します。 そのほかのシステムをお使いの場合は、 qmail 付属の /var/qmail/boot にあるスタートアップスクリプトを参考にしてください。

sendmail ローカルメーラーを利用するためのサンプルスタートアップスクリプト (/var/qmail/boot)
スクリプト名 対応するシステム
binm1 BSD 系 (/usr/libexec/mail.local -r)
binm1+df 同上 + dot-forward
binm2 System V Release 4 (SVR4) 系 (/bin/mail -r)
binm2+df 同上 + dot-forward
binm3 UNIX V7 (/bin/mail -f)
binm3+df 同上 + dot-forward
proc procmail (後述)
proc+df 同上 + dot-forward

Solaris 8 付属の sendmail は、 標準では /usr/lib/mail.local -l をローカルメーラーとして使用しています。 -l オプションはマニュアル mail.local(1M) には記載されていませんが、LMTP (Local Message Transfer Protocol, RFC 2033) で sendmail と通信するための指定です。 qmail-local は LMTP による通信には対応していないので、 -l オプションは指定しません。 そして、送信者のアドレスと宛先のユーザーはコマンドライン引数で指定します。

mail.local を組み込んだスタートアップスクリプト (/var/qmail/rc, Solaris 8):
#!/bin/sh
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start \
'|preline -f /usr/lib/mail.local -f "${SENDER:-MAILER-DAEMON}" "$USER"' \
splogger qmail

qmail 付属の preline コマンドは、 メールに先頭の「From 送信者アドレス タイムスタンプ」行、 Return-Path: フィールド、Delivered-To: フィールドを付加し、 指定されたコマンドに渡すラッパーコマンドです。 マニュアル qmail-command(8) で解説されているように、 qmail ではそれらの情報を環境変数によりコマンドに渡すようになっていますが、 sendmail 向けに作成されたコマンドは理解できません。 メール先頭の「From 」行の付加は mail.local が行うので、 ここでは preline に -f オプションを指定して「From 」行の付加を抑制しています。 (→「7.3.2 qmail 付属の .qmail 用コマンド」の「.forward 用コマンドの利用 - preline」)

環境変数 SENDER は送信者のメールアドレス、 USER はメールボックスの所有者のユーザー名です。 詳細は 「7.3.1 どのようにしてコマンドが起動されるのか」か、 マニュアル qmail-command(8) をご覧ください。

procmail を qmail 環境へ組込む

メールのフィルタリングや振り分けなどに利用されるソフトウェア、 procmail を組み込む例を紹介します。 procmail は sendmail のローカルメーラーとして利用されることもあり、 デフォルトの配送先は sendmail と同じ共有スプールディレクトリ内の mbox 形式のメールボックスです。

厳密なパッケージ管理システムの下では qmail パッケージと sendmail パッケージが共存できず、 qmail から sendmail パッケージに含まれるローカルメーラーを利用できないことが考えられます。 そんな場合には、 sendmail とは独立している procmail を利用するとよいでしょう。

procmail の Web サイト
http://www.procmail.org/
procmail のソースの所在
ftp://ftp.procmail.net/pub/procmail/
ftp://ftp.ring.gr.jp/pub/net/mail/procmail/ (ミラー)

以下に procmail のインストール例を示します。 付属の Makefile では /usr にインストールされますが、 この例では /usr/local にインストールされるよう変更しています。 また、コンパイル中にロックのテストのための追加ディレクトリの入力を求められますが、 通常は必要ありませんのでリターン (Enter キー) だけ入力してください。 カスタマイズしてコンパイルするには、 make する前に Makefileconfig.h ファイルを編集してください。 詳細は付属の INSTALL ファイルを参照のこと。

procmail のコンパイルとインストール:
$ gzip -dc procmail-3.22.tar.gz | tar xf -
$ cd procmail-3.22
$ cp -p Makefile Makefile.dist
$ sed 's!^BASENAME.*=.*$!BASENAME=/usr/local!' < Makefil.dist > Makefile
$ make 2>&1| tee make.out
… コンパイル前の準備 …
I will temporarily use a testdirectory named _locktest
in the following directories:

/tmp .

If you would like to add any, please specify them below,
press return to continue:

リターンのみ入力
… ロックのテスト、バイナリなどのコンパイル状況 …
$ su
Password: root のパスワード
# make install-suid
… バイナリのインストール状況 …
# make install.man
… マニュアルのインストール状況 …

このインストールの例では procmail は /usr/local/bin/procmail に置かれるので、 スタートアップスクリプトは次のようになります。

procmail を組み込んだスタートアップスクリプト (/var/qmail/rc):
#!/bin/sh
exec env - PATH="/var/qmail/bin:/usr/local/bin:$PATH" \
qmail-start '|preline procmail' splogger qmail

10.3.5 必要なヘッダーフィールドが付けられていないメールの矯正

RFC 2822 「Internet Message Format」によると、 インターネットメールには From:/Date: フィールドが必須と定義されています。 また同文書には、メールを一意に識別するための Message-ID: フィールドも「付けるべき」と定義しています。 よって、 これらのヘッダーフィールドは、 メールの生成と送信を行うメールクライアントが付加すべきものですが、 メールクライアントの中にはこれに従わないものが存在します。

sendmail は必須とされるヘッダーフィールドが含まれていないメールを受信すると、 自前で生成しメールに付加してから配送します。 しかし、純粋にメールの配送処理しか行わない qmail は、 経路情報を示すフィールド (Received:/Delivered-To: フィールド) を追加する以外、メールを書き換えることはありません。 このため、sendmail から qmail に以降すると、 メールクライアントの不具合が健在化します。

壊れたメールが矯正されるまでの流れ

qmail の FAQ に、この問題に対処するための方法が紹介されています。

How do I fix up messages from dumb clients?
http://cr.yp.to/qmail/faq/servers.html#network-rewriting
http://www.jp.qmail.org/qmail/faq/servers.html#network-rewriting (日本語訳)

ここで紹介されている設定を施すと、 SMTP (qmail-smtpd) 経由で受信したメールが、 次の図のような流れで配送・加工が行なわれます。

図: 必要なヘッダーフィールドがないメールの矯正 (FAQ に紹介されている手法)

    問題のあるメールクライアント (1)
        宛先アドレス bob@example.com
        Date:/Message-ID: フィールドなし
        |
        v
    tcpserver (RELAYCLIENT="@fixme")
    qmail-smtpd (2)
        宛先アドレス bob@example.com@fixme
        Date:/Message-ID: フィールドなし
        |
        v
    qmail-send (3)
        |
        v
    ~alias/.qmail-fixup-default (4)
    qmail-inject
        宛先アドレス bob@example.com
        Date: ...
        Message-ID: ...
        | (5)
        v
    qmail-send
        |
        v
    ......

(1)メールクライアントからメールを送信します。 (2)qmail-smtpd は特定のクライアントからメールを受信したときに、 宛先アドレスを書き換えて「実際の宛先アドレス@fixme」宛に送付します。 (3)「fixme」ドメイン宛のメールは自ホストの仮想ドメインで受け取るように設定されているため、 qmail-send は virtualdomains の設定に従って ローカルの「fixup-実際の宛先アドレス@fixme」に配送しようとします。 (4)ユーザー「fixup」は存在しないのでエイリアスの ~alias/.qmail-fixup-default が評価され、 メールは qmail 付属のメールクライアント qmail-inject に渡されます。 (5)qmail-inject はメールに足りないヘッダーフィールドを付加し、 実際の元の宛先アドレスに送信します。

壊れたメールを矯正するための設定

まず始めに、 fixme ドメイン宛のメールを自ホストの仮想ドメイン宛に配送し、 qmail-inject に渡されるようにします。 仮想ドメインに定義したドメインは control/locals に記述しなくてもローカル配送されます。 また、SMTP 経由で fixme ドメイン宛のメールを受け取る必要はないため、 control/rcpthosts に記述する必要もありません。

仮想ドメインの定義は control/virtualdomains ファイルに記述します。 fixme ドメイン宛のメールが 「fixup-宛先アドレスのローカル部」 というメールボックス名に配送されるように指示します。 control/virtualdomains の変更を有効にするには、 qmail-send のプロセスに HUP シグナルを送信するか、再起動が必要です。

fixme ドメイン宛メールを仮想ドメインで受信するための設定 (control/virtualdomains):
fixme:fixup

メールボックス名「fixup-宛先アドレスのローカル部」 宛のメールをすべて受け取るように、 ワイルドカードアドレスとして ~alias/.qmail-fixup-default ファイルを用意します。 メールはこのファイルの指示に従って qmail-inject に渡されます。 その際、宛先アドレスは「実際の宛先アドレス@fixme」のローカル部 (「@」の前の部分)、つまり元の宛先アドレスに戻ります。 環境変数についての解説は 「7.3.1 どのようにしてコマンドが起動されるのか」と qmail-command(8) を参照してください。

fixme ドメイン宛メールの配送指示 (~alias/.qmail-fixup-default):
|bouncesaying 'Permission denied' [ "@$HOST" != "@fixme" ]
|qmail-inject -f "$SENDER" -- "$DEFAULT"

次に、 問題のあるクライアントからのメールを 「実際の宛先アドレス@fixme」宛にリダイレクトされるようにします。

qmail-smtpd は、 環境変数 RELAYCLIENT が設定されている場合、 クライアントにメールのリレーを許可するとともに、 クライアントから指定された宛先アドレスに RELAYCLIENT の値を追加します。 通常は RELAYCLIENT は空白が設定されるようにしますが、 問題があるクライアントからの場合は 「RELAYCLIENT="@fixme"」とし、 受け取ったメールが fixme ドメイン宛に送付されるようにします。

qmail-smtpd の起動に ucspi-tcp の tcpserver を利用しているのであれば、 アクセスコントロールファイルに次のように記述します。 この例では、問題のあるクライアントの IP アドレスが 192.168.0.100 〜 192.168.0.120 の範囲にあるものとしています。

特定のクライアントからのメールを @fixme ドメイン宛に配送するための設定 (/etc/tcp.smtp):
192.168.0.100-120:allow,RELAYCLIENT="@fixme"
192.168.0.:allow,RELAYCLIENT=""
:allow
/etc/tcp.smtp.cdb の更新:
# cd /etc
# tcprules tcp.smtp.cdb tcp.smtp.$$ < tcp.smtp

このメール矯正方法の問題点

FAQ に紹介されているメール矯正の設定では、 From: フィールドがないメールを受信すると、 「From: alias@defaulthost」 フィールドが付加されてしまうという問題があります。 ~alias/.qmail-fixup-default で呼び出している qmail-inject の代わりに、 次のようなラッパースクリプトを利用すれば回避できます。

メールを矯正するスクリプトの例 (From: フィールドがないメールに対応):
#!/bin/sh

QMAILUSER=`echo $SENDER | sed 's/@[^@]*$//'`
QMAILHOST=`echo $SENDER | sed 's/^.*@//'`
export QMAILUSER QMAILHOST

qmail-inject -f "$SENDER" -- "$DEFAULT"

しかしなお、次のような問題が残ります。 1 と 2 は sendmail にあるヘッダー内のアドレスの補完機能に似ていますが、 qmail のこの設定では抑制できません。 3 はほとんどないと思われるケースですが、 まったくないとも言いきれません。

  1. From:/To:/Cc: フィールドに含まれるアドレスがアットマーク「@」を含まない場合、 そのアドレスにアットマークと control/defaulthost (なければ control/me) のドメイン名が付加されてしまう。
  2. From:/To:/Cc: フィールドに含まれるアドレスのドメイン部がドット「.」を含まない場合、 そのアドレスにドットと control/defaultdomain (なければ control/me) のドメイン名が付加されてしまう。
  3. 送信者アドレスが空白かつ From: フィールドがないと、 From: フィールドは「From: alias@defaulthost」となってしまう。

このように、 条件によっては望まない書き換えが実行されてしまうことがあります。 書き換えの対象とするクライアントは、 あなたの管理下にあるものだけに限るべきです。 外部からのメールには適用されないように設定してください。

10.3.6 宛先ユーザー不明によるバウンスを管理者に通知する

sendmail は自ホスト宛のメールが宛先ユーザー不明の場合、 送信者にバウンスメールを送信するだけでなく、 自ホストの postmaster 宛にもその旨を通知するメールを送信することができます。 (実際にはそのほかのエラーについても通知可能らしい)

この動作を qmail で実現するには、 どのエイリアス/ユーザーにも一致しない場合のワイルドカードアドレスとなる ~alias/.qmail-default ファイルに細工を施します。

バウンスしたメールのコピーを得る方法

宛先ユーザー不明のメールを postmaster@example.co.jp 宛に転送する例を示します。 bouncesaying は qmail 付属のコマンドで、 .qmail ファイルで送信者にバウンスメールを返す場合に使用します。 10.3.2 節で解説している fastforward を利用しているなら -p オプションを追加して、 /etc/aliases に一致する名前がなかった場合に fastforward 以降の配送指定が評価されるようにします。

バウンスしたメールを postmaster に転送 (~alias/.qmail-default):
&postmaster@example.co.jp
|bouncesaying 'Sorry, no mailbox here by that name. (#5.1.1)'
fastforward を利用している場合 (~alias/.qmail-default):
|fastforward -p /etc/aliases.cdb
&postmaster@example.co.jp
|bouncesaying 'Sorry, no mailbox here by that name. (#5.1.1)'

より適切なバウンスメール情報を通知する方法

先の例はとてもシンプルでお手軽ですが、 管理者に通知 (転送) されるメールに次のような問題点があります。

  1. メールのヘッダー/本文とも元のメールそのままであるため、 一見しただけではバウンスしたメールであることを判断することが難しい。
  2. 削除されたユーザー宛のメール、 あるいは宛先アドレスの綴り間違いがあるメールがバウンスした場合、 他人のプライバシーを侵害してしまう恐れがある。
  3. 通知先への配送がバウンスすると、 送信者アドレスにバウンスメールが届いてしまう。

そこで、この問題を対処したバウンスメール情報通知用のスクリプト notifynomailbox を用意しました。 その特徴を示します。

バウンスしたメールのヘッダー部分だけを通知
プライバシーを侵害しないようにするため
通常のバウンス通知メールに似た From:/To:/Subject: フィールドと本文がついたメール
エラー通知メールとわかるように
送信者アドレスは空白
通知先への配送がバウンスした場合にループが発生しないように
終了コードは必ず 0
続く bouncesaying (あるいはほかの任意の処理) が実行されるように
自ホスト宛のメールが宛先ユーザー不明によりバウンスしたことを通知するスクリプト (notifynomailbox):
#!/bin/sh
#
# NAME
#       notifynomailbox - Notify header of bounced mail that deliverred to
#                         this host but no such mailbox on this host.
#
# SYNOPSIS
#       in .qmail-default:
#           |notifynomailbox address ...
#           |bouncesaying "Sorry, no mailbox here by that name. (#5.1.1)"
#
# AUTHOR
#       SATOH Fumiyasu <fumiya-s-qmail@samba.gr.jp>
#       2001-11-05, since 2001-09-10
#
# VERSION
#       1.0.3
#
# COPYING
#       GNU General Public License ver.2

cmd=notifynomailbox
qmail_home=/var/qmail
me_file=$qmail_home/control/me

if [ $# -eq 0 ]; then
    echo "$cmd: usage: $cmd address ..." 1>&2
    exit 0
fi
if [ ! -s $me_file ]; then
    echo "unable to read control $me_file" 1>&2
    exit 0
fi

me=`cat $me_file`
from=MAILER-DAEMON@$me
to=''
for t in "$@"; do
    to="$to$t, "
done
to=`echo "$to" | sed 's/, $//'`

(cat <<EOF_MAIL; awk '/^$/{body=1} body==0{print}') | \
qmail-inject -f '' -- "$@"
From: $from
To: $to
Subject: nomailbox notice

Hi. This is the $cmd program at $me.
The qmail-send tried to deliver a message to this address, but no such
mailbox on $me. This is a warning message for postmaster.
Bounce notice mail was back to envelope sender $SENDER.

<$RECIPIENT>:
Sorry, no mailbox here by that name on this host. (#5.1.1)

--- Below this line is a copy of the message (header only for privacy).

Return-Path: <$SENDER>
EOF_MAIL

exit 0

この notifynomailbox スクリプトは /var/qmail/bin などにインストールしてください。 また、このスクリプトはあくまでも一例ですので、 必要に応じて改造を施してください。 次に組み込んだ例を示します。

notifynomailbox の組み込み例 (~alias/.qmail-default):
|notifynomailbox postmaster@example.co.jp
|bouncesaying 'Sorry, no mailbox here by that name. (#5.1.1)'
fastforward を利用している場合 (~alias/.qmail-default):
|fastforward -p /etc/aliases.cdb
|notifynomailbox postmaster@example.co.jp
|bouncesaying 'Sorry, no mailbox here by that name. (#5.1.1)'

付録

参考文献

qmail の付属文書ファイル
SENDMAIL
REMOVE.sendmail
INSTALL.vsm
マニュアル
dot-forward(1)
fastforward(1)
newinclude(1)
procmail(1)
dot-qmail(5)
maildir(5)
mbox(5)
qmail-control(5)
qmail-command(8)
qmail-start(8)
sendmail(8)
mailer.conf(5) (FreeBSD)
rc.conf(5) (FreeBSD)
Message-ID に関する考察 - Taki Internet Mail Private Lab.
http://www.emaillab.org/essay/message-id.html
RFC: Local Mail Transfer Protocol (LMTP)
RFC 2033
RFC: Simple Mail Transfer Protocol (SMTP)
RFC 2821
RFC: Internet Message Format
RFC 2822

更新履歴

2001-12-17 佐藤文優
初版発行前の校正の取り込み。
2001-11-14 佐藤文優
notifynomailbox を 1.0.3 に更新。
2001-11-12 佐藤文優
http://www.qmail.org を紹介している箇所にミラー http://www9.jp.qmail.org を追加。
2001-11-03 佐藤文優
タイトルに「qmail へ」を追加。
2001-10-11 佐藤文優
「ヘッダー」→「フィールド」、あるいは「ヘッダーフィールド」
フィールド名のあとにコロン「:」を追加
「Message-Id」→「Message-ID」
2001-10-07 佐藤文優
「パーミッション」→「アクセス許可」
「バイナリ/ソースパッケージ」→「各種バイナリ/ソースパッケージ」
第7章へのリンクをいくつか追加
2001-10-01 佐藤文優
「送信元アドレス」→「送信者アドレス」
2001-09-23 佐藤文優
10.2.5 POP/IMAP サーバーの移行」を追加
環境変数 MAIL の解説を追加 (10.2.6 メールクライアントの設定変更)
root と nobody のエイリアスについての記述を追加 (10.2.7 エイリアスと転送設定の移行)
更新履歴を追加
2001-09-13 佐藤文優
第1稿の完成
2001-08-01 佐藤文優
執筆開始