ドキュメント本文へスキップ
C#

Webhook の検証

配信の内容を信頼する前に、その署名を確認します。

配信を検証する

Program.cs
using OpenEmail; var builder = WebApplication.CreateBuilder(args);var app = builder.Build();var secret = builder.Configuration["OPENEMAIL_WEBHOOK_SECRET"] ?? string.Empty; app.MapPost("/webhooks/openemail", async (HttpRequest request) =>{    using var reader = new StreamReader(request.Body);    var payload = await reader.ReadToEndAsync();     try    {        var delivery = OpenEmailClient.VerifyWebhookSignature(payload, request.Headers["X-OpenEmail-Signature"], secret);         app.Logger.LogInformation("{Type} {Id}", (string?)delivery["type"], (string?)delivery["id"]);         return Results.NoContent();    }    catch (OpenEmailWebhookException)    {        return Results.BadRequest();    }}); app.Run();

OpenEmailClient.VerifyWebhookSignature() は、タイムスタンプとボディに対するヘッダーの HMAC を定数時間で確認し、イベントを JsonObject として返します。2 番目の引数は X-OpenEmail-Signature ヘッダーの値で、リクエストヘッダーそのものを受け取るオーバーロードもあります。シークレットは client.Webhooks.CreateAsync() が返したものです。

届いたままの生のボディを渡してください。解析して再エンコードしたボディは、もう署名と一致しません。

古い配信

tolerance.cs
var payload = """{"id":"evt_1","type":"email.received"}"""; try{    OpenEmailClient.VerifyWebhookSignature(payload, "t=1767225600,v1=5f2d", "whsec_example", toleranceSeconds: 60);}catch (OpenEmailWebhookException error){    Console.WriteLine($"refused: {error.Message}");}

5 分以上前の配信は拒否されるため、傍受されたリクエストをあとで再送することはできません。toleranceSeconds: でこの 5 分を変更でき、ゼロにするとどれだけ古い配信でも受け付けます。

  • ヘッダーがない場合や形式が正しくない場合、署名が一致しない場合、配信が古すぎる場合は、いずれも OpenEmailWebhookException がスローされます。
  • シークレットをローテーションしたあとは、配信に複数の署名が付くことがあり、どれか 1 つが一致すれば通ります。
  • すばやく 2xx のステータスで応答してください。それ以外の応答を受けた配信は、あとで再試行されます。