この節では .qmail ファイルの基本的な事柄を解説します。 .qmail ファイルは sendmail の .forward ファイルに似た用途を持ち、 書式や動作も似通っていますが、 いくつか異なる点があります。 qmail 付属のマニュアル dot-qmail(5) も参照のこと。
.qmail ファイルは通常はユーザーのホームディレクトリに置かれ、 ユーザーに配送されたメールをどのように扱うかを制御します。 メールの配送指定には、次のいずれかの方法を指定できます。
.qmail ファイルを評価して指定された配送処理を実行するのは qmail-local コマンドです。 .qmail ファイルが存在しない、 あるいは .qmail ファイルのサイズが 0 バイトの場合、 qmail-local は qmail-start コマンドを介して指定されたデフォルトの配送方法を実行します。 ただし、拡張メールアドレス (→7.2節) の場合は、 対応する .qmail ファイルが存在しない場合、 メールはバウンスされます。
qmail-local は、 作業ディレクトリをユーザーのホームディレクトリに移動してから .qmail ファイルを評価します。 よって、 メールボックスやコマンドのパス名に相対パスを指定すると、 ホームディレクトリを基点としたパスを参照することになります。
qmail-lspawn は、 プロセスの実効権限をユーザーの UID, GID に変更したあとに qmail-local を起動します。 よって、qmail-local によるメールボックスへの保存やコマンドの起動などの処理は、 ユーザーの権限で実行されます。
.qmail ファイルには 1行以上の行を記述し、 各行が 1つのメール配送の指定となります。 記述可能なものは、 コメント、 maildir 形式のメールボックスのパス、 mbox 形式のメールボックスのパス、 転送先のアドレス、 起動するコマンドのいずれかです。
#
」で始める# This is a comment. I love comments.
.
」か「/
」で始めてメールボックスのパスを記述し、パスの末尾に「/
」を付ける./Maildir/
.
」か「/
」で始めてメールボックスのパスを記述し、パスの末尾に「/
」を付けない./Mailbox
|
」、続けてコマンドラインを記述|preline vacation fumiya
&
」、続けて転送先アドレスを記述&
」は省略可能&fumiya@nextstep.example.net
行末のスペースとタブは無視されます。 しかし、行頭にスペースやタブがあってはいけません。 空白行を含めることができますが、 .qmail ファイルの先頭の行を空白行にすることはできません。
転送先のアドレスは、 純粋に「ローカル部@ドメイン部」 といったアドレスだけを記述します。 余計なスペースやタブ、括弧類、 RFC 2822 で定義されているようなコメントを含めてはいけません。 また、ドメイン部は FQDN (完全修飾ドメイン名, Fully Qualified Domain Name) でなければなりません。
転送先のアドレスはアットマーク「@」と以降のドメイン部を省略することができます。
そのようなアドレスには、
qmail-send によって「@」と control/envnoathost
ファイル
(なければ control/me
) の値が付加されます。
.qmail ファイルが誰でも書き込めるようなアクセス許可を持つ場合、 qmail-local は .qmail ファイルの評価を拒否して一時エラーとします。 一時エラーとなったメールは、しばらく後に配送を再試行されます。
.qmail ファイルを所有するユーザーと所有グループは何でも構いません。 .qmail ファイルが置かれているディレクトリは、 所有グループとアクセス許可には要件はありません。 しかし、ディレクトリをほかのユーザーが所有していると一時エラーとなります。
例外として、次の節で解説しているように、
.qmail ファイルの実行アクセス権とディレクトリの
sticky 属性は特別な意味を持ちます。
また、
qmail 付属のマニュアル
qmail-users(5)
で解説されているように、
users/assign
ファイルで宛先アドレスに対応するユーザー/ホームディレクトリなどを割り当てた場合は、
ディレクトリの所有者は誰でも構いません。
.qmail ファイルが所有者の実行アクセス許可を持つ場合、 qmail-local は転送以外の配送指定の実行を拒否し、 一時エラーとなります。
ホームディレクトリに sticky 属性が付いている場合、 .qmail ファイルの有無にかかわらず、 qmail-local はメールの配送を拒否して一時エラーとします。 この動作は .qmail ファイルを安全に編集するために利用します。
エディタなどで .qmail ファイルを編集して結果を保存する場合、 保存を実行するプロセスが .qmail ファイルを書き換えている最中にメールが到着し、 qmail-local コマンドのプロセスが不完全な .qmail ファイルが参照してしまう可能性があります。 これはほんのわずかなタイミングで遭遇する可能性は低いですが、 完全にゼロではありません。
以下にディレクトリの sticky 属性を利用して .qmail ファイルを安全に編集する例を示します。 chmod コマンドで sticky 属性を指定するには、 シンボルモードでは「t」を用います。
$ cd
$ pwd
/home/fumiya
$ chmod +t .
$ ls -ld .
drwxr-xr-t 67 fumiya fumiya 10240 Sep 29 00:01 .
$ vi .qmail
…編集中…
$ chmod -t .qmail
$ ls -ld .
drwxr-xr-x 67 fumiya fumiya 10240 Sep 29 00:03 .
一時的な作業ファイルを編集し、 編集が完全に終わったあとに .qmail ファイルに「mv」する方法も安全です。 ファイル名の変更途中 (rename(2)) にほかのプロセスに割込まれることはありませんので、 不完全な .qmail ファイルが表われるタイミングはありません。
$ cd
$ pwd
/home/fumiya
$ vi .qmail.tmp.$$
…編集中…
$ chmod 644 .qmail.tmp.$$
$ mv .qmail.tmp.$$ .qmail
qmail が稼働しているシステムで自分宛のメールを受け取っているユーザーは、 自分のユーザー名に続けてハイフン「-」 と任意の文字列を足したものをローカル部に持つ 「拡張メールアドレス」を利用することができます。 例えば、 yoursite.example.com ドメインのユーザー carol は、 「carol@yoursite.example.com」のほかに 「carol-anything@yoursite.example.com」 いったアドレスでも受け取れます。
拡張アドレスは好きな数だけ用意することができます。 ハイフン以降の「anything」の部分は、 メールアドレスのローカル部に含めることができる文字であれば、 どんなものでも構いません。 ただしこの後の節で解説しているように、 末尾が「-default」、「-owner」となっているアドレスは特殊です。
拡張メールアドレスを用意するには、ホームディレクトリに 「.qmail-拡張名」という名前の特別な .qmail ファイルを作成します。 例えば、ユーザー bob がホームディレクトリに「.qmail-test」という名前の .qmail ファイルを作成すると、 「bob-test@ドメイン部」 というアドレス宛のメールを受け取れるようになります。
拡張メールアドレス用の .qmail ファイルの書式は、 通常の .qmail ファイルとまったく同じです。
$ cd
$ pwd
/home/bob
$ touch .qmail-test
$ chmod 644 .qmail-test
拡張メールアドレスの拡張名部分に大文字が含まれる場合、 対応する .qmail ファイルは、 すべての大文字を小文字に変換した名前になります。 拡張メールアドレスの拡張名部分にドット「.」が含まれる場合、 対応する .qmail ファイルは、 すべてのドット「.」をコロン「:」に変換した名前になります。
ファイル名の末尾が「-defualt」になっている .qmail ファイルを用意すると、 ワイルドカードアドレスとして機能します。 例えば、「.qmail-default」という名前の .qmail ファイルを持つユーザー carol は、 宛先アドレスのローカル部が「carol-」で始まっているのメールなら、 すべて受け取ることができます。 ただし、対応する名前を持つ .qmail ファイルがあるなら、 そちらの指示に従って配送されます。
ユーザー carol の拡張メールアドレスが、 どのような順番で .qmail ファイルを検索し配送するかを見てみましょう。 以下のように、 最初は対応する名前の .qmail ファイルそのものを参照し、 なければ最後のハイフン「-」以降を「-default」にした .qmail ファイルを参照します。
通常 qmail-local は、 メールの転送を行なうとき、 送信者アドレスはそのままにして転送先アドレスに送信します。 これは、「.qmail-拡張名-owner」という名前の .qmail ファイルを用意することで、 メーリングリストマネージャーのように、 転送時に送信者アドレスを置き換えることができます。
さらに「.qmail-拡張名-owner-default」という名前の .qmail ファイルも存在すると、 qmail-local は qmail 特有の VERP (Variable Envelope Return Paths) 機能を利用してメールを送信します。 これにより、送信者アドレスは転送先ごとに異なるアドレスとなります。
Bob (bob@example.net) から
Carol の拡張アドレス carol-foo@hoge.example.com 宛に送信されたメールが
~carol/.qmail-foo
ファイル内の指示により転送されるとき、
送信者アドレスがどのようになるかを見てみましょう。
送信者アドレスの置き換えにより、 転送したメールがバウンスしたときの差し戻し先は、 Bob でなく Carol 宛になります。
送付されたメールがバウンス通知メールの場合は、
送信者アドレスの置き換えは実行されません。
(元の送信者アドレスが空もしくは「#@[]
」の場合)
この節では qmail 付属のマニュアル dot-qmail(5), qmail-command(8) の内容と実際の動作を元に解説します。
.qmail ファイルで指定されたコマンドは、 次のような手順で実行されます。
1. は qmail-lspawn が、 2.〜5., 7. は qmail-local が実行します。 1.〜3. は、評価する .qmail ファイルを決定して配送処理を始める前に 1度だけ実行されます。 4. 以降はコマンドの起動指示ごとに実行されます。
コマンドは、 シェル /bin/sh の -c オプションを介して起動されます。 よって、.qmail ファイル内のコマンド起動の指定には、 シェルスクリプトを記述することができます。 ただしスクリプトは .qmail ファイルの書式に従い、 1行で記述しなければなりません。
起動されたコマンドは、 処理すべきメールのメッセージを標準入力から取得します。 必要がなければ読み込まなくても構いません。
qmail-local は、 .qmail ファイルに記述されている各配送指定に従いメールを別プロセスに渡すとき、 同一のファイル記述子を使い回します。 このため、 コマンドから子プロセスを生成するなどしてバックグラウンドでメールを読み込ませると、 ほかのプロセスと競合する可能性があります。
sendmail とは違い、
メールの先頭に「From 送信者アドレス タイムスタンプ」
という行は付加されていません。
また、送信者アドレスを含む Return-Path: フィールド、
現段階での最終的な配送先アドレスを示す Delivered-To: フィールドも付きません。
これらはそれぞれ環境変数
UFLINE
, RPLINE
, DTLINE
を介して渡されます。
コマンドは必要に応じてこれら環境変数の値をメールに追加します。
qmail は環境変数を利用して配送に関する情報をコマンドに渡します。 sendmail の .forward ファイルから起動されるコマンドのように、 メールのヘッダー部を解析する必要はありません。
以下に qmail-local により設定される環境変数の一覧を挙げます。 値の例は、送信者アドレスが bob@from.example.net、 宛先アドレスが carol-foo-bar@to.example.com、 配送先のローカルユーザーが carol であるときの値です。
送信者アドレス関連 | ||
---|---|---|
変数名 | 意味 | 値の例 (備考、条件など) |
SENDER |
送信者アドレス | bob@from.example.net |
NEWSENDER |
転送時に用いるべき送信者アドレス 通常は SENDER と同じ値。
.qmail-拡張名-owner ファイルの存在によって置き換る。
(→「7.2.3 転送時の送信者アドレスの変更」)
|
bob@from.example.net (.qmail-foo-bar-owner が存在しない場合) |
carol-foo-bar-owner@to.example.com (.qmail-foo-bar-owner が存在する場合) |
||
宛先アドレス関連 | ||
変数名 | 値の意味 | 値の例 (備考、条件など) |
RECIPIENT |
宛先アドレス | carol-foo-bar@to.example.com |
LOCAL |
宛先アドレスのローカル部 | carol-foo-bar |
EXT |
宛先アドレスの拡張名の部分 | foo-bar |
EXT2 |
EXT の値の最初のハイフン「-」までを取り除いたもの |
bar |
EXT3 |
EXT の値の 2番目のハイフン「-」までを取り除いたもの |
(空白) |
EXT4 |
EXT の値の 3番目のハイフン「-」までを取り除いたもの |
(空白) |
HOST |
宛先アドレスのドメイン部 | to.example.com |
HOST2 |
HOST の値の最後のドット「.」以降を取り除いたもの |
to.example |
HOST3 |
HOST の値の最後から 2番目のドット「.」以降を取り除いたもの |
to |
HOST4 |
HOST の値の最後から 3番目のドット「.」以降を取り除いたもの |
to |
配送先のローカルユーザーと .qmail ファイル関連 | ||
変数名 | 値の意味 | 値の例 (備考、条件など) |
USER |
配送先のユーザーのログイン名 | carol |
HOME |
USER のホームディレクトリ |
/home/carol |
DEFAULT |
ファイル名が「-default」で終わる .qmail ファイルを評価したときの「default」部分の実際の名前 | 未定義 (.qmail-foo-bar を評価した場合) |
bar (.qmail-foo-default を評価した場合) |
||
foo-bar (.qmail-default を評価した場合) |
||
ヘッダー関連 | ||
変数名 | 値の意味 | 値の例 (備考、条件など) |
UFLINE |
mbox 形式メールボックスでメールメッセージの先頭に付ける 「From 送信者アドレス タイムスタンプ」行 | From bob@from.example.net Mon Oct 01 21:56:18 2001 + 改行 |
RPLINE |
Return-Path: フィールド | Return-Path: <bob@from.example.net> + 改行 |
DTLINE |
Delivered-To: フィールド | Delivered-To: carol-foo-bar@to.example.com + 改行 |
qmail-local は実行したコマンドの終了コードを評価して、 配送の正否の判定と以降の配送指定を実行するかどうかを決定します。 終了コードは以下のように分類されます。
ドキュメントなどに記述がないため確証はありませんが、
qmail-command(8)
にて定義されている 64 から 78 までの値と「そのほか」の値の終了コードは、
ヘッダーファイル /usr/include/sysexits.h
で定義されている定数を元に割り当てられたものと思われます。
このヘッダーファイルは、
システムコマンドが使用すべき終了コードとその意味を定義しています。
FreeBSD 4.3 の同ヘッダーファイルを見ると、 次のような定数が定義されいるのがわかります。 多少の違いがあるものの、 FreeBSD 以外のほかのシステムでも同じ名前、同じ値、 同じ意味の定数が定義されています。
/usr/include/sysexits.h
で定義されている定数 (FreeBSD 4.3):
#define EX_OK 0 /* successful termination */
#define EX__BASE 64 /* base value for error messages */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#define EX__MAX 78 /* maximum listed value */
qmail の .qmail ファイル向けのコマンドは終了コードとして
0 か 99〜111 を返すようになっていますが、
sendmail の .forward ファイルからの利用を想定しているコマンドは、
sysexits.h
の EX_XXXX
定数で定義されている 0 か
66〜78 の値 (システムにより多少異なる) を返します。
このため、.forward 用に作成されたメール処理コマンドを .qmail で利用するには、
本来ならば、
終了コードを qmail-local 向けに変換するラッパーを介する必要があります。
しかし、qmail-local は sysexits.h の終了コードも想定している (と思われる) ため、
ほとんどの場合そのまま流用できます。
qmail には .qmail ファイルで利用できるコマンドがいくつか用意されています。 ここで簡単に紹介します。 それぞれマニュアルが用意されていますので、 詳細はそちらを参照してください。
forward コマンドは、
指定されたアドレスにメールを転送します。
送信者アドレスは環境変数 NEWSENDER
の値となります。
|forward address ...
「&宛先アドレス」と変わりないじゃないかという話もありますが、 宛先アドレスを動的に生成したいときに有用です。
|forward "david-$RECIPIENT"
./Maildir/
condredirect は条件付きの転送処理コマンドです。 引数に指定されたコマンドを起動し、 その終了コードが 0 ならばメールを転送します。
condredirect により起動されたコマンドは、 標準入力からメールを読み込むことができます。 必要ならばメール本文や環境変数の値を参照し、 条件に合うかどうかの判定の材料にします。
|condredirect address command [arg ...]
|condredirect carol-info@example.com [ "$HOST" = "info.exmaple.com" ]
./Maildir/
※ 条件が合致すると condredirect はメールを転送して 99 を返すため、
続く ./Maildir/
への配送は実行されない。
bouncesaying は条件付きのバウンス処理コマンドです。 引数に指定されたコマンドを起動し、 その終了コードが 0 ならばメールをバウンスします。 コマンドの指定を省略すると、無条件でメールをバウンスします。
bouncesaying 自身は、ほとんどなにも処理をしません。 バウンスさせる場合は終了コード 100 を返すことで、 qmail-local にバウンス処理を実行させます。
|bouncesaying message [command [arg ...]]
|bouncesaying 'Mr. David retired in February.'
except コマンドは、 起動したコマンドの終了コードを得て、 その意味を反転させて終了コードを返します。 単独でも利用できますが、 condredirect, bouncesaying と組み合わせても利用できます。
|except command [arg ...]
|bouncesaying 'I do not accept Bcc.' except iftocc
./Maildir/
※ iftocc は次節で紹介する mess822 コマンドライブラリに含まれているコマンドで、
環境変数 RECIPIENT
で示される宛先アドレスがメールの
To:/Cc: フィールドに含まれていると 0 を、含まれていなければ 100 を返す。
qreceipt コマンドは、 メールが無事到着したことを通知するメールを送信者アドレスに送付します。 この通知を必要とする送信者は、 メールの Notice-Requested-Upon-Delivery-To: フィールドに宛先のアドレスを含めなければなりません。
Notice-Requested-Upon-Delivery-To: フィールドは、 D. J. Bernstein 氏が提唱している独自のヘッダーフィールドです。 RFC 2298 「An Extensible Message Format for Message Disposition Notifications」 で定義しているメッセージ到達通知の仕組みとは異なるものです。
この文書は過去に IETF (The Internet Engineering Task Force, http://www.ietf.org) のインターネットドラフトとして公開されていましたが、 現在は期限切れで削除されています。 残念ながら RFC にはなっていません。
|qreceipt youraddress
./Maildir/
|qreceipt alice@yoursite.example.com
qbiff コマンドを .qmail ファイルに組み込むことで、 メールの到着をユーザーの端末に通知することができます。 qbiff コマンドには必要な引数はありません。
./Maildir/
|qbiff
qbiff コマンドによる通知を受けるには、
biff コマンドで通知の仕組みを有効にしなければなりません。
ログインしたあとに、biff y
と実行してください。
biff コマンドを引数なしで実行して
「is y
」と表示されれば有効になっています。
$ biff
is n
$ biff y
$ biff
is y
preline は、 sendmail の .forward ファイルでの利用を想定しているコマンドを .qmail ファイルで利用するためのラッパーコマンドです。
.forward ファイル向けに作成された旧来のコマンド群は、
qmail-local が設定する環境変数を関知することができません。
preline は、
qmail-local が設定した環境変数
UFLINE
, RPLINE
, DTLINE
の値をメールに付け足し、
.forward 用コマンドが想定するメールの形式にします。
|preline [-frd] command [arg ...]
UFLINE
の値を付け足さないようにする
RPLINE
の値を付け足さないようにする
DTLINE
の値を付け足さないようにする
|preline vacation carol
ここでは、 .qmail ファイルで有用なコマンドを含むソフトウェアパッケージを簡単に紹介します。 それらは .qmail ファイルに限らず、 ほか場面でメールのメッセージを操作したいときにも便利です。
mess822 は、 メールのメッセージの解析を行なうためのライブラリと、 それを利用して実装されたコマンドを含むソフトウェアです。 mess822 は、qmail と同じく D. J. Bernstein 氏による作品です。 名前に含まれる「822」とは、 インターネットメールのメッセージ形式を定義している RFC 822 (「Standard for ARPA Internet Text Messages」、 RFC 2822 で置き換えられた) のことを指します。
mess822 に含まれているコマンドを簡単に紹介します。
RECIPIENT
または引数で指定されたアドレスが
To:/Cc: フィールドに含まれているか検査する。
比較の際、大文字/小文字は同一視される。
qtools は、 qmail 環境で使用するためのユーティリティコマンド群です。 .qmail ファイルでの使用を想定しています。 qtools には、 mess822 のコマンドに似た名前のコマンドが 10 種類以上も含まれています。