ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

SendGrid の Event Webhook から POST されたデータを Azure DocumentDB に登録する

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 します。

EventWebhook

HTTP Post URL には、デプロイした Web API の URL(http://xxx.azurewebsites.net/api/sendgrid/)を設定します。送信に失敗したメールアドレスの情報を取得したいので、3つのアクションを設定しました。

  • Dropped・・・無効なメールアドレス、バウンスされたメールアドレスなど
  • Deferred・・・受信側メールサーバーから一時的に拒否された
  • Bounced・・・受信側メールサーバーが受信できない

結果確認

存在しないメールアドレス(test@example.com)を宛先としてメール送信すると、DocumentDB に JSON 形式のデータが登録されます。Azure Preview ポータルのクエリ エクスプローラで、DocumentDB に登録されたデータを確認できます。

doc

まとめ

クラウドで展開されるアプリケーションは、パスワードリマインダや登録完了のお知らせなどのトランザクションメールの機能が必要となるケースが多く、メール送信の信頼性は重要なポイントになります。Event Webhook なら、送信に失敗したメールアドレスを通知できるので、対応を自動化することも可能です。

今回は、Azure DocumentDB に登録しましたが、同じような NoSQL ストアである Azure Search に登録してもいいと思います。Azure DocumentDB は、まだ日本にデプロイされていないので、来月 GA する際にはデプロイされてほしいです。