私は現在、非常に小さなプロジェクトに取り組んでいます。私は smtpd.py に基づいて作業していますが、ゆっくりとまったく異なるものに向かっています。
これはsmtpサーバーです。現在、メールを受信し、中継することができます。それはかなり簡単ですが、私は自分自身にいくつかの質問をするところまで来ました。
smtpd.py は asyncore と asychat を使用します。問題は、非同期 API を使用する単一プロセスであることです。すべてが機能し、問題なくさらに進むことができます。
問題は、サーバーがポート 25 にバインドされている場合、ルート uid の下にある必要があることです。ここに大きな問題があります。smtp サーバーの背後にあるアイデアは、Python を使用して多くのことを実装できるということです。ローカル ユーザー、データベース、または任意のデータ ストアにアクセスできるようにしたいと考えています。ハッシュまたは現在 Python でサポートされているものから、または必要に応じてサポートを追加することもできます。
問題は、ルートユーザーを使用してこのすべての制御を行うことは非常に安全ではないと感じていることです...誰かが何かを実行して、ルートpythonシェルでうまくいくとしたらどうでしょう...
そのため、最初はスレッドを作成し、os.setuid を使用してそれらに別の uid を設定したかったのですが、機能していないようであるか、危険でもある可能性があります。
私の 2 番目のアイデア: 接続を受け入れてからフォークし、uid を変更します。フォークされたプロセスからソケットを読み書きできるはずで、すべて問題ありません。
3 番目のアイデアは、メッセージを処理するローカル サーバーにすべてのメッセージを中継するプロキシ サーバーを用意することでした。唯一の問題は、私の smtp サーバーを使用することになっていない誰かが、実際には何にもアクセスできない単なるプロキシであるため、プロキシが認証または何もできないことです。
フォークが最も興味深いソリューションだと思います。
あるいは、まだ考えていないことがあるかもしれません。
とりあえずありがとう
- 編集 -
root でプロセスを開始し、ソケットが作成されると、os.setuid を使用して別のユーザーに切り替えることができるようです。移植性はあまり高くないと思いますが、今のところ大きな問題ではありません。Pyramid/Pylons/Paste のコードを検索した後、私はついにそれを見つけました! SocketServerモジュール。おそらく、ForkingMixIn または ThredingMixIn のいずれかを使用する予定です。スレッドの量などを定義することが可能です。
いずれにせよ、なぜ私が postfix、exim、または qmail を使用していないのか不思議に思っている人のために.. それは非常に簡単です。私は本当に smtp サーバーを作っているわけではありません。メールの受信、受信者または送信者の受け入れまたは拒否など、最低限必要なもののみを実装する場合、smtp プロトコルは非常に単純です。最初の「.」をエスケープします。RFC では、データは "\r\n.\r\n" で終わると記載されているためです。
私が見ているように、Python は積み木に似ています。アイデアは、smtp サーバーを作成することではなく (ESMTP を確実に実装します)、独自のサーバーを構築するための「フレームワーク」を作成することです。私が抱えている問題は、私が一人だとは信じていません。誰かが構成ファイルと postfix を構成する方法を設計しました。ハードコードされており、すべてのケースに適合するわけではありません。すべてのケースに適合するサーバーを作成することもうまくいきません。それはおそらく巨大で醜いものになるでしょう。アイデアは、サーバーに必要なパーツを簡単に追加できるようにすることです。データベースを使用する場合は、既存のモジュールで必要なデータベースを使用してください。クエリを実行し、結果を送り返します。
すべてのドメイン、特定のドメイン、さらにはユーザー名に適用されるルールを本当に定義したい場合は、それが可能になるはずです。
たとえば、私はユースケースを見ます。本当に奇妙なものですが、それでも。1 台のサーバーのみを使用して、postfix でそのようなセットアップをセットアップするのはどれほど簡単でしょうか。あなたは3つのドメインを持っています。a.com、b.com、c.com。
a.com は、受信したすべてのメールを maildir と b.com に同じユーザー名で送信します。b.com は、受信したすべてのメールを maildir と c.com に同じユーザー名で送信します。c.com は、受信したすべてのメールを maildir と a.com に同じユーザー名で送信します。
すでに送信したメールを受け入れるドメインはありません。
言い換えると
a.com -> b.com -> c.com -x-> a.com
b.com -> c.com -> a.com -x-> b.com
...
ここでの考え方は、メールは複数のドメインに複製されますが、その所有者には戻らないということです。そのようなユースケースは非常に単純なはずです。しかし、すべてのドメインがメールを別の場所に保存する場合や、2 回のバウンスごとにメールを保存したい場合はどうでしょう。
a -> b -> c(save)
a -> b(save) -> c
a(save) -> b -> c
already saved to C so stop the mail would be sent 9 times