【第1回】完全無料で構築するモダンメールサーバー!Cloudflare Workers × TypeScript × Resendで自動応答システムを作ろう

第1回resendAPIを使ったCloudflareWorkersからのメール送信の概要 プログラミング

今回は、サーバーの維持費を永年0円(無料枠内)に抑えつつ、信頼性の高い独自ドメインのメール送受信環境を構築する方法を解説します。

全数回にわけて解説します。第1回目は、システム全体の概要と、プログラムから独自ドメインでテストメールを送信するまでの手順を進めていきます。

環境はWindows11を想定しています。Macの方はターミナルコマンドを適宜変更してください。

1. 今回構築するメールシステムの概要

今回構築するのは、「Cloudflare Workers」「TypeScript」、そして次世代のメール配信サービス「Resend」を組み合わせた超軽量・高速なサーバーレスメールシステムです。

クライアントからのメールがresendへ届くまでの流れ

自分自身も以前はVPSでPostfixやDovecotをセットアップして様々な設定ファイル、レコード管理などを駆使してメールサーバーを構築していましたが、今回のこのシステムを使えば管理の手間もコストも劇的に削減できます。

VPSすら持たずにメールサーバーを無料で構築できるのは非常に驚きでした。

構成の全体像とメリット

[クライアント/Webポータル] 
       │ (HTTP POST)
       ▼
[Cloudflare Workers (TypeScript)] ──(API Key認証)──► [Resend API]
                                                            │ (SMTP/DNS認証)
                                                            ▼
                                                    [宛先メールアドレス]

なぜこの技術スタックなのか?(選定理由とメリット)

  • Cloudflare Workers: サーバーを持たずにプログラムを実行できる環境(サーバーレス)です。メールの送受信イベントが発生した瞬間だけ起動するため、無駄な待機コストが一切かかりません。
  • TypeScript: 型安全で堅牢なコードを記述し、バグの少ないクリーンな開発を進めます。
  • Resend: 開発者体験(DX)が抜群に良い最新のメール配信サービスです。無料枠が1日100通 / 月3,000通まで用意されており、面倒な送信ドメイン認証が画面の指示通りに進めるだけで完了します。

これらを組み合わせることで、従来のようなVPSのメールサーバー構築の手間や、ブラックリスト入りのリスクから解放された快適なメール環境が手に入ります。

2. Resendの初期設定とドメイン認証

まずは、メール送信の要となる Resend のセットアップとドメイン認証を行います。これを怠ると、送信したメールがGmail等で「迷惑メール」扱いされたり弾かれたりしてしまいます。

ドメイン認証によって送信メールの高い到達率を実現する流れ

独自ドメインの登録とDNS認証

  • Resendのダッシュボードにサインアップし、ログインします。
  • 左メニューの 「Domains」「Add Domain」 をクリックします。
  • お持ちの独自ドメイン(例: go-pro-world.net)を入力し、Regionに ap-northeast-1(東京)などを指定して登録します。
  • 画面に表示される DNSレコード(MXレコード、TXTレコード等) を、ドメインのDNS管理画面(Cloudflareなど)に設定するか、確認ボタンがあればクリックだけで設定が書き換えられます。

💡 ポイント: なぜDNS設定が必要なのか?

TXTレコードを設定することで、SPF(送信元のなりすまし防止)や DKIM(メールの改ざん防止)といったドメイン認証がパスします。これにより、相手の受信トレイに確実に届くようになります。

  • 以下の画面のように Status が Verified になればOKです。
resendに独自ドメイン登録した後の管理画面のスクリーンショット

API Keyの取得

認証が完了したら、プログラムからResendを操作するための鍵を取得します。

  • 左メニューの 「API Keys」「Create API Key」 をクリック。
resendのAPIKeyを作成する画面のスクリーンショット
  • Nameに Workers-Mail などと入力し、Permissionは Full Access を選択して作成します。
resendのAPIKey取得のための設定画面のスクリーンショット
  • 発行された re_xxxxxxxxxxxx というAPIキーを安全な場所にコピーしておきます。
    ※画面を閉じると二度と表示されないため、必ずコピーしてください。

