SupabaseのEdge FunctionsとSendGridでメールを一斉送信する

WEBサービスやECサイト、会員向けメルマガを発行する際、どのようにして送信されますか?
普通にメールソフトやGmailから送信すればいいのでは?』と思うかもしれませんが、実はそれ、すごくリスクが高い手法です。
同じIPから同じ文面を大量送信すると、受け手のブラックリスト等に入れられ、普通のビジネスメールですら届かなくなるかもしれません。

では一般企業はどのようにしてメールを送っているのか、といえば『SendGrid』のようなメール送信サービスを利用しています。
SendGridはスパムフィルタに引っかかりにくい送信手法を取っていますし、各種APIや効果測定機能等も充実しています。

今回はSupabaseの『Edge Functions』とメール配信サービスである『SendGrid』を利用して、DBで管理されているメールアドレスに一斉送信をする仕組みを作成します。

目次

事前準備

今回の実装を行うために下記の対応を行う必要があります。

Dockerの環境構築

https://www.docker.com/ja-jp/products/docker-desktop/Dockerがもしインストールされていなければ、上記URLからDockerをダウンロード&インストールしてください。

Denoの環境構築

https://docs.deno.com/runtime/manual/getting_started/installationDenoがもしインストールされていなければ、上記URLからDenoをインストールしてください。

Gmailのメールアドレス(エイリアス)追加

参考リンク
複数のメールアドレスを疑似的に準備するため、メールアドレスを5つ追加しておきます。
(sample+1@example.com, sample+2@example.comのように連番で作成してください。)

SendGridのアカウント作成~Web APIの初期設定

https://sendgrid.com/en-usもしまだSendGridを利用したことがない場合は、上記のURLからSendGridのアカウントを作成してください。

その後、下記のURLからWeb APIの初期設定を行います。
https://app.sendgrid.com/guide/integrate
この時作成したAPIキーをコピーしておいてください。(Edge Functionsで利用します。)

Supabase側の設定

①:Supabaseプロジェクトの作成

Supabaseにログイン(登録していなければアカウント登録から)して、
トップページの「New Project」を押します。

すると、下記の様な画面が表示されます。

適当なプロジェクト名とデータベースのパスワードを入れ、新しいプロジェクトを作成しましょう。
※Regionはできれば自分の住んでいる地域の近くがいいです。私は日本にしました。

②:Supabaseテーブル作成

Supabaseのダッシュボードから`Table Editor`にアクセスし、新しいテーブルを作成します。
下記のような設定で`recipients`テーブルを作成してください。

事前準備で作成したメールアドレスで5つの行を作成してください。

③:テーブルのポリシー設定

②で作成した`recipients`テーブルにアクセス可能にするポリシーを設定します。
Supabaseのダッシュボードより`Authentication`→`Policies`から`recipients`を選択し、`New Policy`ボタンを押します。
今回はあくまで誰でもrecipientsにアクセスできれば良いため添付画像のように設定してください

Edge Functions作成

①:Edge Functions環境構築

適当なディレクトリを作成し、下記のコマンドでsupabaseのCLIをインストールします。
(下記はすべて作成したディレクトリ内の作業です)

npm install supabase --save-dev

Supabaseにログインします。

npx supabase login

supabaseを初期化します。

npx supabase init

Edge Functionsを作成します。

npx supabase functions new sendgrid

最終的にディレクトリ内が下記のような状況になっていればOKです。

②:Edge Functions実装

まずは実装のために事前準備で作成したSendGridのAPIキーを利用できるようにしましょう。
ディレクトリ直下に`.env`ファイルを作成します。
内容は下記のような形です。

SG_API_KEY=ここにAPIキーが入る

次に関数そのものを作成します。
`functions/sendgrid/index.ts`を開きましょう。
内容を下記に変更します。

コードの内容としては、

  • Supabaseの`recipients`テーブルからデータ取得
  • emailアドレスをAPIにポストするjsonの形に合わせる。
  • SendGridのAPIにポスト

といった形です。

import { createClient } from 'https://esm.sh/@supabase/supabase-js'

const SG_API_KEY = Deno.env.get('SG_API_KEY')
 
const handler = async (_request: Request): Promise<Response> => {
  try {
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_ANON_KEY') ?? '',
    )

    const { data: recipients, error } = await supabase.from('recipients').select('*')

    if (error) {
      throw error
    }

    const recipientArr = []
    
    let index = 0;

    recipients.forEach((recipient) => {
      recipientArr.push(
        {
          "to": [{"email": recipient.email}],
          "headers": {"Message-ID": `<sample${index}@example.com>`}
        }
      )
      index++
    })

    const res = await fetch("https://api.sendgrid.com/v3/mail/send", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + SG_API_KEY,
      },
      body: JSON.stringify({
       "personalizations": recipientArr,
        "from": {"email": "ここにSendGridで設定したfromのメールアドレスを入れる"},
        "subject": "Supabaseからの一斉送信テスト",
        "content": [
          {
            "type": "text/plain",
            "value": "Supabaseからの一斉送信テスト"
          },
          {
            "type": "text/html",
            "value": "<html><head></head><body>Supabaseからの一斉送信テスト</body></html>"
          }
          ]
        }),
    });
  
    return new Response(res.body, {
      status: res.status,
      headers: {
        'Content-Type': 'application/json',
      },
    });

  } catch (err) {
    return new Response(String(err?.message ?? err), { status: 500 })
  }
};
 
Deno.serve(handler);

ここは適宜、皆さんの環境に合わせて置き換えてください。

"from": {"email": "ここにSendGridで設定したfromのメールアドレスを入れる"},

③:Edge Functionのデプロイ

ここまででEdge Functionが作成できたので、実際にSupabaseにデプロイし利用できるようにしましょう。
まずは.envファイルをSupabaseに送ります。
プロジェクトIDはhttps://supabase.com/dashboard/project/ 以下のテキストです。

npx supabase secrets set --env-file .env --project-ref {プロジェクトID}

次に下記で関数のデプロイを行います。
ログにエラーが出なければOKです。

npx supabase functions deploy sendgrid --project-ref {プロジェクトID}                  

設定後はSupabaseダッシュボード→`Project Settings`→`Edge Functions`に下記のように変数が追加されます。

また、Supabaseダッシュボード→`Edge Functions`に関数が追加されます。

実行確認

それでは実際にメールの一斉送信ができるか確認してみましょう。

まず実行前にSupabaseのダッシュボード→`Edge Functions`から追加した関数の詳細ページを開きます。

設定に`Enforce JWT Verification`がありますが、今回認証を強制せずに確認したいためチェックをOFFにしてください。

上記の設定が終わったらShellで下記を実行しましょう。

curl -I -X POST https://{プロジェクトID}.supabase.co/functions/v1/sendgrid

実行後に`HTTP/1.1 202 Accepted`と帰ってきたら成功です。

Gmailを開くと5通のメールが送られていることが確認できます。

これでメール一斉送信の仕組みの作成は完成です!
これをアプリの利用者向けに活用したり、顧客リストからメールマガジンを送る際等に利用してください。

その他参考資料など

今回のgithubはこちらです。

またTodoONada株式会社では、チャットシステム以外にも、ストレージを利用した画像アプリや、SMS認証の作成方法についてご紹介しています。
ぜひこちらもご覧ください!

SupabaseのTIPSリンク集

お問合せ&各種リンク

presented by

  • システム開発、アプリ開発
  • マッチングアプリ開発
  • インフラ構築支援等、なんでもご相談ください。
よかったらシェアしてね!
  • URLをコピーしました!
目次