第11章 パッチによる qmail の動作変更 - qmail で作る快適メールサーバー

佐藤 文優 <https://fumiyas.github.io/>
2001年12月17日 更新, 2001年10月8日 以来

目次

11.1 パッチ入門
11.1.1 パッチとは?
11.1.2 qmail 用のパッチ
11.2 日時関連のパッチ
11.2.1 日付の表示を地方標準時にする
11.3 メールボックスの容量制限
11.3.1 メールボックス容量超過の場合に即バウンスさせる
11.4 SMTP によるメール配送を制限するためのパッチ
11.4.1 特定の宛先アドレスへのメールの受信を拒否する
11.4.2 受信拒否する送信者/宛先アドレスをパターンで指定可能にする
11.4.3 送信者アドレスのドメイン部の正当性の検査
11.5 バウンスメール関係のパッチ
11.5.1 バウンスメールのメッセージを変更可能にする
11.5.2 バウンスメールのサイズを制限する
11.6 問題ある POP3 クライアントを救済するパッチ
11.6.1 「サーバーにメールを残す」機能が動作しないメールクライアントの救済
11.6.2 Netscape Messenger のメール取得の進捗表示が機能しない問題への対応
11.7 大量のメール配送時のパフォーマンス改善
11.7.1 送信処理の最大並列数の上限を上げる
付録
参考文献
更新履歴

11.1 パッチ入門

11.1.1 パッチとは?

一般的には、パッチ (patch) とは日本語で次のような意味を持ちます。

名詞
動詞

ソフトウェアでいう「パッチ」もほぼこれと同じで、 動作の不具合を応急的に修正あるいは回避するため、 ソフトウェアを書き換える「差分」情報のことを指します。 また、その差分をソフトウェアに組み込むことを「パッチをあてる」、 「パッチを適用する」などと表現します。

ソフトウェアの「欠陥」という名の穴を繕うものだけがパッチではありません。 いわばパッチワークのように、 ソフトウェアに機能を追加したり、動作を変更するためのパッチも存在します。

パッチは薬のようなもの

パッチは薬と同じで、時には副作用が生じることがあります。 構成によってはまったく影響の出ない副作用もありますが、 明かに害となって現れることもあるでしょう。 それが目に見える形で現われることもあれば、 自覚症状がない (より危険) ことがあるかもしれません。 また、複数のパッチの適用によって生じる副作用もあるかもしれません。 麻酔薬のように当面の痛みを取り除くだけで、 根本的な問題を解決できないこともあるでしょう。

あなたが直面している問題をしっかりと分析し、 適切なパッチを選択することが肝心です。 パッチに謳われている効能を理解するのはもちろん、 ソース形式のパッチであれば、 どのような変更がされるのか解析するようにしましょう。

パッチの形式

パッチには、 バイナリファイルを書き換えたりファイルごと置き換えるバイナリ形式のパッチと、 ソースファイルやスクリプトを書き換えるためのソース形式のパッチがあります。 この章では、 qmail のソースに変更を加えるためのソース形式のパッチを扱います。 ソースにパッチを適用したあとは、 もちろん再コンパイルして新しいバイナリファイルを生成し、 インストールする必要があります。

ソースファイル用のパッチには、 書き換える対象のソースファイルの名前と位置、そして変更点が記されています。 1つのパッチファイルに複数のファイルのパッチが含まれていることもあります。

以下に、 「Hello, World!!」と表示するコマンドのソース (C言語) を、 「Hello, New World!!」と改行を表示するように変更するためのパッチを示します。

ソース形式のパッチの例 (helloworld.c 用のパッチ):
--- helloworld.c.old    Thu Oct 11 19:50:51 2001
+++ helloworld.c        Thu Oct 11 19:51:53 2001
@@ -1,5 +1,5 @@
 int main(void)
 {
-    printf("Hello, World!!");
+    printf("Hello, New World!!\n");
     return 0;
 }

この例を見るとわかるように、ソース形式のパッチの正体は、 2 つのファイルを比較して違いを表示する diff コマンドの出力です。 diff コマンドの出力には何種類か異なる形式がありますが、 先の例のパッチは「unified 形式」と呼ばれるものです。 パッチの提供者は、 修正前後のファイルを diff コマンドに通し、 得られた差分情報をパッチファイルとして第3者に配布します。

以下にパッチの適用前後の helloworld.c を示します。