3. プロジェクトの作成とコードの実装

ここからはローカル環境(PC)で開発を進めます。

npmでプロジェクトを作成する

ターミナル(PowerShellやMacのターミナル)を開き、プロジェクト作成のコマンドを入力します。

 npm create cloudflare@latest mail-serverless

​🔍 コマンドの仕組みを分解

  • ​npm (Node Package Manager)
    • ​Node.jsというJavaScript/TypeScriptの環境で使えるライブラリ管理ツールです。
  • ​create
    • ​npmが持つ特別な機能で、「新しくプロジェクト(ひな型)を作るとき専用」の命令です。内部的には npm exec create-cloudflare という仕組みを裏側で走らせています。
  • ​cloudflare@latest
    • ​「Cloudflare公式が提供しているプロジェクト作成ツール(create-cloudflare)の最新版(latest)を使ってください」という意味です。
  • ​mail-serverless
    • ​あなたがこれから作るプロジェクト名(フォルダ名)です。自由に決められます。

いくつか質問されるので以下のように選択していきます。

 What would you like to start with? 
  ● Hello World example 
  Select from barebones examples to get started with Workers  
╰ Which template would you like to use? 
  ● Worker only 
 Which language do you want to use? 
  ● TypeScript
Do you want to add an AGENTS.md file to help AI coding tools understand Cloudflare APIs? 
 ●  No

作成されたフォルダに移動し、Resend公式のSDKをインストールします。

cd mail-serverless
npm install resend

設定ファイル(wrangler.jsonc)の修正

プロジェクトのルートにある wrangler.jsonc を開き、以下のように本番環境用の基本設定を記述します。

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "mail-serverless",
  "main": "src/index.ts",
  "compatibility_date": "2024-04-03",
  "observability": {
    "enabled": true
  },
  "vars": {
    "RESEND_API_KEY": "re_xxxxxxxxxxxxxxx" // ローカルテスト時に一時的にキーを入れる場所
  }
}

送信プログラム(src/index.ts)の実装

src/index.ts の中身を以下のように書き換えます。Webからのリクエスト(POST)を受け取って、Resend経由でメールを送信するシンプルなAPIを作成します。

import { Resend } from 'resend';
// Cloudflare Workersの環境変数を定義する型(インターフェース)
// wrangler.jsonc や Cloudflareのダッシュボードで設定した変数を受け取ります
export interface Env {
  RESEND_API_KEY: string; // Resendの管理画面から取得したAPIキーが入る
}
export default {
  // ■ Webからのリクエスト(HTTPリクエスト)が発生したときに自動的に実行されるメイン関数
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    
    // リクエストされたURLの情報を解析する(パス名などを取得するため)
    const url = new URL(request.url);
    
    // 【セキュリティ&ルーティング制限】
    // メソッドが「POST」かつ、アクセス先が「/send」以外のリクエストはすべて404エラー(Not Found)で弾く
    if (request.method !== 'POST' || url.pathname !== '/send') {
      return new Response('Not Found', { status: 404 });
    }
    try {
      // 送信されてきたJSONデータ(リクエストボディ)を解析し、必要な値を取り出す
      // to: 送信先アドレス, subject: 件名, text: 本文
      const { to, subject, text } = await request.json() as { to: string; subject: string; text: string };
      // 環境変数にResendのAPIキーが正しく設定されているかチェック
      if (!env.RESEND_API_KEY) {
        return new Response('API Key is missing', { status: 500 });
      }
      // Resendの送信クライアントを初期化(APIキーを渡す)
      const resend = new Resend(env.RESEND_API_KEY);
      
      // ResendのAPIを使って、実際にメールを送信する
      const { data, error } = await resend.emails.send({
        from: '[email protected]', // 認証を完了させたあなただけの独自ドメインアドレス
        to: [to],                      // 送信先(配列で指定)
        subject: subject,              // メールの件名
        text: text,                    // メールの本文(テキスト形式)
      });
      // Resend側で送信エラー(ドメイン未認証やアドレス不備など)が発生した場合の処理
      if (error) {
        return new Response(JSON.stringify({ error }), { status: 400 });
      }
      // 送信がすべて成功した場合、結果のデータと一緒にステータス200(成功)を返す
      return new Response(JSON.stringify({ message: 'Email sent successfully', data }), { status: 200 });
      
    } catch (err: any) {
      // JSONのパース失敗など、予期せぬプログラムエラーをキャッチして500エラーを返す
      return new Response(JSON.stringify({ error: err.message }), { status: 500 });
    }
  }
};

