ゼスト Tech Blog

ゼストは「護りたい。その想いを護る。」をミッションに、在宅医療・介護業界向けのSaaSを開発しています。

CDNだけじゃないCloudflare:Email Workersの使い方と活用例 〜 概要編 〜

Cloudflareといえば、一般的には高速なCDNサービスを思い浮かべる方が多いかもしれません。しかし、CloudflareはCDNだけではなく、セキュリティを強化するZero Trust、サーバーレスでアプリケーションを実行できるWorkers、データベースサービスのD1、オブジェクトストレージのR2など、様々な開発者にとって、便利なサービスを提供しています。

今回は、その中でも意外と知られていない便利な機能「Cloudflare Email Workers」をご紹介します。Email Workersを使えば、受信したメールをトリガーにしてWorkersの処理を実行できます。メールの転送、自動返信、内容の解析、他のサービスとの連携など、アイデア次第でさまざまな自動化が実現できます。

Cloudflare Email Routingとは?

Cloudflare Email Workersの紹介の前にまずは、基礎となるRouting機能についてご紹介します。

www.cloudflare.com

Cloudflare Email Routingは、カスタムドメインのメールアドレスを簡単に管理できるサービスです。独自ドメインで受信したメールを、GmailやOutlookなどの既存のメールボックスに転送できます。 Gmailアカウントしか持っていないが、独自のドメインのメールアドレスの登録を求められることは多々あると思います。その際に、メールサーバーを独自に立てることなく、自由にいくらでも自分のメールアドレスを発行することができます。

利用の条件としては、利用したいドメインをCloudflareをネームサーバーとして使用していることだけです。

Cloudflare上で管理しているドメインを選択し、サイドメニューの「メールアドレス」 -> 「Email Routing」から登録することができます。

ルーティングルールから発行したいメールアドレスを作成します。

これだけで、独自のメールアドレスを発行でき、Gmailアドレス等に転送することができます!

Cloudflare Workersとは?

Cloudflare Workersについては、ご利用されている方も多いため、あえて紹介する必要もないでしょう。

workers.cloudflare.com

簡単におさらいすると、Cloudflareのエッジネットワーク上でJavaScript/TypeScript/WebAssemblyを実行できるサーバーレスプラットフォームです。
世界中に分散したエッジロケーションでコードが実行されるため、ユーザーに近い場所で低レイテンシな処理が可能です。

コールドスタートがほぼゼロであるという点も、従来のサーバーレス環境と比較した大きなメリットですね。
また、R2(オブジェクトストレージ)、D1(SQLiteベースのデータベース)、KV(Key-Valueストア)、Queues(メッセージキュー)など、Cloudflareの他サービスとシームレスに連携できるのも魅力です。

料金面でも、毎日最初の10万リクエストまで無料という太っ腹な無料枠があり、個人開発や小規模プロジェクトで活用されている方も多いのではないでしょうか?

Cloudflare Email Workersとは?

Email Workersは、Email RoutingとCloudflare Workersを組み合わせた機能です。受信メールをトリガーとしてWorkerを実行し、受信したメールの内容をもとに、処理の自動化などを実現できます。

developers.cloudflare.com

通常のEmail Routingでは単純な転送しかできませんが、Email Workersを使えば

  • 送信者に応じて転送先を変える
  • 特定の条件でメールをドロップ(破棄)する
  • 外部APIを呼び出して通知を送る
  • メールの内容を解析して自動処理する

といった柔軟な処理が可能になります。

では実際に試してみましょう!

準備

wranglerがもしインストールされていないなら、まずは、下記のインストールから始めましょう。

$ npm install -g wrangler

次にCloudflareへログインしましょう。

$ wrangler login

最後にプロジェクトを作成します。

$ wrangler init <your-application-name>

これで、準備は完了です。次に src/index.js を編集していきましょう!

Email Workerの基本構造

Email Workerはemailイベントをリッスンする通常のWorkerです