パッチを適用する前の helloworld.c:
int main(void)
{
    printf("Hello, World!!");
    return 0;
}
パッチを適用した後の helloworld.c:
int main(void)
{
    printf("Hello, New World!!\n");
    return 0;
}

パッチの適用方法

パッチを適用してソースファイルを変更するには、 patch コマンドを使用します。 patch コマンドの使用方法は、 パッチの形式によって多少異なることがありますが、 概ね、以下のように実行します。

patch コマンドの実行例 (パッチファイル newworld.patch を適用):
$ ls
helloworld.c    newworld.patch
$ patch < newworld.patch
patching file helloworld.c

先にも述べたように、パッチ (diff の出力) の形式にはいくつかの種類がありますが、 patch コマンドは種類を自動で認識し、適切に処理してくれます。 パッチファイルにはパッチの前後にコメントや解説がついていることがありますが、 patch コマンドはそれらを無視してくれます。

通常、パッチファイル内には、 パッチの対象となるファイルの相対パス名が記述されています。 patch コマンドはそのパス名を利用してパッチ対象のファイルにアクセスするため、 適切なディレクトリに移動してから patch コマンドを実行しなければなりません (patch コマンドの -d オプションを利用する方法もある)。

パッチ対象のパス名の先頭に余計なディレクトリ名が含まれているなら、 patch コマンドの -p オプションを利用して削除することができます。 -p オプションには、パス名の先頭から何番目のスラッシュ「/」 までを削除するかを指定します。

11.1.2 qmail 用のパッチ

以下の節では、qmail のソースに適用するパッチをいくつか紹介します。 パッチを適用することで、 qmail の動作を変更したり、 追加の機能を実現することができます。

qmail 用のパッチの多くは、 qmail のユーザーサイトの 1つ「The qmail home page」 から入手することができます。 また、qmail のメーリングリストにパッチやその情報が投稿されることもあります。

The qmail home page
http://www9.jp.qmail.org (ミラー)
http://www.qmail.org
qmail mailing list
http://cr.yp.to/lists.html#qmail

11.2 日時関連のパッチ

11.2.1 日付の表示を地方標準時にする

qmail が生成する日付は世界標準時

qmail は様々な場面で日付文字列の生成や表示を行いますが、 それらはすべて世界標準時の日時になります。 そのような日付には、 世界標準時からの時差がないことを意味する「-0000」、 またはグリニッジ標準時 (Greenwich Mean Time) を意味する「GMT」、 あるいはその両方が付加されています (qmail の場合はどちらかのみ)。

一方、qmail 以外の MTA やメールクライアントの多くは、 システムの地域情報の設定 (タイムゾーン) に合わせ、日付は地方時間で生成します。 例えば日本では世界標準時からの時差は 9時間なので、 日付にはそれを意味する「+0900」、 または「JST」(Japan Standard Time)、 あるいはその両方が付加されます。

qmail に地方標準時の日付を生成させる

次に紹介するパッチは、 qmail の日付生成処理に変更を施し、 システムの地域設定に従った地域標準時の日付を生成するようにします。

日付の表示を地方標準時にするパッチ
ftp://ftp.nlc.net.au/pub/unix/mail/qmail/qmail-date-localtime.patch
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch -p1 < /path/to/qmail-date-localtime.patch

このパッチによる動作は、設定ファイルで制御することはできません。 代わりに、コマンドを起動する前に、 環境変数 TZ を設定してください (マニュアル tzset(3) などを参照のこと)。

このパッチは、qmail の以下のコマンドに影響を及ぼします。

qmail-inject
Date: (Recent-Date:) フィールドの日付 (ヘッダーに含まれていない場合に追加する)
qmail-send
バウンス通知メールの Date: フィールドの日付
qmail-smtpd など
受信したメールに追加する Received: フィールドの日付
qmail-qread
メールがキューに到達した日時を示す日付

qmail-date-localtime.patch の問題点

このパッチにより、qmail-qread が出力する日付の表示に問題が発生します。 qmail-qread は、キューにあるメールの情報を表示するコマンドです。 その情報の中にはメールがキューに到着した日時が含まれており、 このパッチによりシステムの地域設定 (または環境変数 TZ の値) の標準時で表示されますが、 実際の地域設定に関わらず必ず「GMT」と表示されてしまいます。 これを解消するには、qmail-qread.c に以下のようなパッチを適用するとよいでしょう。

