Twilio SendGridライブラリで送信リクエストとレスポンスを取得する方法 ~C#編~

Twilio SendGridライブラリで送信リクエストとレスポンスを取得する方法 ~C#編~

メール送信リクエストを実行したのに、ActivityEvent Webhookにイベントが記録されていない!という経験はありませんか?イベントが発生しない主な原因として、Twilio SendGridに送信リクエストが届いていない可能性が考えられます。問題が発生した際に原因をしっかり特定できるよう、実際に送ったJSON形式の送信リクエストとそのHTTPレスポンスをログに出力するよう心がけましょう。

SMTPやWeb APIで送信する場合は、TelnetやcURLなどのツールによって簡単に送信リクエストとレスポンスが取得できるので、チュートリアルをお試しください。今回のブログでは、C#向けのSendGridライブラリ(以降、sendgrid-csharpと表記)における取得方法を紹介します。

今回は、Microsoftが提供しているDockerイメージのdotnet/sdkを使い、.NET 9(9.0.5)の環境で確認しました。ライブラリはsendgrid-csharpの他、.envファイルから環境変数を読み込むためにDotNetEnvを使っています。

sendgrid-csharpを使った送信処理のサンプルコード

sendgrid-csharpにおける送信処理のサンプルコードは次のとおりです。

using SendGrid;
using SendGrid.Helpers.Mail;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode;
using System.Text.Encodings.Web;

//環境変数の読み込み
DotNetEnv.Env.Load();

var 送信 = new SendGridClient(DotNetEnv.Env.GetString("SG_API_KEY"));

//送信リクエスト
var メール = new SendGridMessage()
        {
            From = new EmailAddress("kozohanako@example.com", "構造花子"),
            Subject = "C#のライブラリを使ったメール送信",
            PlainTextContent =
                """
                構造さん
                お元気ですか。
                """,
            HtmlContent =
                """
                <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
                <html xmlns="http://www.w3.org/1999/xhtml">
                <head>
                    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
                </head>
                <body>
                    <p>構造さん</p>
                    <p>お元気ですか。</p>
                </body>
                """
        };

//宛先
メール.AddTo(new EmailAddress("kozotaro@example.com", "構造太郎"));

//送信リクエストの出力
var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    WriteIndented = true
};
Console.WriteLine(JsonSerializer.Serialize(メール, options));

//メール送信
var レスポンスデータ = await 送信.SendEmailAsync(メール).ConfigureAwait(false);

//レスポンスの出力
Console.WriteLine(レスポンスデータ.StatusCode);
Console.WriteLine(レスポンスデータ.Headers.ToString());
Console.WriteLine(レスポンスデータ.Body.ReadAsStringAsync().Result);

dotnetコマンドでプログラムを実行すると、sendgrid-csharpがSendGridのAPIを使ってメールを送信します。

dotnet run

それでは、送信リクエストとレスポンスを取得する部分を見てみましょう。

送信リクエストの取得方法

送信リクエストはSendGridMessageオブジェクトをJSONにシリアライズすると取得できます。

//送信リクエストの出力
var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    WriteIndented = true
};
Console.WriteLine(JsonSerializer.Serialize(メール, options));

指定したオプションにはそれぞれ次の意味があります。

  • Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    エスケープ処理を最小限にして、文字化けなどを防ぎます(参考
  • DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    シリアライズの際、値がnullの属性は出力対象から除外します
  • WriteIndented = true
    インデントを整えます

出力結果は次のとおりです。

{
  "From": {
    "Name": "構造花子",
    "Email": "kozohanako@example.com"
  },
  "Subject": "C#のライブラリを使ったメール送信",
  "Personalizations": [
    {
      "Tos": [
        {
          "Name": "構造太郎",
          "Email": "kozotaro@example.com"
        }
      ]
    }
  ],
  "PlainTextContent": "構造さん\nお元気ですか。",
  "HtmlContent": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1\">\n</head>\n<body>\n    <p>構造さん</p>\n    <p>お元気ですか。</p>\n</body>"
}

続いて、レスポンスの取得方法を紹介します。

レスポンスの取得方法

レスポンスはSendEmailAsyncメソッドの戻り値から取得します。

//メール送信
var レスポンスデータ = await 送信.SendEmailAsync(メール).ConfigureAwait(false);

//レスポンスの出力
Console.WriteLine(レスポンスデータ.StatusCode);
Console.WriteLine(レスポンスデータ.Headers.ToString());
Console.WriteLine(レスポンスデータ.Body.ReadAsStringAsync().Result);

発生した問題の原因を特定する際、特に大事なのはステータスコードとボディの情報です。正常応答(ステータスコードがAccepted)であれば、SendGridに送信リクエストが届いています。レスポンスがエラーの場合(ステータスコードがAccepted以外)は、SendGridに送信リクエストが届いていない、もしくは受け付けられていないので、bodyの「errors」で示されたメッセージをもとに原因を確認しましょう。

正常応答の場合

Accepted

Server: nginx
Date: Thu, 29 May 2025 01:48:47 GMT
Connection: keep-alive
X-Message-Id: z3hDxrXgSgKzwsTiuegjCg
Access-Control-Allow-Origin: https://sendgrid.api-docs.io
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-acl
Access-Control-Max-Age: 600
X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: frame-ancestors 'none'
Cache-Control: no-cache
X-Content-Type-Options: no-sniff
Referrer-Policy: strict-origin-when-cross-origin

エラ-の場合(正しくないメールアドレス形式を指定した場合)

BadRequest

Server: nginx
Date: Thu, 29 May 2025 01:54:48 GMT
Connection: keep-alive
Access-Control-Allow-Origin: https://sendgrid.api-docs.io
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-acl
Access-Control-Max-Age: 600
X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: frame-ancestors 'none'
Cache-Control: no-cache
X-Content-Type-Options: no-sniff
Referrer-Policy: strict-origin-when-cross-origin

{"errors":[{"message":"Does not contain a valid address.","field":"personalizations.0.to.0.email","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.personalizations.to"}]}

エラ-の場合(無効な認証情報が指定された場合)

Unauthorized

Server: nginx
Date: Thu, 29 May 2025 22:36:01 GMT
Connection: keep-alive
Access-Control-Allow-Origin: https://sendgrid.api-docs.io
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-acl
Access-Control-Max-Age: 600
X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: frame-ancestors 'none'
Cache-Control: no-cache
X-Content-Type-Options: no-sniff
Referrer-Policy: strict-origin-when-cross-origin

{"errors":[{"message":"The provided authorization grant is invalid, expired, or revoked","field":null,"help":null}]}

レスポンスにエラーが返る場合は、送信リクエストに誤りがないかどうか確認しましょう。また、リクエストは正常に受け付けられたがメールへの差し込みがうまくいかない、指定したテンプレートが反映されないなど、お困りの場合は、弊社サポートチームがフォローいたします。送信リクエストとレスポンス、受信メールを添えてお問い合わせください。

コードの再確認をしましょう

SendGridでは送信後の状況をActivityやEvent Webhookで確認できるため、その手前の送信リクエストやレスポンスのログ出力を忘れがちです。今回のブログをきっかけに、しっかりログ出力できているかご自身のコードをもう一度見直してみてください。

アーカイブ

  • クレジットカード
    登録不要

  • 無料利用の
    期限なし

  • 独自ドメイン
    利用OK

クラウドサービスのため
インストールは一切不要。
SendGridの充実した機能をまずは
試してみませんか?

無料ではじめる