📧

Cloudflare Email Workers でメールを受信したら Chatwork に通知する

2023/10/19に公開

はじめに

この記事はCloudflare Email Workers に関する記事です。

  • Email受信をトリガーにしてCloudflare Workersを実行したい
  • Cloudflare WorkersでChatworkに通知したい

上記に当てはまる方のお役に立てるかと思います。

Cloudflare 周りの説明

Cloudflare Workers とは

Cloudflare Workersは、サーバーレスコードをデプロイすることで、優れたパフォーマンス、信頼性、および拡張性をグローバルに提供するプラットフォームです。
このプラットフォームを使用することで、最新のクラウド向けアプリケーションを構築することが可能となります。

https://www.cloudflare.com/ja-jp/developer-platform/workers/

Cloudflare Email Workers とは

Cloudflare Email Workersは、Route to Workers 機能を利用して、受信したメールを EmailEvent として Workers ロジックを経由して転送する機能を提供します。
この機能は、特定の前提条件として Email Routing の設定が必要となります。

https://developers.cloudflare.com/email-routing/email-workers/

Cloudflare Email Routing を始めるには

以下のURLを参照いただければと思います。

https://c-limber.co.jp/blog/5174#email-routing-start

Wrangler とは

Wranglerは、Cloudflare Workers用のコマンドラインインターフェース(CLI)ツールで、簡単なコマンド入力でWorkers用プロジェクトの作成からビルド、デプロイまでを行うことができます。

https://developers.cloudflare.com/workers/wrangler/

Wrangler のインストール

npmで wrangler をインストール

npm install -g wrangler

wrangler バージョンの確認

wrangler -v

2023年10月時点で 3.13.2 が確認できます

 ⛅️ wrangler 3.13.2
-------------------

wrangler でプロジェクトを作成しデプロイする

wrangler ログイン

以下のコマンドでブラウザの認証画面からログインが可能です

wrangler login

wrangler プロジェクトの作成

以下のコマンドでプロジェクトの作成ができます

wrangler init chatwork-notify

postal-mime のインストール

プロジェクトディレクトリへ移動し、 postal-mime をインストールします

cd chatwork-notify
npm install postal-mime

index.js の編集

chatwork-notify/src/index.js を編集しメールを受けた際に

  • Chatworkへ通知
  • リストの配送先に転送

を実装します

const PostalMime = require('postal-mime');

const CW_API_ENDPOINT = "https://api.chatwork.com/v2/rooms/";

export default {
    async email(message, env, ctx) {
        ctx.waitUntil(notifyMessage(message, env));
    }
};

const streamToArrayBuffer = async (stream, streamSize) => {
    let result = new Uint8Array(streamSize);
    let bytesRead = 0;
    const reader = stream.getReader();
    while (true) {
        const {done, value} = await reader.read();
        if (done) {
            break;
        }
        result.set(value, bytesRead);
        bytesRead += value.length;
    }
    return result;
};

const buildNotifyMessage = async (message, parsedEmail, relayEmails) => {
    return `
[info]
[title]Notifications from Cloudflare Mail Email Workers[/title]
From: ${message.from}
To: ${message.to}
[code]
Message-id: ${message.headers.get('message-id')}
Received: ${message.headers.get('received')}
Date: ${message.headers.get('date')}
[/code]
[info]
Title: ${message.headers.get('subject')}
Body:
${parsedEmail.text}
[/info]
[code]
# Forwarding Email Addresses
${relayEmails.join(', ')}
[/code]
[/info]`;
};
const sendChatwork = async (notifyMessage, env) => {
    try {
        const cwBody = new URLSearchParams({
            body: notifyMessage,
        });
        const cwHeaders = new Headers();
        cwHeaders.append("Content-Type", "application/x-www-form-urlencoded");
        cwHeaders.append("X-ChatWorkToken", env.CHATWORK_TOKEN);
        const cwRequest = new Request(`${CW_API_ENDPOINT}${env.CHATWORK_ROOM}/messages/?${cwBody.toString()}`, {
            headers: cwHeaders,
            method: 'POST',
        });
        let cwResponse = await fetch(cwRequest);
        console.log(cwResponse);
    } catch (e) {
        console.error(e);
    }
};

const notifyMessage = async function (message, env) {
    try {
        const relayEmails = JSON.parse(env.RELAY_EMAILS);
        const rawEmail = await streamToArrayBuffer(message.raw, message.rawSize);
        const parser = new PostalMime.default();
        const parsedEmail = await parser.parse(rawEmail);
        const notifyMessage = await buildNotifyMessage(message, parsedEmail, relayEmails);
        console.log('parsedEmail: ', parsedEmail);
        await Promise.all(relayEmails.map(email => message.forward(email)));
        await sendChatwork(notifyMessage, env);
    } catch (e) {
        console.error(e);
    }
};

wrangler.toml の編集

環境変数を設定するために wrangler.toml を編集します

以下の情報へ変更して下さい

  • CHATWORK_TOKEN は Chatwork API のトークン
  • CHATWORK_ROOM は Chatwork のルームID
  • RELAY_EMAILS は 転送先のメールアドレスの配列
name = "chatwork-notify"
main = "src/index.js"
compatibility_date = "2023-10-01"
#node_compat = true
vars = { CHATWORK_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", CHATWORK_ROOM = "XXXXXXXXX", RELAY_EMAILS = '["email1@example.com", "email2@example.com"]' }

Cloudflare Workers へデプロイ

以下のコマンドでログイン中のアカウントへデプロイが可能です

npx wrangler deploy

最後に

Cloudflare Email Workers でメールを受信したら Chatwork に通知する方法をご紹介しました。
Cloudflare Email Routing の設定を行い、受信から Workers へ流すだけで Chatwork への通知とメールの転送が可能になりました。
メールを受信したら PDF化し R2への保存、添付ファイルのR2への保存なども今後やっていきたいと思います。

最後まで読んでいただき、ありがとうございました!

Discussion