Webhook APIを使って添付ファイル付きメールを処理する(Google Cloud Functions + TypeScript/Node.js)

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

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

メール受信時のWebhookはその名の通り、メールを受け取った際に任意のURLをコールするものです。この記事では添付ファイル付きメールを受け取った際のWebhook処理について解説します。

フォーマットはマルチパートフォームデータ

Webhookの形式として、JSONとマルチパートフォームデータ(multipart/form-data)が選択できます。この二つの違いは、添付ファイルがあるかどうかです。JSONの場合、添付ファイルは送られてきません。今回のようにメールに添付ファイルがついてくる場合は、後者を選択してください。

Webhook設定ダイアログ

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

メールを受信すると、以下のようなWebhookが送られてきます(データは一部マスキングしています)。JSONにしていますが、実際にはmultipart/form-dataです。

{
    "filter": "info@smtps.jp",
    "headers": [
      {name: 'Return-Path', value: '<user@example.com>'},
        :
      {name: 'Date', value: 'Thu, 27 Apr 2023 15:56:26 +0900'}
    ],
    "subject": "Webhookのテスト",
    "envelope-to": "user@smtps.jp",
    "server_composition": "sandbox",
    "html": "<div dir=\\\\\\\\\\\\\\\\"ltr\\\\\\\\\\\\\\\\">Webhookのテスト用メールです。<div>...</div></div>",
    "text": "Webhookのテスト用メールです。\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\n--\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\n...",
    "envelope-from": "info@smtps.jp",
    "attachments": 1,
    "attachment1": "...."
}

Google Cloud Functionsの準備

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

mkdir cmc
cd cmc

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

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

tsconfig.json を編集します。

{
    // 省略
    "rootDir": "./src",
    "outDir": "./dist",
    // 省略
}

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

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');
});

マルチパートフォームデータを取得する

multipart/form-data で送られてくるデータは Busboy で処理します。まずライブラリをインストールします。

npm i busboy
npm i @types/busboy -D

そして、 src/index.ts にてインポートします。

import Busboy from 'busboy';

使い方は、まず初期化します。

const busboy = Busboy({headers: req.headers});

そして、パラメーターは field イベント、添付ファイルは file イベントで取得します。ファイルデータは FileStream として取得できます。ファイル名はエンコードされているので、適切にデコードしてください。

busboy.on('field', (fieldname, val) => {
    console.log(fieldname, typeof val, val);
    // server_composition string sandbox
    // headers string [{"name":"Return-Path","value":"...
    // attachments string 1
});
busboy.on('file', (fieldname, file, {filename}) => {
    file.resume();
    console.log(fieldname, filename, file);
    // attachment1 =?UTF-8?B?44CQMjAyM+W5tDbmnIjjgJHnmbrms6jmm7jjg7voq4vmm7gueGxzeA==?=  FileStream
});
busboy.end(req.rawBody); // 処理開始

Webhookの結果は管理画面で確認

Webhookでデータが送信されたログは管理画面で確認できます。送信時のAPIキー設定など、HTTPヘッダーを編集するといった機能も用意されていますので、運用に応じて細かなカスタマイズが可能です。

Webhookログ

まとめ

メールと連携したシステムはよくあります。通常、メールサーバを立てて、その中で処理することが多いのですが、メールサーバが落ちてしまうとシステムが稼働しなくなったり、メール文面の解析が煩雑でした。Customers Mail Cloudを使えばそうした手間なくJSONで処理できて便利です。

添付ファイルまで処理対象にしたい時には、この方法を利用してください。

受信サーバ | Customers Mail Cloud