fml がメールを読みこむ際のキューイング
fmlの各プロセスは MTA から起動され、STDIN(標準入力)からメールを読みこ
みます。
fml は、いったんメールを読みこみ、まずはディスクに書き込みます
(incoming queue へ書き込む)。書き込みに成功した場合、その書き込んだファ
イルに対してメッセージの解析をスタートします。これにより、少なくとも読
みこんだオリジナルのメールの記録は残せます。
もし、失敗した場合、exit(EX_TEMPFAIL)します。たいていの OS では
exit(75) です。このエラーコードをうけとると、MTA は一時的なエラーがお
こったとみなすため、このメッセージの再送処理を試みてくれます。
incoming queue の処理は Mail::Delivery::Queue を使い、ML固有の queue
で管理されます。一連の処理が終ると、たいてい、そのプロセスの最後に、
このキューは消されます。
fml からメールで返事を送り返す
送り返すべきメールは
Mail::Delivery::Queue
を使いML固有の queue に入れます。
queue に入ったメールは、のちに
FML::Process::QueueManager
クラス経由で(配送)処理をします。
微妙に処理が異なりますが、記事の配送もコマンドメールも同様に
Mail::Delivery::Queue ベースのキューイング処理をしています。そのため、
配送処理の途中でエラーが起きた場合、別のfmlプロセスにより再送処理が行
なわれます。
fml の中ではどう書くのか?
あるメッセージ(テキストメッセージ)を送り返したい場合は、次のように書きます。
$curproc->reply_message( "you are not a ML member." );
この場合の受信者はコマンドの結果などを受けとる人、
fml にリクエストをした人です。
ファイルを送りたい場合や画像ファイルを送りたい場合は次のようにします。
$curproc->reply_message( {
type => "text/plain; charset=iso-2022-jp",
path => "/usr/local/etc/fml/main.cf",
filename => "main.cf",
disposition => "main.cf example",
});
$curproc->reply_message( {
type => "image/gif",
path => "/some/where/logo001.gif",
filename => "logo.gif",
disposition => "attachment",
});
mail queue と配送の仕組み
FML::Process::QueueManager により
特定の queue ファイルが queue ディレクトリから pickup され、
Mail::Message で parse され、
FML::Mailer 経由で
Mail::Delivery が実際にメール配送処理をします。
Mail::Delivery::Queue
↓
↓→→→ キューディレクトリ
↓
FML::Process::QueueManager
↓
↓←←← キューディレクトリ
↓
FML::Mailer
↓
Mail::Delivery
キューを操作する際には、対象のキューを flock(2) します。ロックを他の
ATOMIC 操作を使って実装してもよいのですが、
操作途中に OS が逝ってしまうケースを想定すると、
やはり flock(2) を使うべきでしょう。
mail queue ディレクトリ
queue ディレクトリは複数のディレクトリからなります。
new/
active/
incoming/
deferred/
info/sender/
info/recipients/
info/transport/
info/ には envelope 情報が格納されます。
また incoming/ は incoming queue ですが、それ以外のディレクトリは
outgoing 用です。
queue ファイルを作る時は、一旦 new/ に作成します。
queue ファイルを作る作業が終了し、配送準備 OK となったら
new/ から active/ に移動されます。
つまり active/ にあるファイルは配送準備ができているものです。
queue ディレクトリをロックする
特定の $queue_id object ごとに lock() と unlock() メソッドを使い、
ロックをかけます。
ロックは active/$queue_id ファイルに対しての flock(2) システムコールです。