Google Cloud Functions + Node.js(TypeScript)でメールステータスWebhookを受け取る

Customers Mail CloudのWebhookは2種類あります。

  1. メール受信時
  2. メール送信時

メール送信時は、送信したメールに対してステータスが変わったタイミングで通知が送られるものです。

本記事では実際にどういった内容が送られてくるのかを紹介します。

受け取るWebhookの設定

管理画面にて、受け取るWebhookを設定できます。設定は以下が用意されています。

  • Bounces
    • bounced(エラーメールを受け取る)
  • Deliveries
    • queued(キューに入ったタイミング)
    • succeeded(送信完了)
    • failed(送信失敗)
    • deferred(送信延期)

送信されてくるデータについて

メール送信した直後

メール送信を行うと、そのデータがキューに入ります。そして、以下のようなWebhookが送られてきます(データは一部マスキングしています)。

{
    "event_type": "deliveries",
    "server_composition": "pro",
    "event": {
        "deliveries": [
            {
                "reason": "",
                "sourceIp": "100.100.100.1",
                "returnPath": "info@return.pro.smtps.jp",
                "created": "2023-01-25 14:03:06",
                "subject": "メールマガジンのテスト",
                "apiData": "",
                "messageId": "<031a32d4-06cd-b1ae-9526-011c0b9f1296@example.com>",
                "from": "info@example.com",
                "to": "user@example.jp",
                "senderIp": "",
                "status": "queued"
            }
        ]
    }
}

メール送信完了時

Customers Mail Cloudからメール送信処理が行われると、ステータスが succeeded になったWebhookが送られてきます。

{
    "event_type": "deliveries",
    "server_composition": "pro",
    "event": {
        "deliveries": [
            {
                "reason": "",
                "sourceIp": "",
                "returnPath": "info@return.pro.smtps.jp",
                "created": "2023-01-25 14:03:09",
                "subject": "メールマガジンのテスト",
                "apiData": "",
                "messageId": "<031a32d4-06cd-b1ae-9526-011c0b9f1296@example.com>",
                "from": "info@example.com",
                "to": "user@example.jp",
                "senderIp": "100.100.100.3",
                "status": "succeeded"
            }
        ]
    }
}

メール送信失敗時(メールアドレス形式に問題がある場合)

メールアドレスの形式に問題があるなど、送信処理が失敗した場合には以下のようなWebhookが送られてきます。

{
    "event_type": "bounces",
    "server_composition": "pro",
    "event": {
        "bounces": [
            {
                "reason": "host unknown",
                "returnPath": "info@return.pro.smtps.jp",
                "created": "2023-01-25 14:05:15",
                "subject": "メールマガジンのテスト",
                "apiData": "",
                "messageId": "<8f902ee7-ae65-8711-48a8-2f708cb14205@example.com>",
                "from": "info@example.com",
                "to": "user@example",
                "status": "1"
            }
        ]
    }
}

メール送信失敗時(送信先サーバーからエラーが返ってくる場合)

ユーザーが存在しない、メールボックスがいっぱいなど送信先サーバーからエラーが返ってきた場合には、以下のようなJSONが返ってきます。

{
    "event_type": "deliveries",
    "server_composition": "pro",
    "event": {
        "deliveries": [
            {
                "reason": "550 5.1.1 The email account that you tried to reach does not exist. Please try 5.1.1 double-checking the recipient's email address for typos or 5.1.1 unnecessary spaces. Learn more at 5.1.1  <https://support.google.com/mail/?p=NoSuchUser> b197-20020a621bce000000b0058b80756b07si311029pfb.3 - gsmtp (in reply to RCPT TO)",
                "sourceIp": "",
                "returnPath": "info@return.pro.smtps.jp",
                "created": "2023-01-25 14:06:06",
                "subject": "メールマガジンのテスト",
                "apiData": "",
                "messageId": "<9e7e564c-ac83-8cd8-2cb4-b9ff2a9f168d@example.com>",
                "from": "info@example.com",
                "to": "no-user@example.jp",
                "senderIp": "100.100.100.3",
                "status": "failed"
            }
        ]
    }
}

エラーとしてのWebhookも送られてきます。上記のものと event_type が異なるので注意してください。

{
    "event_type": "bounces",
    "server_composition": "pro",
    "event": {
        "bounces": [
            {
                "reason": "550 5.1.1 The email account that you tried to reach does not exist. Please try 5.1.1 double-checking the recipient's email address for typos or 5.1.1 unnecessary spaces. Learn more at 5.1.1  <https://support.google.com/mail/?p=NoSuchUser> b197-20020a621bce000000b0058b80756b07si311029pfb.3 - gsmtp (in reply to RCPT TO)",
                "returnPath": "info@return.pro.smtps.jp",
                "created": "2023-01-25 14:06:07",
                "subject": "メールマガジンのテスト",
                "apiData": "",
                "messageId": "<9e7e564c-ac83-8cd8-2cb4-b9ff2a9f168d@example.com>",
                "from": "info@example.com",
                "to": "no-user@example.jp",
                "status": "2"
            }
        ]
    }
}

Google Cloud Functionsの準備

今回はローカルで開発する流れを紹介します。まず、適当なフォルダを作成します。今回はcmcとします。

mkdir cmc
cd cmc

そしてTypeScriptプロジェクト用に準備します。

npm i typescript -D
npx tsc --init
mkdir src

tsconfig.json を編集します。

{
    // 省略
    "rootDir": "./src",                                  /* Specify the root folder within your source files. */
    "outDir": "./dist",                                   /* Specify an output folder for all emitted files. */
    // 省略
}

そしてライブラリをインストールします。

npm i @google-cloud/functions-framework

次に src/index.ts というファイルを作成します。内容は以下の通りです。

import * as functions from '@google-cloud/functions-framework';

functions.http('helloGET', (req, res) => {
    // ここに処理を記述します
  res.send('ok');
});

そして、以下のようにコマンドを実行します。

npx tsc && npx @google-cloud/functions-framework --target=helloGET

これで、 http://localhost:8080 にてサーバーが立ち上がります。

TypeScriptのコード

処理は src/index.tsfunctions.http 内に記述します。

import * as functions from '@google-cloud/functions-framework';

functions.http('helloGET', (req, res) => {
    // ここに処理を記述します
  res.send('ok');
});

送られてくるデータは req.body で受け取れます。この内容はJSONオブジェクトなので、キーを使ってデータを取得できます。

const { body } = req;

後は、このオブジェクトから必要な情報を取り出して処理を行います。

const { body } = req;
console.log(body.event_type); // deliveries
console.log(body.event.deliveries[0].subject); // メールマガジンのテスト

まとめ

Webhookを使うことで、メール送信ステータスの変化に応じて通知を受け取れるようになります。メールと連携したシステムを開発する際に役立つでしょう。

このWebhookはSMTP経由の場合、利用できます。ぜひご利用ください。