4. 開発サーバーの起動と送信テスト

開発サーバーの立ち上げ

コードが書けたら、ローカル環境でWorkersを起動します(npm run start でも同様に起動します)。

npx wrangler dev

ターミナルに http://localhost:8787 と表示されれば、ローカル開発サーバーが正常に起動しています。

コマンドでテストメールを送信する

サーバーを起動したまま、別のターミナルウィンドウを開き(またはcurlが実行できる環境で)、以下のコマンドを実行してメール送信テストを行います。

💡 Windows (PowerShell) での送信テストのコツ

PowerShellでJSONを直接指定すると、ダブルクォートのエスケープ(\”)漏れでエラーになりがちです。 ConvertTo-Json を使うか、1行で書く場合はダブルクォートをエスケープして実行してください。

  • ConvertTo-Jsonを使う方法
# 1. 送信データをハッシュテーブルで作成
$body = @{
    to      = "[email protected]"
    subject = "【テスト】Cloudflare Workersからの送信"
    text    = "WorkersとResendを使ったメール送信テストです。"
} | ConvertTo-Json -Depth 3 -Compress
# 2. リクエストの送信
Invoke-RestMethod -Uri "http://localhost:8787/send" `
  -Method Post `
  -ContentType "application/json; charset=utf-8" `
  -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
  • エスケープして1行で書く方法

コマンドの末尾にある `(バッククォート)は「次の行へ続く」という意味の記号です。このままコピー&ペーストして実行するか、` を外して横一行につなげて実行しても同じように動きます。

Invoke-RestMethod -Uri "http://localhost:8787/send" `
  -Method Post `
  -ContentType "application/json; charset=utf-8" `
  -Body "{\"to\":\"[email protected]\", \"subject\":\"【テスト】Cloudflare Workersからの送信\", \"text\":\"テストメッセージ\"}"

​🔍 コマンドの仕組みを分解​

  • nvoke-RestMethod​
    • PowerShellで「外部のWebサイトやAPIとデータのやり取りをする」ための専用の機能(コマンドレット)です。
  • ​-Uri “http://localhost:8787/send”
    • データの送信先(宛先URL)です。localhost:8787 はあなたのパソコン内で立ち上がっているCloudflare Workersの開発サーバーを指しており、コード内で指定した /send というエンドポイントを呼び出しています。
  • ​-Method Post​
    • データを「新規登録・送信」するときに使われるHTTP通信の規格(POSTメソッド)を指定しています。​
  • -ContentType “application/json”
    • ​プログラムに対して、「今から送るデータは JSON(ジェイソン)形式 というプログラムが読みやすい形式のテキストですよ」と教えてあげるための設定です。​
  • -Body ‘{“to”:…, “subject”:…, “text”:…}’​
    • 実際に送信する**メールの中身(データ本体)**です。先ほど修正した src/index.ts のプログラムが、この to、subject、text という名前を読み取って、そのままResendに引き渡してメールを送信します。

コマンドを実行し、少し待って指定したテスト用アドレスにメールが届いていれば、第1段階の送信テストは見事成功です!

5. 次回予告

第1回目は、ResendとCloudflare Workersを連携させ、プログラムからメールを送信する基盤を作りました。

  • サーバーの維持費は0円
  • 高いメール到達率(SPF/DKIM設定済)
  • 数行のTypeScriptで完結するシンプルな構造

第2回目では「メールの受信と自動応答」の実装に入ります。CloudflareのEmail Routingを活用し、送られてきたメールをWorkerでキャッチして日本語で自動返信する仕組みを構築します。

是非以下の記事をご覧ください。

コメント