最近、Ninja650に乗り換えたSREチームの菅原です。今までマルチばかり乗ってきたんですが、ツインもなかなか面白いですね。シフトペダルをガチャコンいわせながら方々に出かける毎日です。この記事では、サービスが配信しようとして何らかの理由で差し戻されたメール—バウンスメールの管理をどのように行っているかという話しを書きます。バウンスメールサービスがユーザに向けてメールを配信しようとすると、多かれ少なかれバウンスメールは発生します。メールアドレスが間違っている・携帯電話の設定で受信を拒否している・メールボックスが一杯にになっている・IPアドレスがブラックリストに載ってしまったためサーバにメールの受信を拒否されている...etc。完全になくすことは難しいですが、バウンスメールを放置するとメールの到達率を下げたり、送信先から一時的にメールの受信を拒否されたりすることがあるため、差し戻されてしまった宛先はリストに登録して、再送を抑止することが望ましいです。SendGridのようなサービスを利用している場合、差し戻されたメールは自動的にリストに登録されて再度メールを送っても配送されないようになっていたりするのですが、クックパッドの場合は内部システムのPostfixサーバからメールを配信していたため、バウンスメールの管理をある程度、自前で作り込む必要がありました。既存のシステム以前はbounceHammerというOSSとMySQLのバウンスメール管理用のテーブルを使って、バウンスメールの管理が行われていました。アプリケーションはメール送信サーバのPostfixを経由して、メールを配信します差し戻されたメールは、バウンスメール管理サーバのPostfixが受け取りますPostfixが受け取ったメールをbounceHammerが解析して自身のデータベースに入れます定期実行されるスクリプトがbounceHammerのデータベースからアプリ用のデータベースにバウンスメール情報をマイグレーションしますアプリケーションはユーザテーブルとバウンスリストを結合して、メールが差し戻された宛先にはメールを送らないようにしますバウンスリストの情報は、管理用アプリケーションから削除することができます既存システムの問題点このバウンスメール管理システムには、いくつか問題点がありました。bounceHammerの導入が後付けであったため、バウンスメール情報がbounceHammerとアプリ用データベースで二重管理になっていた同様に後付けが原因で、管理アプリケーションからアプリ用データベースの情報は削除できるが、bounceHammerの情報を削除(ホワイトリスト登録)できないため、手作業で同期を取る必要があったユーザテーブルとバウンスリストをSQLで結合して配信対象をフィルタリングする方式であったため、スケーラビリティに問題があったバウンスリストがテーブルという単位で管理されているため、アプリケーションの各機能が個別に配信対象のフィルタリングを実装する必要があったSQLの結合という形でフィルタリングを行うと、メールが配信されなかったユーザがそもそも配信の対象にならなかったのか、バウンスリストに登録されていたため配信されなかったのか、区別を行うことが難しかったバウンスメールの情報がきちんと可視化されていなかったため、配信状況の把握に難があったbounceHammerがEOLになった問題点を抱えた状態での運用がつらく、またbounceHammerがEOLになったこと、さらにシステムのリニューアル作業が進行中だったこともあり、バウンスメール管理システムを新しく作り直すことにしました。そのコアの部分として利用することになったのがSisimaiです。SisimaiSisimaiはbounceHammerの後継として開発されているバウンスメール解析ライブラリです。bounceHammerが管理用Webアプリや集計用のスクリプトも含めた複合的なシステムであったのに対して、シンプルなPerl・Rubyのライブラリです。ライブラリの依存関係も少なく、またわかりやすいAPIで、しかも自分が慣れたRubyのライブラリであったため、とても簡単に新しいシステムに組み込むことができました。parseendSisitoSisimaiはすばらしいライブラリなのですが、bounceHammerにあったような管理用のWebアプリケーションはなくなってしまいました。エンジニア以外のスタッフが「問い合わせのあったメールアドレスをホワイトリストに登録する」等の作業が発生するため、管理用のWebアプリケーションは必須です。そこで以前の運用経験を踏まえ、バウンスメール情報保存用のデータベースとそれを管理するウェブアプリケーションを作成しました。それがSisitoです。以下はSisitoの管理画面のスクリーンショットです。バウンスメール管理システム以外からバウンスメールの情報を取得するため、sisito-apiというAPIサーバも作成しました。新バウンスメール管理システムSisimaiとSisitoを使った新しいバウンスメール管理システムの構成が以下のようになります。アプリケーションはメール配信サーバのPostfixを経由してメールを配信します。・特定の理由のみ、など)blacklistを更新しますSisitoを使って統計情報の閲覧やホワイトリストへの登録を行いますアプリケーションはsisito-apiを経由してバウンスメールの情報を取得しますメールの送信ステータス・Subject・blacklistによるリジェクト状況などのログはElasticsearchに送信してKibanaで閲覧できるようにしますまとめ新バウンスメール管理システムの導入により、アプリケーションの各機能で配信制御を行う必要がなくなり、Postfixでフィルタリングを行うことでスケーラビリティの問題も解決することができました。Sisitoによる可視化により問題が発生しても(たとえば、特定の理由のバウンスメールが増えているなど)状況をすぐに把握して迅速に対応することができるようになりました。ホワイトリストの登録処理がエンジニアを介さずにできるようになったため、業務フローのコストも下げることができました。差し戻されるメールのエラー内容はサービスによって様々なパターンがあり、人間が解析することはかなりの労力を伴います。SisimaiのようなライブラリがOSSとして公開されていることは大変ありがたいことです。積極的に活用して、フィードバックなどで開発に貢献していきたいと考えています。