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

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

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

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

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

ライブラリはPHPのパッケージ管理ツールであるComposerを利用して取得します。
sendgrid-phpを使った送信処理のサンプルコードは次のとおりです。

<?php

use Dom\HTMLElement;
require 'vendor/autoload.php';

$email = new \SendGrid\Mail\Mail();

// 差出人
$email->setFrom("kozotaro@example.com", "構造太郎");
// 宛先
$email->addTo("kozohanako@example.com", "構造花子");
// 件名
$email->setSubject("PHPのライブラリを使ったメール送信");
// 本文(テキストパート)
$email->addContent("text/plain", "構造さん\r\nお元気ですか。");
// 本文(HTMLパート)
$email->addContent("text/html", <<<HTML
<!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>
HTML
);

$apiKey = getenv('SENDGRID_API_KEY');
$sendgird = new \SendGrid($apiKey);

try {
    echo "--送信リクエストを標準出力する--<br/>\r\n";
    $json = json_encode($email->jsonSerialize(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    echo "<pre>{$json}</pre>";


    // メールの送信
    $response = $sendgird->send($email);
   
    echo "--レスポンスを標準出力する--<br/>\r\n";
    echo $response->statusCode() . "<br/>\r\n";
    echo "---------------------------<br/>\r\n";
    echo implode("<br/>\r\n", $response->headers());
    echo "---------------------------<br/>\r\n";
    echo $response->body() . "<br/>\r\n";

} catch (Exception $e) {
    echo $e->getMessage();
}

ダッシュボードで作成したAPIキーOSの環境変数に設定し読み込んでいます。

SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxxxxxxx

送信リクエストとレスポンスを取得する部分を詳しくみていきましょう。

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

送信リクエストは次の方法で取得できます。

$email = new \SendGrid\Mail\Mail();
// ※各種リクエスト内容の設定については省略

// 送信リクエストの取得
$json = json_encode($email->jsonSerialize(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
echo "<pre>{$json}</pre>";

json_encodeメソッドでJSONを整形して出力すると次のようになります。

--送信リクエストを標準出力する--<br/>
<pre>{
    "personalizations": [
        {
            "to": [
                {
                    "name": "構造花子",
                    "email": "kozohanako@example.com"
                }
            ]
        }
    ],
    "from": {
        "name": "構造太郎",
        "email": "kozotaro@example.com"
    },
    "subject": "PHPのライブラリを使ったメール送信",
    "content": [
        {
            "type": "text\/plain",
            "value": "構造さん\r\nお元気ですか。"
        },
        {
            "type": "text\/html",
            "value": "<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Strict\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-strict.dtd\">\r\n    <html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\r\n    <head>\r\n        <meta http-equiv=\"Content-Type\" content=\"text\/html; charset=utf-8\">\r\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1\">\r\n    <\/head>\r\n    <body>\r\n        <p>構造さん<\/p>\r\n        <p>お元気ですか。<\/p>\r\n    <\/body>"
        }
    ]
}</pre>

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

レスポンスの取得方法

送信リクエストに対するレスポンスは次の方法で取得します。

try {
    $response = $sendgird->send($email);
   
    echo "--レスポンスを標準出力する--<br/>\r\n";
    echo $response->statusCode() . "<br/>\r\n";
    echo "---------------------------<br/>\r\n";
    echo implode("<br/>\r\n", $response->headers());
    echo "---------------------------<br/>\r\n";
    echo $response->body() . "<br/>\r\n";


} catch (Exception $e) {
    echo $e->getMessage();
}

原因を特定する際、特に大事なのはステータスコードとボディの情報です。正常応答(ステータスコードが2xx系)であれば、SendGridに送信リクエストが届いています。レスポンスがエラーの場合(ステータスコードが2xx系以外)は、SendGridに送信リクエストが届いていない、もしくは受け付けられていないので、try-catchで捕捉した例外もきっちり処理しましょう。

正常応答の場合

202
---------------------------
HTTP/1.1 202 Accepted
Server: nginx
Date: Wed, 28 May 2025 04:43:38 GMT
Content-Length: 0
Connection: keep-alive
X-Message-Id: 4dfx1a-WTyiqW3GbYPGepg
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

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

Fatal error: Uncaught SendGrid\Mail\TypeException: "$emailAddress" must be a valid email address. Got: kozohanakoexample.com in ~\htdocs\sendgrid\vendor\sendgrid\sendgrid\lib\helper\Assert.php:61 Stack trace: #0 ~\htdocs\sendgrid\vendor\sendgrid\sendgrid\lib\mail\EmailAddress.php(69): SendGrid\Helper\Assert::email('kozohanakoexamp...', 'emailAddress') #1 ~\htdocs\sendgrid\vendor\sendgrid\sendgrid\lib\mail\EmailAddress.php(47): SendGrid\Mail\EmailAddress->setEmailAddress('kozohanakoexamp...') #2 ~\htdocs\sendgrid\vendor\sendgrid\sendgrid\lib\mail\Mail.php(190): SendGrid\Mail\EmailAddress->__construct('kozohanakoexamp...', '\xE6\xA7\x8B\xE9\x80\xA0\xE8\x8A\xB1\xE5\xAD\x90', NULL) #3 ~\htdocs\sendgrid\vendor\sendgrid\sendgrid\lib\mail\Mail.php(383): SendGrid\Mail\Mail->addRecipientEmail('To', 'kozohanakoexamp...', '\xE6\xA7\x8B\xE9\x80\xA0\xE8\x8A\xB1\xE5\xAD\x90', NULL, NULL, NULL) #4 ~\htdocs\sendgrid\index.php(17): SendGrid\Mail\Mail->addTo('kozohanakoexamp...', '\xE6\xA7\x8B\xE9\x80\xA0\xE8\x8A\xB1\xE5\xAD\x90') #5 {main} thrown in ~\htdocs\sendgrid\vendor\sendgrid\sendgrid\lib\helper\Assert.php on line 61

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

401
---------------------------
HTTP/1.1 401 UnauthorizedServer: nginxDate: Wed, 28 May 2025 04:49:13 GMTContent-Type: application/jsonContent-Length: 116Connection: keep-aliveAccess-Control-Allow-Origin: https://sendgrid.api-docs.ioAccess-Control-Allow-Methods: POSTAccess-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-aclAccess-Control-Max-Age: 600X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.htmlStrict-Transport-Security: max-age=31536000; includeSubDomainsContent-Security-Policy: frame-ancestors 'none'Cache-Control: no-cacheX-Content-Type-Options: no-sniffReferrer-Policy: strict-origin-when-cross-origin
---------------------------
{"errors":[{"message":"The provided authorization grant is invalid, expired, or revoked","field":null,"help":null}]}

レスポンスで「Bad Request」などのエラーが返る場合は、送信リクエストに誤りがないかどうか確認しましょう。SendGridが用意するSandboxモードを利用することで、実際にメール送信を行うことなく、リクエストが正しいかどうかの検証ができます。

// メールの作成
$email = new \SendGrid\Mail\Mail();

…

// SandBoxModeで送信リクエストを検証する
$email->enableSandBoxMode();

// メールの送信
try {
    $response = $sendgird->send($email);
   
    echo "--レスポンスを標準出力する--<br/>\r\n";
    echo $response->statusCode() . "<br/>\r\n";
    echo "---------------------------<br/>\r\n";
    echo implode($response->headers()) . "<br/>\r\n";
    echo "---------------------------<br/>\r\n";
    echo $response->body() . "<br/>\r\n";

} catch (Exception $e) {
    echo $e->getMessage();
}

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

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

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

アーカイブ

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

  • 無料利用の
    期限なし

  • 独自ドメイン
    利用OK

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

無料ではじめる