qmail-date-localtime.patch による qmail-qread の不具合を解消するパッチ:
--- qmail-qread.c.dist  Mon Jun 15 19:53:16 1998
+++ qmail-qread.c       Mon Oct 15 18:50:53 2001
@@ -65,8 +65,8 @@
 
  len = 0;
  datetime_tai(&dt,qtime);
- i = date822fmt(s,&dt) - 7/*XXX*/; len += i; if (s) s += i;
- i = fmt_str(s," GMT  #"); len += i; if (s) s += i;
+ i = date822fmt(s,&dt) - 1/*XXX*/; len += i; if (s) s += i;
+ i = fmt_str(s,"  #"); len += i; if (s) s += i;
  i = fmt_ulong(s,id); len += i; if (s) s += i;
  i = fmt_str(s,"  "); len += i; if (s) s += i;
  i = fmt_ulong(s,size); len += i; if (s) s += i;

11.3 メールボックスの容量制限

11.3.1 メールボックス容量超過の場合に即バウンスさせる

UNIX には、ユーザーのディスク使用量を制限するための 「クォータ (quota)」と呼ばれる機能があります。 クォータによりディスク使用を制限されたユーザーは、 作成できるファイルの数と使用できる容量に制限が設けられます。 制限に達っすると、ファイルの新規作成やファイルへのデータ出力は失敗します。

qmail (qmail-local) は、 メールボックスへのメール保存の処理に失敗すると、 一時エラーとし、メールボックスへの配送は後ほど再試行されます。 この動作はクォータの制限によって失敗した場合も変わりません。 その後も問題が解消されなければ、 メールは control/queuelifetime で指定された時間だけキューに滞留したのち、バウンスします。 メールの送信者は、そのときやっとメールが届かないことがわかりますが、 バウンスメールを見ても送信先のメールボックスが一杯であることはわかりません。

次のパッチを適用することで、 qmail-local はクォータによる書き込み失敗を検知できるようになり、 そのような場合には永続的エラーとするようになります。

qmail-local にクォータ制限によるエラーを検知可能にするパッチ
http://www9.jp.qmail.org/qmail-1.03-quotas-1.1.patch (ミラー)
http://www.qmail.org/qmail-1.03-quotas-1.1.patch
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch < /path/to/qmail-1.03-quotas-1.1.patch

このパッチにより、クォータ制限に達っしているユーザーへのメール配送は、 即座にバウンスするようになります。 バウンスメールには、配送に失敗した原因として、 宛先ユーザーのメールボックスが一杯であることが示されます。

11.4 SMTP によるメール配送を制限するためのパッチ

qmail (qmail-smtpd) は、 SMTP の MAIL コマンドで渡される送信者アドレス (control/badmailfrom) や、 RCPT コマンドで渡される宛先アドレスのドメイン部 (control/rcpthosts, morercpthosts)、 DATA コマンドで渡されるメールのサイズ (control/databytes) により、 メールの受信を拒否することができます。

ここで紹介するパッチは、 SMTP によるメールの受信と配送に対し、 受信の拒否条件の設定をより柔軟に指定可能にするパッチや、 なにかしらの制限を加えるためのパッチです。 これらは主に、SPAM メールの受信や配送を抑制するために利用されます。

11.4.1 特定の宛先アドレスへのメールの受信を拒否する

標準の qmail-smtpd は、宛先アドレスのドメイン部により受信の拒否が可能ですが、 宛先アドレスのローカル部を含めた受信拒否の判定をさせることはできません。 次に紹介するパッチを適用することで、ドメイン部だけでなく、 宛先アドレス全体により受信の可否を判定できるようになります。

特定の宛先アドレスへのメールの受信を拒否するパッチ
http://patch.be/qmail/badrcptto.html
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch -p1 < /path/to/badrcptto.patch

受信を拒否する宛先アドレスは、 このパッチによる追加の設定ファイル control/badrcptto に記述します。 このファイルの形式は、 受信を拒否する送信者アドレスを指定するための control/badmailfrom ファイルと同じです。 例えば、宛先アドレスが badname@example.com のメールと、 宛先アドレスのドメイン部が baddomain.example.net のメールの受信を拒否するには、 次のように記述します。

SMTP で特定の宛先アドレスのメールの受信を拒否する (control/badrcptto):
badname@example.com
@baddomain.example.net

