SendGrid の Event Webhook を利用すると、メールを送信する際に発生したイベントを指定した URL に POST することができます。POST されるデータは、delivered や bounce などのイベントタイプによってスキーマが異なる JSON 配列なので、スキーマフリーの NoSQL ストアである Azure DocumentDB に登録してみました。
Event Webhook から POST される Web API の作成
まず、Azure Preview ポータルから Azure DocumentDB を作成しておきます。10分ほどかかるので、Visual Studio から ASP.NET Web API のプロジェクトテンプレートを作成します。NuGet から、DocumentDB の Client Library をインストールします。
- Install-Package Microsoft.Azure.Documents.Client -Pre
SendGridController を追加し、Post メソッドを実装します。
#SendGridController.cs [RoutePrefix("api/sendgrid")] public class SendGridController : ApiController { private static string EndpointUrl = "https://xxx.documents.azure.com:443/"; private static string AuthorizationKey = "xxx"; private static string DatabaseID = "SendGridDb"; private static string CollectionID = "SendGridCollection"; [Route] public async Task Post() { // Event Webhook から POST された JSON を 取得 var json = ""; using (var reader = new StreamReader(await Request.Content.ReadAsStreamAsync())) { json = reader.ReadToEnd(); } // Azure DocumentDB に登録 using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { var database = client.CreateDatabaseQuery() .Where(x => x.Id == DatabaseID).ToArray().FirstOrDefault(); if (database == null) { database = await client.CreateDatabaseAsync(new Database { Id = DatabaseID }); } var documentCollection = client.CreateDocumentCollectionQuery(database.CollectionsLink) .Where(x => x.Id == CollectionID).ToArray().FirstOrDefault(); if (documentCollection == null) { documentCollection = await client.CreateDocumentCollectionAsync(database.SelfLink, new DocumentCollection { Id = CollectionID }); } foreach (var doc in JsonConvert.DeserializeObject<List<dynamic>>(json)) { await client.CreateDocumentAsync(documentCollection.DocumentsLink, doc); } } } }
EndpointUrl と AuthorizationKey には、Azure Preview ポータルから取得できる値を設定してください。スキーマを定義することなく、dynamic 型をそのまま DocumentDB に登録できるところがいい感じです。実装できたら、Azure Websites にデプロイします。
Event Webhook から POST する URL を設定する
SendGrid のダッシュボードで、Apps メニューから Event Notification を Enabled します。
HTTP Post URL には、デプロイした Web API の URL(http://xxx.azurewebsites.net/api/sendgrid/)を設定します。送信に失敗したメールアドレスの情報を取得したいので、3つのアクションを設定しました。
- Dropped・・・無効なメールアドレス、バウンスされたメールアドレスなど
- Deferred・・・受信側メールサーバーから一時的に拒否された
- Bounced・・・受信側メールサーバーが受信できない
結果確認
存在しないメールアドレス(test@example.com)を宛先としてメール送信すると、DocumentDB に JSON 形式のデータが登録されます。Azure Preview ポータルのクエリ エクスプローラで、DocumentDB に登録されたデータを確認できます。
まとめ
クラウドで展開されるアプリケーションは、パスワードリマインダや登録完了のお知らせなどのトランザクションメールの機能が必要となるケースが多く、メール送信の信頼性は重要なポイントになります。Event Webhook なら、送信に失敗したメールアドレスを通知できるので、対応を自動化することも可能です。
今回は、Azure DocumentDB に登録しましたが、同じような NoSQL ストアである Azure Search に登録してもいいと思います。Azure DocumentDB は、まだ日本にデプロイされていないので、来月 GA する際にはデプロイされてほしいです。