ここでは大きく分けて次の4つの作業があるとして、それぞれの作業の流れを考える。
1.メール内容の入力と配信予約
2.配信の確認
3.配信のキャンセル(スケジュール配信のみ)
4.メールアドレスのクリーニング
1.メール内容の入力と配信予約
2.配信の確認
3.配信のキャンセル(スケジュール配信のみ)
4.メールアドレスのクリーニング
1 | ユーザー側 | システム側 |
2 | タイトルと内容を記述し、送信ボタンを押す※1 | |
3 | プレビューを確認し、確認ボタンを押す※2 | |
4 | 作業の終了画面でエラーが起こっていないことを確認し、終了 | バックグラウンドでDBの配送用テーブルに追記(※3) |
5 | CRON等を用いて一定時間ごとにメールサーバに対してキューを追加(※4) | |
6 | メールサーバが自動的に配信(※5) |
※1 即時の配信開始か、またはスケジュール配信かを選べることが望ましい
※2 HTMLメールを採用する場合、AJAXを用いる等して、プレビューはフォーム画面で確認出来ることが望ましい
※3 要件上INSERT文を何万件も発行せねばならない場合、アプリケーションからINSERTを何万件も繰り返すのは負荷が一気に高まるため危険である。SQLファイルを作成して、直接そのSQLファイルをMYSQLにインポートしたほうがよい。とてもたくさんあるのであれば、全てを一度の処理でDBに入力するよりも、小分けにして入れたほうがよいのはもちろんである。なお、DBの配送用テーブルを例えばユーザー管理テーブルなどと一緒にしてはならない。ロックがかかるとレスポンスに多大な影響がでる。
※4 これも、間違っても何万件もあるデータを全て一度に送ろうとしてはいけない。最悪、詰まってメールサーバの緊急メンテナンスを入れる羽目になる。また、キューに追加したことは別途ログに残しておくほうがよい。
※5 キューが詰まった場合、”自動的に”ではなく”手動で”行わねばならなくなる
メールを送った後で確認せずに送りっぱなし、というわけにいかないのは当然である。
しかし、ユーザーに確実にメールが配送されたことを100%確認することは、現在のメールの仕様では残念ながらできない。そのため、
ある程度の誤差は技術上の問題で仕方ないと割り切って、代替案でもって確認することになる。
まず、作業の流れから、次の状況に一つでも不備があれば間違いなく送られないため、下記の動作が期待通りに動いていることを最低限確認する。
- データベースに配送予定が正しく追記されており
- かつ、データベースにキューを追加した記録が残っており
- かつ、キューが溜まっていない
これは例えば、データベースの配送予定テーブルの集計表と、MTAの残存キュー問い合わせによってチェックすることができる。
MTA(ここではpostfix)の残存キュー問い合わせの例:
queue_count.sh
#!/bin/sh
QUEUE_PATH="/var/spool/postfix"
echo "### Postfix MailQueue File Count(PATH:$QUEUE_PATH) ###"
for i in `ls $QUEUE_PATH`
do
echo -n $i :
ls -l $QUEUE_PATH/$i/* | grep "^-" | wc -l
done 2> /dev/null
このスクリプトは下記URLのこーぢ氏のブログの内容をそのまま引用している。
http://swkoji.blog63.fc2.com/blog-entry-24.html
リンクだけにとどめようかとも思ったが、ブログが停止する可能性を危惧し、あえてスクリプトの全文を引用させて頂いている。
ただしこれだけでは、先方のメールサーバに拒否を受けていたり、プログラム自体にバグが残っている(!)などの原因で実際に送られていない場合のチェックができない。そこで、次のような対策をとる。
- 確認用のID付IMGタグを埋め込んで、開封をトレースする。使えるのがHTMLメールに限定される点が泣きどころだが、これはメールの開封率をチェックすることも出来るようになるメリットがある。ただし、ユーザーのメーラの設定によっては画像が表示されないため、過信は禁物である。
- 開封確認を追加する。ただし膨大な量の開封確認が届く上に、開封確認メールはあまりメジャーでないためユーザー離れを引き起こすおそれがあり、よほど重要なものでなければ行わないほうがよいだろう。
- 管理者のメールアドレスを何点か混ぜておく。サンプル数が少ないため、統計の根拠としてはやや薄弱ながら、少なくとも届かなかった場合にはすぐ気付ける。なお、実装する倍は携帯とPCのメールアドレスを両方ともいれておくとよい。携帯はDOCOMOとAUとSoftbankの3キャリアがあればなお良い。
- 顧客のレスポンス率をチェックする。レスポンス率が普段と比べて異常なほど悪く、しかもレスポンスのないユーザーに何らかの傾向がみられる場合(たとえば、一定地域の反応がない等)は、特に要注意。
メール配信のキャンセルは、相手方のメールサーバーに届いてしまったあとでは、基本的に不可能である。(メールサーバーの管理者に連絡し、ユーザーが受信する前にキューを消してもらえれば別だが、現実的ではない)。
しかしながら、メールがまだ相手方のメールサーバーに届けられていないのであれば、キャンセルは可能である。具体的には、データベースに記録した配信予約を取り消せばよい。MTAのキューに残っているならそれも消せるが、そちらはあまり期待できないので正規オペレーションには含めない。
1 | ユーザー側 | システム側 |
2 | 配信状況表示画面から、キャンセルボタンを押す※1 | |
3 | 本当にキャンセルしてよいか確認する | |
4 | 作業の終了画面でエラーが起こっていないことを確認し、終了 | DBの配送用テーブルに変更または削除をかける※2 |
※1 すでに送られたメールの状況をチェックする必要はあろう。
※2 削除してもキャンセル自体は成功するが、後々のトレースができない点が危険である。キャンセル記録は保存しておくべきである。削除する場合でも、別途ログを取っておくことは良い管理の工夫である。
一斉メールの送信では、システムが100%正確に動いていたとしても、尚、必ずといっていいほど不達が発生する。なぜなら、ユーザー自身がメールアドレスを時折廃棄または変更し、登録時のメールアドレスを無効にするからである。また、場合によっては、最初から正確なメールアドレスが登録されていないこともあるだろう。(確認メールを送ってから登録を完了させる手順を取れなかった場合、こうなりやすい)
この使えないメールアドレスを放置しておくと、メールサーバのリソースの確実な浪費や、相手方メールサーバからメールアドレスの管理不行き届きを理由とした配送拒否に繋がる。そのため、届かなかったメールアドレスに対しては送信を行わないよう、必ず管理する必要がある。メールアドレスのクリーニングと呼ばれる作業である。
メールアドレスが間違っていたことによって届かなかったメールは、幸いにしてエラーメールとして返送される仕様となっているため、検知することができる。
なお、エラーメールは、return-pathとenvelope-senderをメールの送信時に設定しておくことで、期待通りに帰ってくる(はずである)。これは明示しなければ記述されないのが普通なので、アプリケーションやフレームワークの仕様に応じた実装が必要である。
4.1 手オペによるメールアドレスのクリーニング
もっとも単純な方法は、管理者またはオペレータのメールアドレスにエラーメールが届くようにして、手オペでエラーメールのアドレスを一つづつ消していく方法である。配信数が少なければ(〜1000件程度だろうか)、大した手間もないだろうから、全てこれで行っても十分だろう。
4.2 自動処理によるメールアドレスのクリーニング
管理者またはオペレータの手オペによるクリーニングは、配信数が多い場合は現実的でない。また、そうでなくとも、このような単純作業はなるべくシステム任せにしたくなるのは自然な感想である。
そこで、メールの受信時になんらかのアプリケ―ションが走るよう設定し、エラーメールを自動で解析、この検出されたアドレスを自動で使用不能にすることにする。
PHPで行う場合の手順としては、例えば
1)PEAR の Mail_Mimeでエラーメールの本文をデコードし、メールアドレスを取得して使用できなくするCLI版のアプリを用意する。
2)aliases(/etc/aliases)に記述を加え、サーバー側でメール受信時にアプリケーションが走るよう設定する。
といった手順が考えられる。
なお、デコード失敗に備え、期待通りに動作させられなかった場合は手オペによるクリーニングが可能なように管理者アドレスに配信する、といった工夫があるとなおよいだろう。
タグ
コメントをかく