11.4.2 受信拒否する送信者/宛先アドレスをパターンで指定可能にする

qmail には標準で、 特定の送信者アドレスからのメールの受信を拒否する機能があります。 拒否する送信者アドレスの指定は control/badmailfrom ファイルで行いますが、 固定的なアドレスかドメインの指定しかできません。 先の節で紹介した宛先アドレスによる受信拒否用のパッチの機能も同様です。

ここで紹介するパッチは、 ニューズサーバーソフトウェア INN で利用されている wildmat と呼ばれるパターン一致処理を qmail-smptd に追加し、 受信を拒否する送信者/宛先アドレスの指定にパターンを記述可能にするパッチです。

受信拒否する送信者/宛先アドレスをパターンで指定可能にするパッチ
http://www.unixpimps.org/software/wildmat/
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ gzip -dc /path/to/wildmat-0.3.tar.gz | tar xf -
$ patch < wildmat.patch

このパッチを適用することで、 qmail 標準の control/badmailfrom ファイルは機能しなくなり、 代わりに control/badmailpatterns ファイルを使うようになります。 しかも、このファイルに記述したアドレスは、 送信者アドレスだけでなく宛先アドレスにも適用されます。 残念ながら、 受信を拒否する送信者アドレスと宛先アドレスを別々に指定することはできません。 この点、十分のご注意ください。

wildmat 形式のパターン表記法

wildmat 形式のパターン表記法は、 シェルのワイルドカードパターンの表記に似ています (glob(3) などを参照のこと)。 残念ながらパッチには詳しい解説が含まれていませんので、 INN の付属のマニュアル wildmat(3) を参照するか、 Web の検索ページで探してみてください。 ここで簡単に解説します。

?
あらゆる単一の文字に一致する。
*
あらゆる文字列に一致する。空文字列にも一致する。
[x...y]
括弧内に含まれる単一の文字に一致する。
ハイフン「-」で文字の範囲を指定することができる。(例: [0-9a-z])
ハイフンを含めるには括弧内の最初か最後に指定する。
閉じる括弧「]」を含めるには括弧内の最初に指定する。
[^x...y]
括弧内に含まれない単一の文字に一致する。
\x
任意の単一の文字 x に一致する。
?」などの特殊な文字の機能を打ち消すために用いる。

以下に control/badmailpatterns ファイルの記述例を示します。

SMTP で特定のパターンの送信者/宛先アドレスのメールの受信を拒否する (control/badmailpatterns):
*@baddomain.example.net
*%*@*
*@*@*

11.4.3 送信者アドレスのドメイン部の正当性の検査

SPAM メール送信者の多くは、 送信者アドレスを偽って SPAM メールを送信します。 その際に利用されるメールアドレスのドメイン部は、 SPAM 送信者とは関係のない第3者のドメインを勝手に名乗ったり、 実在しないドメインが利用されます。

次に紹介するパッチを qmail に適用することで、 qmail-smtpd は SMTP の MAIL コマンドで指定される送信者アドレスからドメイン部を抜き出し、 DNS でそのドメインの MX レコードを検索するようになります。 該当する MX レコードが存在しない場合、 qmail-smtpd は無効な送信者アドレスと判断してメールの受信を拒否します。

送信者アドレスのドメイン部を DNS で検査するためのパッチ
http://www9.jp.qmail.org/qmail-1.03-mfcheck.3.patch (ミラー)
http://www.qmail.org/qmail-1.03-mfcheck.3.patch
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch -p1 < /path/to/qmail-1.03-mfcheck.3.patch

このパッチによる機能は、追加の設定ファイル control/mfcheck に 0 か 1 を記述することで、 無効にするか有効にするかを制御することができます。 デフォルトは 0 で、送信者アドレスのドメイン部の検査機能は無効になります。 この設定は環境変数 MFCHECK の値でも指定可能で、 control/mfcheck ファイルによる指定よりも優先されます。

11.5 バウンスメール関係のパッチ

qmail (qmail-send) は、 メール配送が失敗した場合に送出するバウンスメールについて、 ヘッダーの From: フィールドの内容を設定可能にしています (ただし送信者アドレスは設定に関係なく必ず空)。 また、バウンスメールがバウンスしたときに送出する 2重バウンスメールについては、 送付先の宛先アドレスが設定可能です。

