私は約のWebアプリケーションを持っています。3 万人のユーザーと急速に成長しています。電子メールを介していくつかの機能を有効にしたいと考えています。つまり、各ユーザーに一意の電子メール アドレスを割り当てることを意味します (セキュリティ上の理由から)。これらの一意のアドレスに送信された電子メールは、PHP スクリプトに転送する必要があります。PHP スクリプトは、メールのすべての部分 (ヘッダー、本文、添付ファイル) にアクセスする必要があります。これを設定する正しい方法が何であるかわかりません。私たちは現在 sendmail を使用しており、それを使い続けることを望んでいます (問題がある場合、これは Linux です)。スクリプトへの個々の電子メール転送を取得できましたが、(私の考えでは) 30,000 のエイリアスを作成し、新しいユーザーがサインアップするたびに新しいエイリアスを作成するのはスケーラブルではありません。PHPスクリプトに受信者である一意の電子メールアドレスを伝えるだけの、ある種のキャッチオール/正規表現ベースのソリューションがあれば、私はもっと幸せです。
3 に答える
30k アカウントでは、処理が予想されるトラフィックに関する情報は提供されません。しかし、それは別の質問であるとしましょう。
catch all
ユーザーのアドレスを作成したドメイン (基本的には ) 内のすべての電子メールを単純に受け入れるタイプのアカウントを作成できます*@domain
。次に、受信メールごとに処理スクリプトを起動できます (通常は、stdin
ストリームからメール本文全体を取得し (PHP で 経由でアクセスできますphp://stdin
)、好きなように処理できます。しかし、PHP を使用したい場合 (または各メールは新しい PHP プロセスを生成し、すべての拡張機能を初期化する必要があるため、これらすべてに時間とリソースが必要であり、1 つの大きなスパムが殺到し、ボックスがほとんど焼けてしまいます。
別の方法として、メールを他のメールと同じようにメールボックスに集めて、スクリプトでそこから取得することもできます (直接、掘り下げて、maildir
または IMAP や POP などのメール プロトコルを介して)。これは、管理の観点からはより良いように見えます。メール サーバーが着信メールを受け入れることができる限り、システム全体が引き続き機能します。いくつかのフィルター規則を (MTA レベルで) 設定してシステムを「分割」し、受信メールを単一のメールボックスではなく複数のメールボックスに配信することもできます。次に、これらのメールをより少ない手間で並行して処理できます (複数のインスタンスで同じメールを処理することを気にする必要はありません)。「パーティション」スキーマは非常に何でもかまいません。つまり、完全なアドレス命名スキームに応じて、文字ベースの場合は別のメールボックスになるかa*@
、b*@
または[a-d]*@]
(トラフィックに依存します)、実際には問題ではありません。
または、受信メールの本文をデータベースに入れ、POP/IMAP 処理を必要とせずに上記のように処理することもできます。
何を選択しても、処理スクリプトをメール受信プロセス チェーンに直接配置しないことをお勧めします。通常、1 分間の遅延は問題ではありません (したがって、任意の種類のデーモンを実行して、処理、cronjob などのためにメールをフェッチすることができます)、ユーザーは文句を言わずにそれだけ待つことができます - インスタント処理はおそらくそうではないようですあなたの場合も必須です。しかし、そうであれば、PHPは最適なツールではないかもしれません。
編集:(コメントの質問に答え、コメントのサイズ制限に達しないようにするため)
ここで正確な構成指示を与えるほど Sendmail に精通していません (私はカスタマイズされた qmail を使用しています) が、いくつかの一般的なヒントが適用されることを願っています。まず、Sendmail は仮想ユーザー (つまり、 に存在しないユーザーのメール ボックス) をサポートしていると思います/etc/passwd
。その場合、MTA は通常、いくつかの組み込みプロバイダーを使用して DB にクエリを実行できるようにする必要があります (対象の電子メール アドレスが有効かどうか、およびメールを送信するユーザーのホーム ディレクトリがどこにあるかを確認するため)。または(さらに良い)外部プログラムを呼び出してそれを行います。実際にはユーザーがいないため、ここでは後者が勝者です。そのため、小さなスクリプトを作成するか、(これもパフォーマンスの点で優れています) C アプリを作成して、このトリックを実行できます。必要なのは、いくつかの簡単な事前定義されたルールに基づいて、受信メールをいくつかの物理メールボックスに「分離」することだけなので、いくつかif()
の +substr()
s で完了です。数行で、DB は不要で、非常に迅速です。または、さらに良いことに、ここで最もばかげたアプローチを試すこともできます-メールがヒットした場合、またはメールの 50% が終了し、残りの 50% が終了した場合 (または 4 つのターゲットアカウントを使用する場合は 25%が終了したroundrobin
場合) は、実際には無関係です。など)それがあなたが気にするべき唯一の条件だと思います. そのために使ってみることもできますが、それは無意味であり、パフォーマンスに最適ではないと思います。accountA
accountB
A
B
procmail
メールをデータベースに入れることについて。これは MTA に依存します。デフォルトでは、メールを maildir に入れるよりも遅いため (DB は通常他のホストであるため)、誰もそうしませんが、まだ解決策がいくつかあります。それを行うSendmailのサードパーティパッチを探すか、物理メールボックスからDBにメールを「コピー」する別のスクリプト/アプリを追加してください。あなたは言うかもしれませんが、それは遅くなります。確かに、しかし繰り返しになりますが、あなたのケースで非リアルタイム処理が本当に重要かどうかはわかりません(私の盲目的な推測です-そうではありません)。ここで数ミリ秒節約できても、ソリューション全体のメンテナンスに数分かかる場合、選択肢は明らかです。
ところで:念のため-私が書いたときはいつでも、ファイル形式ではなく、ユーザーmailbox
のメールのコンテナを意味していました。ファイル形式(または派生的なもの)に関しては、はるかに優れた選択です。 mailbox
maildir
本当にすべての受信メールに対してPHPをフォークしたいですか?あなたがまともなメール量を扱っているならば、それは高くつくかもしれません。メールサーバーに、受信メールを処理してデータベースに挿入するカスタムコールバックを設定し、処理する新しいメッセージを継続的にポーリングするワーカースクリプトを作成してみませんか?
mail-to-dbの部分は、すべての処理を実行するよりもはるかに軽量である必要があります。これにより、キューが解放されるため、ほぼ同時に大量のリクエストを受け取った場合でも、システムが処理しようとして倒れることはありません。それらすべてを一度に。
小規模ではありますが、これと同様の実装を行いました...ただし、目的に合わせて拡張する必要があります。
2つの別々の問題
(1) メール - 前述のキャッチオールは良い解決策ですが、スパムや不正な形式の電子メール アドレスに対処する必要があります (これは良いことでも悪いことでもあります)。サーバーを所有している場合は、「架空の」アカウントにエイリアスを設定し、メールサーバーにそれらすべてを同じ中央メールボックスにドロップするように指示するだけで、実際のアカウントを個別に作成する必要がなく、ヘッダー情報がそのまま残るため、タスクが完了します。詳細はメールソリューションによって異なりますが、メールサーバーはこのタスクとボリュームを処理するのに十分な設備が整っている必要があり、エイリアスの作成をスクリプト化できる必要があります...そうでない場合はキャッチオールに戻ります
(2) PHP の解析と処理 - PHP の組み込みの pop3 関数は、(現在) 単一の電子メール アカウントのチェックとメッセージの処理を簡単に処理できます。これを実行するために使用した関数の例をいくつか示します。
function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false){
$ssl=($ssl==false)?"/novalidate-cert":"";
return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass,OP_SILENT));
}
function pop3_stat($connection){
$check = imap_mailboxmsginfo($connection); # changed from $imap
return ((array)$check);
}
function pop3_retr($connection,$message,$section='1'){
return(quoted_printable_decode(imap_fetchbody($connection,$message,$section)));
}
function pop3_dele($connection,$message){
return(imap_delete($connection,$message));
}
function pop3_close($connection){
return(imap_close($connection,CL_EXPUNGE));
}
すべて非常に一般的であり、コントロールが必要ない場合は、おそらくそこにクラスがあります。要するに、PHP には、メール メッセージをすばやく解析して処理するために必要なものがすべて備わっています。