読者です 読者をやめる 読者になる 読者になる

.NET で SendGrid API を使う (3)

クロスワープの大鷲です。

前回までで Marketing Campaign の登録に必要な準備が整いましたので、今回は実際に登録します。

キャンペーンの登録と注意点

キャンペーンの登録に最低限必要なパラメーターは

  • title
  • subject
  • sender_id
  • list_ids
  • custom_unsubscribe_url
  • html_content
  • plain_content

この辺です。
title と subject は、まぁいいでしょう。
sender_id は先に説明した送信者の ID、list_ids は受信者リストの ID(複数指定可能)です。

メール本文には必ず配信解除用のリンクを含めなければなりません。
SendGrid が提供する配信解除機能を使うこともできますが、配信解除用のページを自前で提供する場合は、その URL を custom_unsubscribe_url にセットします。

html_content と plain_content は、それぞれ、HTML とプレーン テキストによるメール本文です。
plain_content は省略可能ですが、html_content は必須です。plain_content は HTML メールの表示に対応していないメーラーで使われるようです。
html_content を指定しない場合、キャンペーンの登録は成功しますが、送信時にエラーになって送信されないため注意が必要です。

また、本文には "[Unsubscribe]" という文字列を埋め込む必要があります。
これは送信時に、配信解除用の URL に置き換えられます。
これも、無くても登録はできますが、後述するスケジューリングの時にエラーになります。

キャンペーンのスケジューリング

キャンペーンを登録したら Schedule API を使って送信日時を設定します。
パラメーターの send_at は Unix 時間です。
変換のためにこんなメソッドを作っておくと便利です。

public static class DateTimeUtility
{
  public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
  
  public static DateTime FromUnixTime(
    long unixTime)
  {
    return UnixEpoch.AddSeconds(unixTime).ToLocalTime();
  }
  
  public static long ToUnixTime(
    DateTime datetime)
  {
    return (long)(datetime.ToUniversalTime() - UnixEpoch).TotalSeconds;
  }
}

結果の取得

登録に成功するとキャンペーン ID が返されます。
しかし、この ID を指定して、送信結果(実際に何通届いたかとか、何通開封されたかとか……)を取得するための API は用意されていません。

こうした結果を取得するためには、Event Webhook という機能を利用する必要があります。
Webhook で通知されてくる結果を溜めておいて、後で集計する処理が必要になるでしょう。

Webhook を利用し通知を受けるためには、外部からアクセス可能な HTTP エンドポイントが必要になります。
しかし、開発中にいちいち Web サーバーにデプロイして動作確認するのは面倒なものです。
そういう場合は、SendGrid のドキュメントでも紹介されている ngrok が便利です。
ローカル マシンで立ち上げると、ngrok が公開しているパブリックな HTTP エンドポイントとの間にトンネルを構築し、パブリックな URL に届いたリクエストをローカル マシンに中継してくれます。

詳しい使い方はしばやんさんのブログをご覧ください。
blog.shibayan.jp

無料プランでは起動するごとに URL が変わってしまうので、いちいち SendGrid の管理画面から Webhook URL を変更する面倒くささはありますが、それを補って余りある有用なツールです。

妙な REST 風 API への対応

SendGrid の Web API は REST 風と言ってよいと思いますが、いくつか妙なものが存在します。

例えば、受信者リストをまとめて削除する API
通常、HTTP DELETE というのは、URL で示したリソースを削除するのですが、この API はボディで示した ID のリストをまとめて削除します。

あるいは、キャンペーン メールを送信予約するのではなく、即座に送信する API
POST メソッドを使うのですがボディがありません。

こういった、ちょっと REST らしからぬ API は、対応するメソッドが HttpClient にありません。

それから、登録済みのデータを部分的に修正するために HTTP PATCH メソッドを使いますが、これも HttpClient には標準で備わっていません。

そこで、機能を拡張してやる必要があります。
今回はこんな感じのメソッドを作ってみました。*1
参考にしてみてください。

public static class HttpClientExtensions
{
    // ボディのない POST
    public static Task<HttpResponseMessage> PostAsync(
        this HttpClient client,
        Uri uri)
    {
        var request = new HttpRequestMessage(HttpMethod.Post, uri);
        request.Content = EmptyContent.Default;

        return client.SendAsync(request);
    }

    // ボディのある DELETE
    public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(
        this HttpClient client,
        Uri uri,
        T value)
    {
        var request = new HttpRequestMessage(HttpMethod.Delete, uri);
        request.Content = new ObjectContent<T>(value, new JsonMediaTypeFormatter());

        return client.SendAsync(request);
    }

    // PATCH
    public static Task<HttpResponseMessage> PatchAsJsonAsync<T>(
        this HttpClient client,
        Uri uri,
        T value)
    {
        var request = new HttpRequestMessage(new HttpMethod("PATCH"), uri);
        request.Content = new ObjectContent<T>(value, new JsonMediaTypeFormatter());

        return client.SendAsync(request);
    }
}

まとめ

Marketing Campaigns API を利用する方法や注意点をお届けしました。

次回は、先日開催された SendGrid Night #4 の模様などを紹介したいと思います。

*1:EmptyContent も自作クラスですが実装は割愛します。