ここで紹介するパッチは qmail-send が生成するバウンスメールに関するもので、 qmail 標準より柔軟な設定変更を可能とします。 パッチやその設定によっては、 qmail が従っている標準のバウンスメッセージ形式 (QSBMF) に適合しなくなることがあります。 ご注意ください。

The qmail-send Bounce Message Format (QSBMF)
http://cr.yp.to/proto/qsbmf.txt

11.5.1 バウンスメールのメッセージを変更可能にする

このパッチを適用することで、 qmail が生成するバウンスメールと 2重バウンスメールに含まれる表題 (ヘッダーの Subject: フィールドの内容) と本文のメッセージを設定変更可能にできます。

バウンスメールの表題とメッセージを変更可能にするパッチ
http://www9.jp.qmail.org/qmail-bouncecontrol-1.03.patch (ミラー)
http://www.qmail.org/qmail-bouncecontrol-1.03.patch
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch -p1 < /path/to/qmail-bouncecontrol-1.03.patch

このパッチにより、 以下のような 4つの設定ファイルが追加されます。 ファイルが存在しない場合は、qmail 標準の表題/メッセージとなります。

control/bouncesubject
バウンスメールの Subject: フィールドの内容
最初の 1行だけ使用され、それ以降の行は無視される
control/bouncemessage
バウンスメールの本文のメッセージ
control/doublebouncesubject
2重バウンスメールの Subject: フィールドの内容
最初の 1行だけ使用され、それ以降の行は無視される
control/doublebouncemessage
2重バウンスメールの本文のメッセージ

qmail-send が生成するバウンスメールには Content-Type: フィールドは含まれていないため、 control/bouncemessage, doublebouncemessage に記述するメッセージにはテキスト形式の ASCII 文字だけを含めることができます。 よって、日本語などを含めることはできません。 また、メッセージに空行を含めてしまうと、 QSBMF に従わない形式になってしまいます。

control/bouncesubject, doublebouncesubject に記述する表題は、 そのままバウンスメールのヘッダー部に入るため、 ASCII 文字だけを含めることができます。 日本語などを含める場合は、 いわゆる「MIME エンコード」形式にしなければなりません。 (RFC 2047 「Multipurpose Internet Mail Extensions Part Three: Message Header Extensions for Non-ASCII Text」)

11.5.2 バウンスメールのサイズを制限する

qmail-send が生成するバウンスメールには、 バウンスしたメールがヘッダーと本文とも受信したときのままの形で含まれます。 次のパッチを適用することで、 バウンスメールに含める元のメールのサイズに制限をかけることが可能になります。

バウンスメールに付加される元のメールのサイズを制限するパッチ
http://www.jedi.claranet.fr/qmail-bounce.patch
http://www9.jp.qmail.org/www.jedi.claranet.fr/qmail-bounce.patch (ミラー)
http://www.qmail.org/www.jedi.claranet.fr/qmail-bounce.patch (ミラー)
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch < /path/to/qmail-bounce.patch

このパッチにより、設定ファイル control/bouncemaxbytes が追加されます。 このファイルには、 バウンスメールに含める元のメールの最大サイズをバイト数で指定します。 デフォルトは 50000 バイトです。 残念ながら、このパッチによる動作を無効にして制限なしにすることはできません。

バウンスしたメールがこのサイズを越えている場合、 バウンスメールに含まれる元メールはサイズを越える部分が省略され、 代わりに改行と「--- End of message stripped.」 というメッセージが付加されます。

11.6 問題ある POP3 クライアントを救済するパッチ

11.6.1 「サーバーにメールを残す」機能が動作しないメールクライアントの救済

POP3 クライアントが取得済みのメールを判定するための仕組み

一般的に POP3 に対応しているメールクライアントは、 POP3 サーバーから取得したメールをサーバーから削除せずに、 POP3 サーバーに残しておくことができます。 POP3 クライアントは、 1度サーバーから取得したメールを再び取得しないようにするため、 POP3 (RFC 1939 「Post Office Protocol - Version 3」) のオプションとして定義されている UIDL コマンドで得られるメールごとの識別子、 あるいはメールのヘッダーに含まれる Status:X-UIDL: フィールドの値を利用します (クライアントの実装に依存)。

