Azure FunctionsをWebhookで呼び出す

Customers Mail Cloudではプログラム側からデータを取得したり、メールを送信するWeb APIの他に、Customers Mail Cloudでメールを受信した時にイベントを伝えてくれるWebhook APIが用意されています。

Webhook APIを使うことで、自前でメールサーバを立てずにメール受信のタイミングでシステムを起動させられるようになります。メールサーバを安定して動作させ続けるのはメンテナンスコストが大きいですが、Customers Mail Cloudを使うことで簡単にメールと連携したシステムが作れるようになるでしょう。

今回はAzure FunctionsをWebhook APIと組み合わせて使ってみます。

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

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

Webhook設定ダイアログ

内容を確認するためのコード

今回は送られてくる内容を確認するため、bodyを出力してみます。

import { AzureFunction, Context, HttpRequest } from "@azure/functions"

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    context.log(req.body);
    const name = (req.query.name || (req.body && req.body.name));
    const responseMessage = name
        ? "Hello, " + name + ". This HTTP triggered function executed successfully."
        : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };

};

export default httpTrigger;

この状態でメールを送ってみます。

ログを確認する

Azure Functionsのログを見ると、次のようなデータが送られているのが分かります(一部)。

{
    "filter": "admin@example.com",
    "headers": [
        {
            "name": "Return-Path",
            "value": "<user@example.jp>"
        },
        {
            "name": "DKIM-Signature",
            "value": "v=1;...g=="
        },
        {
            "name": "X-Proofpoint-GUID",
            "value": "zxVl1hwp5EFXkjZkF6kiNdUc7b267ULg"
        },
        {
            "name": "X-Persimmon",
            "value": "[%%...%]"
        },
        {
            "name": "Received",
            "value": "from...; Wed, 21 Dec 2022 13:40:06 +0000 (UTC)"
        },
        {
            "name": "X-Proofpoint-ORIG-GUID",
            "value": "zxVl1hwp5EFXkjZkF6kiNdUc7b267ULg"
        },
        {
            "name": "From",
            "value": "管理者 <user@example.jp>"
        },
        {
            "name": "Message-Id",
            "value": "<F31E1B5C-7070-4FB2-B293-07E880B19D0F@icloud.com>"
        },
        {
            "name": "Subject",
            "value": "テキストメールテスト"
        },
        {
            "name": "Date",
            "value": "Wed, 21 Dec 2022 22:39:54 +0900"
        },
        {
            "name": "X-Mailer",
            "value": "Apple Mail (2.3731.300.101.1.3)"
        },
        {
            "name": "Delivered-To",
            "value": "admin@example.com"
        },
        {
            "name": "X-Proofpoint-Virus-Version",
            "value": "vendor=...signatures=0"
        },
        {
            "name": "X-Proofpoint-Spam-Details",
            "value": "rule=notspam...10113"
        },
        {
            "name": "To",
            "value": "admin@example.com"
        },
        {
            "name": "Mime-Version",
            "value": "1.0 (Mac OS X Mail 16.0 \\\\(3731.300.101.1.3\\\\))"
        },
        {
            "name": "Content-Type",
            "value": "multipart/alternative;\\tboundary=\\"Apple-Mail=_32625FD4-A33D-4973-A95B-27E0AD492824\\""
        }
    ],
    "subject": "テキストメールテスト",
    "envelope-to": "admin@example.com",
    "server_composition": "pro",
    "html": "<html><head><meta http-equiv=\\"content-type\\" content=\\"text/html; charset=utf-8\\"></head><body style=\\"overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;\\"><meta http-equiv=\\"content-type\\" content=\\"text/html; charset=utf-8\\"><div style=\\"overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;\\"><meta http-equiv=\\"content-type\\" content=\\"text/html; charset=utf-8\\"><div style=\\"overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;\\"><meta http-equiv=\\"content-type\\" content=\\"text/html; charset=utf-8\\"><div style=\\"overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;\\"><meta http-equiv=\\"content-type\\" content=\\"text/html; charset=utf-8\\"><div style=\\"overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;\\"><div>テキストメールです。</div><div><br></div><div><b>HTML文</b>です。</div></div></div></div></div></body></html>",
    "text": "テキストメールです。\\r\\n\\r\\nHTML文です。",
    "envelope-from": "user@example.jp"
}

データをJSONで受け取れていますので、FromやToを使ってデータベースを検索するといった仕組みを作るのも簡単でしょう。

まとめ

Azure Functionsは企業内でAzureを使ってシステム構築を行っている場合に良い選択になるでしょう。サーバーレスなので、実行数に応じた課金体系なので、Webhookを処理するのもごく低価格で実現できます。

ぜひCustomers Mail Cloudと組み合わせてみてください。