Webhook APIを使って添付ファイル付きメールを処理する(Go言語 + gin編)

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

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

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

<!—more—>

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

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

Webhook設定ダイアログ

Go言語による実装

Go言語では以下のように作成します。今回はWebフレームワークとしてginを利用しています。まず、プロジェクトを作ります。

go mod init smtps/webhook

また、ginをインストールします。

go get -u github.com/gin-gonic/gin

ginを使った場合のコードは、外観として以下のようになります。今回は POST /mails にてWebhookを受け取る前提になります。最後に必ずHTTPステータス200を返してください。

package main

import (
    "fmt"
    "io" // 添付ファイル用
    "os" // 添付ファイル用
    "strconv" // 添付ファイル用
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.POST("/mails", func(c *gin.Context) {
    // この中で処理します
        c.JSON(200, gin.H{})
    })
    r.Run() // 0.0.0.0:8080 でサーバーを立てます。
}

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

メールを受信すると、以下のような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": "...."
}

実装について

multipart/form-dataの場合、まず c.MultipartForm() を実行します。その後は c.Request.PostForm にデータが入ってきます。

なお、各データは配列になっているので注意してください。

c.MultipartForm()
for key, value := range c.Request.PostForm {
    fmt.Printf("%v = %v \n", key, value[0])
}

添付ファイルの存在確認

添付ファイルがあるかどうかは attachments キーの値が1以上かどうかで判定できます。

attachments, err := strconv.Atoi(c.Request.PostForm["attachments"][0])
if err != nil {
    fmt.Println(err)
}
if attachments > 0 {
  // 添付ファイルあり
}

添付ファイルをローカルに保存する

添付ファイルデータを受け取ってファイルとして保存する際には、以下のように処理します。

if attachments > 0 {
    // 添付ファイルあり
    file, header, err := c.Request.FormFile("attachment1")
    if err != nil {
        fmt.Println(err)
    }
    if file != nil {
        saveFile, _ := os.Create("./" + header.Filename)
        defer saveFile.Close()
        io.Copy(saveFile, file)
    }
}

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

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

Webhookログ

まとめ

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

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

受信サーバ | Customers Mail Cloud