UIDL コマンドはその動作である 「Unique-ID Listing」から名付けられたもので、 サーバーのメールボックス内にあるメールから、 各メールを一意に識別するための識別子 (UID) を返します。 UIDL に対応している POP3 クライアントは、 この識別子を利用してメールが取得済みであるかどうかを判断します。 qmail 付属の POP3 サーバーである qmail-pop3d は、 UIDL コマンドをサポートしています。

Status: フィールドには、 メールが新着か、既読か、取得済みかどうかの状態が保持されます。 メールボックスを直接参照するメールクライアントである mail コマンドや、 いくつかの POP3 サーバーの実装がサポートしており、 必要に応じて Status: フィールドの値を書き換えます。 しかし、qmail-pop3d は Status: フィールドをサポートしていません。 RFC 2076 「Common Internet Message Headers」によると、 Status: フィールドは非標準のヘッダーフィールドです。

X-UIDL: フィールドには、 POP3 の UIDL コマンドで得られるのと同じ、 一意の識別子が保持されます。 詳細は不明ですが、 何らかの形でこのフィールドの値を利用するクライアントが存在するようです。 qmail-pop3d は X-UIDL: フィールドをサポートしていません。

qmail-pop3d に Status:/X-UIDL: フィールドをサポートさせる

以上のように、 UIDL コマンドをサポートしていなかったり、 UIDL をサポートしていても X-UIDL: フィールドに依存している POP3 クライアントは、 qmail-pop3d の下では「サーバーにメールを残す」機能がうまく動作しません。 次に紹介するパッチを適用することで qmail-pop3d がメールに Status:/X-UIDL: フィールドを追加するようになります。

qmail-pop3d で Status:/X-UIDL: フィールドをサポートするパッチ
http://homepages.munich.netsurf.de/Franz.Sirl/qmail-pop3d-1.03.diff
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch -p1 < /path/to/qmail-pop3d-1.03.diff

このパッチによる追加の設定ファイルはありません。 また、このパッチによる動作を抑制することはできません。

11.6.2 Netscape Messenger のメール取得の進捗表示が機能しない問題への対応

qmail 環境で現われる Netscape Messenger の不具合

Netscape 社の Netscape Navigator / Communicator に付属のメールクライアント Netscape Messenger は、 POP3 サーバーからメールを取得している間、 取得の進捗状況をダイアログウィンドウに表示します。 ダイアログは、 サーバー上にあるメールの総数と取得した数、 そして進行の度合を横長のメーターとパーセンテージで表わします。

図: Netscape Messenger のメールの取得状況を示すダイアログ: Netscape Messenger 4.78 (ja) Download Dialog

しかし Messenger は、 POP3 サーバー が qmail-pop3d であると、 横長メーターとパーセンテージが正しく表示されません。 以下のように、メーターは一定のまま変化せず、 パーセンテージの表示はされません。

図: qmail-pop3d に対しては進捗割合いの表示がおかしくなる: Netscape Messenger 4.78 (ja) Download Dialog with qmail-pop3d

原因は qmail-pop3d ではなく Netscape Messenger にあります。

Netscape Messenger が期待する POP3 サーバーの応答

POP3 には、 サーバーからメールを取得 (retrieve) するための RETR コマンドが用意されています。 POP3 サーバーは RETR コマンドの応答として、 指定された番号のメールがあるならコマンドを受け付けたことを意味する 「+OK」行とメールのメッセージ、 そして最後にドット「.」だけの行をクライアントに返します。 以下に、広く普及している POP3 サーバーの実装の一つである Qpopper に対して telnet コマンドで接続し、手動でメールを取得する様子を示します。

POP3 サーバー Qpopper から telnet コマンド経由でメールを取得:
$ telnet mail.example.net pop3
Trying 192.168.1.1...
Connected to mail.example.net.
Escape character is '^]'.
+OK QPOP (version 3.0.2) at mail.example.net starting.  
USER ユーザー名
+OK Password required for ユーザー名.
PASS パスワード
+OK ユーザー名 has 2 visible messages (0 hidden) in 5593 octets.
LIST
+OK 2 visible messages (5593 octets)
1 2881
2 2712
.
RETR 1
+OK 2881 octets
メールメッセージ
…
.
USER, PASS コマンドにより認証を受け、 LIST でメールの一覧 (番号とサイズ) を表示、RETR で取得。

