Site icon image rpine lab Blog

プログラミングや電子工作系の記事を投稿しています。

📨 Cloudflare PagesからMailChannelsでメールを送信する(2024年8月以降利用不可)

💡
MailChannelsからのアナウンスの通り、Cloudflare Workersとの連携による無料メール送信機能は2024年8月をもって完全終了しました
そのため本記事で説明している方法はもう使えません。

Cloudflare PagesやWorkersからはSendGridなどの外部サービスを契約しなくても、Cloudflareと提携しているメール配信サービスのMailChannelsを利用することで無料でメールを送信することが可能です。

これを利用してお問い合わせページなどが作成できます。

今回はCloudflare PagesからMailChannelsのAPIを使ったメール送信方法を解説します。

MailChannelsを使うための設定

MailChannelsを使ってメールを送信するためには、送信元アドレスのドメインのDNS設定が必要です。

これはMailChannelsのDomain Lockdownという仕組みに対応するためで、次のようなレコードをDNSに追加する必要があります。

参考サイト1 (MailChannelsの記事)・参考サイト2 (Cloudflareのドキュメント)

レコード名レコードタイプ
_mailchannels.<送信元ドメイン>TXTv=mc1 cfid=*****.pages.dev (Pages上のWorkersから利用する場合)
v=mc1 cfid=myaccount.workers.dev (Workers単体で利用する場合)
💡
引っかかったポイント1
サブドメインを送信元に使う場合は、レコード名の<送信元ドメイン>の部分にサブドメインを含めたレコード名を指定します。
例(noreply.example.comを送信元アドレスのドメインに利用):_mailchannels.noreply(.example.com)()の部分はDNS設定画面によっては省略表示
💡
引っかかったポイント2
CloudFlare Pages上で動作しているCloudflare WorkersからAPIを呼び出す場合には、MailChannelsの参考サイトのようにアカウントごとのWorkersのサブドメイン(myaccount.workers.dev)ではなく、Pagesプロジェクトのドメイン(*****.pages.dev)の方を指定する必要がありました。
何を指定すればいいか迷った場合には、複数指定可能なのでcfid=****をスペースを空けて複数書けばいいと思います。

送信元ドメイン認証関係

MailChannelsを利用したメール送信では、SPFによる送信元メールサーバの指定やDKIMによるメールの電子署名が可能です。

Gmailによるスパム判定の強化などもあるので出来れば設定した方がいいと思います。

SPF設定
レコード名レコードタイプ
<送信元ドメイン>TXTv=spf1 include:_spf.mx.cloudflare.net include:relay.mailchannels.net -all

DKIM設定

DKIMは設定が面倒で、手元で署名用の秘密鍵を生成する必要があります。生成した秘密鍵は後程、環境変数に設定してAPIの呼び出しに利用し、公開鍵はDNSのDKIMレコードに登録する必要があります。

方法(コマンドは公式ドキュメントからコピペ)

  1. 手元のマシンのターミナルで秘密鍵を生成します。生成したprivate_key.txtは、後程Pagesの環境変数に設定してMailChannelsのAPI呼び出しの際に指定します。
    openssl genrsa 2048 | tee private_key.pem | openssl rsa -outform der | openssl base64 -A > private_key.txt
  2. DNSレコード登録用のテキストファイル(dkim_record.txt)を生成します。
    echo -n "v=DKIM1;p=" > dkim_record.txt && openssl rsa -in private_key.pem -pubout -outform der | openssl base64 -A >> dkim_record.txt
  3. 生成したdkim_record.txtの中身を使い、次のDNSレコードを追加します。
    レコード名レコードタイプ
    mailchannels._domainkey.<送信元ドメイン>
    mailchannelsの部分はセレクタキーで、API呼び出しの際に指定します。
    TXTdkim_record.txtの中身(v=DKIM;p=から始まる)を全て貼り付け

(DMARC設定は省略)

MailChannels APIを利用したメール送信

Cloudflare Workers上からMailChannelsのAPIを呼び出すことでメールを送信することができます。

PagesのMailChannelsプラグインを利用する方法もあるのですが、色々カスタマイズがしやすい、APIを直接呼び出す方法を今回は利用します。

利用するエンドポイントは、https://api.mailchannels.net/tx/v1/sendです。API仕様はhttps://api.mailchannels.net/tx/v1/documentationにあります。

必要な設定(環境変数)

Pagesの環境変数のDKIM_PRIVATE_KEYに、上のDKIM設定で予め作成しておいたprivate_key.txtの内容をセットしてください。

メール送信関数 (TypeScript)

単純なテキストを送る場合の関数の実装コードです。API仕様等を確認しながら適宜カスタマイズしてください。

Next.js 14のServer Actionsを利用した場合で動作を確認していますが、それ以外のWorkersで動くミドルウェアやルートハンドラ等からでも使えるはずです。

async function sendMail({
  subject,
  content,
}: {
  subject: string
  content: string
}) {
  const payload = {
    personalizations: [
      {
        to: [{ name: 'NAME', email: '[email protected]' }],
        dkim_domain: 'noreply.example.com',
        dkim_selector: 'mailchannels', // DKIMのレコード名と同じセレクタを指定
        dkim_private_key: process.env.DKIM_PRIVATE_KEY,
      },
    ],
    from: {
      name: 'Contact Form',
      email: '[email protected]',
    },
    subject,
    content: [{ type: 'text/plain; charset="UTF-8"', value: content }],
  }

  // MailChannels APIを利用してメール送信
  const response = await fetch('https://api.mailchannels.net/tx/v1/send', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
  })

  if (response.status === 200 || response.status === 202) {
    return // 正常に送信できた場合
  }

  try {
    const errors = ((await response.json()) as { errors?: string[] })?.errors
    console.error({ errors })
  } catch {
	  console.error(response.statusText)
  }
}

メールの送信に失敗する場合

APIからの応答にあるエラーメッセージを確認して修正してください。

失敗していたら多分上に書いたDomain LockdownやDKIMのDNS設定辺りの修正が必要だと思います。DNSの設定の反映には時間がかかるので、変更後は時間を置いてテストする必要があります。

また、この方法だとCloudflare Workers以外の実行環境(例えばローカル環境でのデバッグ)からはメール送信できないので、テストの際はPagesのdevelop環境などで実際に実行して試す必要があります。

まとめ

今回はCloudflare PagesからMailChannelsのAPIを使ったメール送信方法を解説しました。

同じくCloudflareが提供しているBOT対策のCloudflare Turnstileを組み合わせることで、Cloudflareで全て完結する形で、いい感じにお問い合わせページ等が作れます。

参考サイト

広告