export default {
  async email(message, env, ctx) {
    // message.from - 送信者アドレス
    // message.to - 受信者アドレス
    // message.headers - メールヘッダー
    // message.raw - 生のメール本文
    
    // 処理ロジックをここに記述
    
    // メールを転送
    await message.forward("destination@<your-domain>");
    
    // または拒否
    // message.reject("Rejected");
  }
}

利用可能なアクションとしては次のようなものがあります。

転送(forward)

await message.forward("inbox@<your-domain>");

認証済みの宛先アドレスにメールを転送します。複数の宛先への転送も可能です。

拒否(reject

message.reject("Unknown sender");

メールを拒否し、送信者にエラーを返します。

ドロップ(暗黙的)

もし何もアクションをしなければ、メールは破棄されます。

実践的なユースケース

これらのアクションを組み合わせることで、下記のようなことが実現できます。

1. 許可リスト(Allowlist)

特定の送信者からのメールのみを転送

export default {
  async email(message, env, ctx) {
    const allowList = [
      "user@<your trusted domain 1>",
      "user@<your trusted domain 2>",
    ];
    
    if (allowList.includes(message.from)) {
      await message.forward("inbox@<your domain>");
    } else {
      message.reject("Sender not in allowlist");
    }
  }
}

2. 宛先に応じた振り分け

受信アドレスによって転送先を変更

export default {
  async email(message, env, ctx) {
    switch (message.to) {
      case "sales@<your domain>":
        await message.forward("sales-team@<your forward domain>");
        break;
      case "support@<your domain>":
        await message.forward("support-team@<your forward domain>");
        break;
      default:
        await message.forward("info@<your forward domain>");
    }
  }
}

3. Slack通知との連携

重要なメールを受信したらSlackに通知

export default {
  async email(message, env, ctx) {
    const subject = message.headers.get("subject");
    
    // Slackに通知
    await fetch("https://hooks.slack.com/services/YOUR/WEBHOOK/URL", {
      method: "POST",
      body: JSON.stringify({
        text: `📧 新着メール\nFrom: ${message.from}\nSubject: ${subject}`
      })
    });
    
    // メールも転送
    await message.forward("<your>@gmail.com");
  }
}

4. 添付ファイルの処理

postal-mimeライブラリを使って添付ファイルを解析*1

import PostalMime from 'postal-mime';

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

export default {
  async email(message, env, ctx) {
    const rawEmailBuffer = await streamToArrayBuffer(message.raw, message.rawSize);
    const parser = new PostalMime();
    const parsedEmail = await parser.parse(rawEmailBuffer);
    
    // 添付ファイルをチェック
    for (const attachment of parsedEmail.attachments) {
      console.log(`Attachment: ${attachment.filename}, Type: ${attachment.mimeType}`);
    }
    
    await message.forward("inbox@gmail.com");
  }
}

Cloudflare Workersのセットアップ

アプリケーションを作成したら、workersにデプロイしましょう。

$ wrangler deploy

デプロイ後、CloudflareのEmail Routingのコンソール画面で作成したWorkerへの紐づけを行います。

アクションでは「ワーカーに送信」を選択します。デプロイに成功していれば、宛先に作成したWorkerが選択肢として表示されます。

ちなみにEmail Workersの実行は、通常のCloudflare Workersと同じ料金体系になっています。

無料枠: 毎日最初の100,000リクエスト(メールトリガー)まで無料

一般的な個人利用であれば、無料枠で十分カバーできるでしょう。

まとめ

Cloudflare Email Routingは、独自ドメインのメール管理を驚くほど簡単にしてくれます。そしてCloudflare Email Workersを組み合わせることで、メール処理の可能性が大きく広がります!

今回は、Cloudflare Email Workersの概要について紹介しましたが、次回はCloudflare Workersを利用した実践的なアプリケーションを紹介します。

ぜひCloudflare Email Workersを試して、プログラマブルなメール処理を体験してみてください!