2014の10日目の記事です。Postfixは2.3からmilterという仕組みをサポートしました。filter」の略で、送信したメールまたは受信したメールになんらかの処理を行う仕組みです。Sendmailが作った仕組みですが、Sendmail・Postfix以外のMTAでもサポートしているMTAがあります。2.6ではSendmailとほぼ同等の機能をサポートしています。SendmailとPostfixでマクロ(後述)名が違うなど一部非互換な部分もありますが、SendmailでもPostfixでも同様に使えます。filterとの使い分けはどうすればよいか、という情報が有用かと思いますが、ここではそのような説明をしません。そのような説明ではなくmilterプロトコルについて説明します。milterプロトコルについての情報は、Postfixユーザーの人にとっては有用ではなく、milter開発者にとってもそんなに有用ではなく、一部のmilterライブラリー開発者にとっては有用*1です。Calendarっぽくなくてごめんなさい。残念ながら2014/12/10中に完成しませんでした。続きはいつかどこかで。はじめに多くのmilterはlibmilterというSendmailが提供しているライブラリーを利用して実装します。libmilter内でmilterプロトコルを実装しているのでmilter開発者がプロトコルの詳細を気にする必要はありません。libmilterのAPIを知っていれば十分です。ここではlibmilterのAPIは説明しません。milterを作るための情報を探している人は次のページを参考にしてください。CまたはC++でmilterを実装したい人向けlibmilterのAPI(英語):Sendmail提供のライブラリー。manager提供のライブラリーlibmilter-clientを使ったmilterの実装例。libmilter-clientはイベント駆動ベース。manager提供のlibmilter-clientのRubyバインディングの使い方。gem:Rubyでmilterプロトコルを実装したライブラリー。ppymilter(後述)をRubyで実装したもの。Pythonでmilterを実装したい人向けpymilter:libmilterのPythonバインディング。ppymilter:Pythonでmilterプロトコルを実装したライブラリー。Perlでmilterを実装したい人向けSendmail::Milter:libmilterのPerlバインディング。Sendmail::PMilter:Perlでmilterプロトコルを実装したライブラリー。Frameworkの実装。この中にmilterプロトコルの実装がある。普通の人向けの情報は提供したので、ここからは普通の人向けではない情報です。実はmilterプロトコルの仕様書はありません。Sendmailでの挙動が事実的な仕様になっています。Postfixや各言語でのmilterプロトコルの実装は、Sendmail・libmilterのソースコード*2や、実際のSendmail・libmilterの動きを参考にmilterプロトコルを実装したものです*3。milterプロトコルについてまとめたメモはあります。Perlでmilterプロトコルを実装した人が残したもの(英語)です。まとめた時期が古い(milterプロトコルのバージョンでいうと2)ので新しいmilterプロトコル(最新はバージョン6)についての情報はないのですが、基本的なことからまとまっているので有用な情報です*4。ベースのやりとりそれではmilterプロトコルについて説明します。ベースとなるやりとりの方法について説明します。milterプロトコルはMTAとmilter間でやりとりします。基本的に、MTAからコマンドを送り、milterが応答する、という流れになります。ーコマンドと応答のフォーマットは同じです。フォーマットは次の通りです。|「データサイズ」はネットワークバイトオーダーで表現されています。データサイズはデータサイズ自体のサイズ(4バイト)を含みません。「データID」と「データ」を合わせたサイズ(バイト数)です。「データID」はこのデータの種類を示す1文字のASCII文字です。「CONNECTというコマンド」を表すデータIDは「C」です。「データ」はデータIDに関連するデータです。データIDによって中身が変わります。0バイトのときもあります。milterプロトコルを実装するときは、まずは、このフォーマットをデコードする処理とこのフォーマットにエンコードする処理を実装します。managerでの実装です。一連のやりとりベースのやりとりがわかったところで、次は一連のやりとりについて説明します。個々のやりとりはこのあと説明します。milterプロトコルはSMTPと関連が深いです。SMTPの1つのセッションがmilterプロトコルでの1つのセッションに対応します。milterプロトコルでの1つのセッションは次のようになります。FROMコマンド」から「メッセージ終了コマンド」の「応答」までを複数回繰り返します。SMTPのセッションと似ていますね。TOコマンド」、「DATAコマンド」はそれぞれSMTPの対応するコマンドを実行したときに実行されます。SMTPで「DATA」の後に指定したメッセージはパースされて個別にmilterに送られます。次は個々のやりとりのうち「MTAから送るデータ」について説明します。MTAから送るデータをコマンドと呼びます。コマンドのID、名前、説明は次の通りです。メールトランザクション中で終了するコマンド。本文のチャンク(一部)を送るコマンド。本文が大きい場合は複数のチャンクにわけて渡される。(複数の本文チャンクコマンドが送られる。接続してきたSMTPクライアントに関する情報を送るコマンド。コマンドに対する付加情報を送るコマンド。メッセージ全体を送ったことを知らせるコマンド。このコマンドの応答でだけメールを変更できる。SMTPのHELO/EHLOに関する情報を送るコマンド。メッセージのヘッダーを1つ送るコマンド。複数のヘッダーがある場合は複数回送られる。FROMに関する情報を送るコマンド。すべてのヘッダーを送ったことを知らせるコマンド。milterセッション開始時に動作を調整するコマンド。