ご覧のように、Qpopper は RETR コマンドの応答の「+OK」行に 「メールのサイズ octets」を付加します。 一方、qmail-pop3d は「+OK」とだけ応答します。 RFC 1939 によると、 動作例としてメールのサイズが付加された応答を返すものが記載されていますが、 そのようにすべきと規定しているわけではありません。

Netscape Messenger の不具合に対応する

Netscape Messenger は RETR コマンドの応答として Qpopper が返すような形式を期待しており、 そこから得られるメールのサイズから進捗のパーセンテージを計算しています。 このため、RETR コマンドに対してメールのサイズを返さない qmail-pop3d 相手ではうまく機能しません。 そこで、次のパッチを qmail-pop3d に適用することで、 Messenger の不具合を回避することができます。

POP3 の RETR コマンドの応答にメールのサイズを追加するパッチ
http://www9.jp.qmail.org/netscape-progress.patch (ミラー)
http://www.qmail.org/netscape-progress.patch
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch < /path/to/netscape-progress.patch

11.7 大量のメール配送時のパフォーマンス改善

11.7.1 送信処理の最大並列数の上限を上げる

最大並列数に指定できる値の上限

qmail はメール配送処理を、 複数のプロセスを生成し並行して実行します。 ローカルユーザーへの配送の最大並列数は control/concurrencylocal、 リモートへの配送の最大並列数は control/concurrencyremote の設定により制限され、デフォルトの最大並列数はローカル配送は 10、 リモート配送は 20 に設定されています。 大量のメールを配送する必要があるならば、 配送処理の最大並列数を上げることで (ほかにボトルネックが生じない限り)、 その分だけメール配送のパフォーマンスは向上します。

しかし、 control/concurrencylocal, concurrencyremote で指定できる並列数は、最大で 120 に制限されています。 この制限は、qmail のコンパイル時、 qmail のソースツリーに含まれる conf-spawn ファイルに記述されている値で決まります。 このファイルの値を増やして qmail をコンパイルすることで、 121 以上の並列配送を実現できます。

しかしそれでも、 conf-spawn ファイルに記述できる最大並列数の最大値は 255 に制限されます。 これは qmail の内部実装による制限です。 この制限はコンパイル時に検査され、 conf-spawn ファイルの値が 255 を越えていると、 次のようにコンパイルが中断されます。

conf-spawn ファイルに 256 以上の数を記述して qmail をコンパイルすると…:
…ほかのオブジェクトやバイナリのコンパイル状況…
./auto-int auto_spawn `head -1 conf-spawn` > auto_spawn.c
./compile auto_spawn.c
./load chkspawn substdio.a error.a str.a fs.a auto_spawn.o 
./chkspawn
Oops. You have set conf-spawn higher than 255.
make: *** [spawn.o] Error 1

最大並列数の上限を 256 以上にする

次のパッチを適用することで、 qmail は 256 以上のプロセスを生成できるようになります。

256 以上の最大並列数を指定可能にするパッチ
http://www9.jp.qmail.org/big-concurrency.patch (ミラー)
http://www.qmail.org/big-concurrency.patch
このパッチの適用例
$ cd source/dir/of/qmail-1.03
$ patch -p1 < /path/to/big-concurrency.patch

このパッチにより、実装としては最大 65536 の並列実行に対応しますが、 65000 以下に制限するように作られています。 そこまで多くのプロセスを実行するには、 CPU 速度、メモリ、ネットワーク帯域、 そのほか相当のリソースが必要になり現実的ではないため、 問題ないでしょう。 conf-spawn ファイルは 1000 に書き換わります。

通常 UNIX カーネルは、システム全体あるいはユーザーごとに、 同時に実行できるプロセスや扱えるファイル記述子の数、 消費メモリサイズなどに制限をかけています。 このパッチを適用し qmail の制限を増すだけでなく、 カーネルパラメーターの調整を確認することを忘れないようにしてください。


付録

参考文献

qmail とパッチ - DJB's software maniacs
http://www.emaillab.org/djb/qmail-patch/index.html
The qmail home page
http://www9.jp.qmail.org (ミラー)
http://www.qmail.org

更新履歴

2001-12-17 佐藤文優
初版発行前の校正の取り込み。
2001-11-12 佐藤文優
http://www.qmail.org を紹介している箇所にミラー http://www9.jp.qmail.org を追加。
2001-11-06 佐藤文優
第1稿の完成
2001-10-08 佐藤文優
執筆開始