通知用Gmail送信に苦戦した話

通知用Gmail送信に苦戦した話

投稿日: 2025年02月24日

学習振り返り
要約
  • Gmail APIを利用してメール通知を実装する際の苦労とポイントを共有。
  • 特にリフレッシュトークンの取得とリダイレクトURIの設定が重要であることを強調。
  • Supabaseを活用して非ログインユーザーのメールアドレスを取得し、問題を解決した。

はじめに

麹帳というアプリでアプリを開けば何件コメント来ているというのはわかるようにしていたのですが、メール通知もやってみようと思い、取り組んでいました。

最初send gridというメール送信用サービスがいいよと教えて頂いたのですが、法人専用になっていて使用することができず、GmailAPIで代用することにしました。

仕事でGoogleまわりのAPIは触ることがあったし、まぁ簡単かなと思って取り組んだら禿げそう&吐きそうだったので、ポイントだった箇所を共有したいと思います。

難易度を上げた箇所

  • メールの送信元、送信先ともにログインユーザーじゃないこと

  • バックエンドで完結させること(ブラウザ操作なし)

この2箇所でした。

公式のドキュメントみてもググっても、「ブラウザ開いて認証」ばっかり出てきました。
ほうほうと思ってやってるとブラウザ開く処理(´;ω;`)
そうじゃないんだよ、バックエンドでやりたいんだよ。千歩譲ってユーザーが認証処理するとしても、📧送信するトリガーになる処理をする人は送る人でもないし受け取る人でもない!!

全然欲しい情報でてこんやないの!って絶望はしてないけど、まぁまぁハードやなと思いながら取り組みました。

ポイント

結果、出来たのですがこれがすぐわかる情報があればもっとスムーズにできたなと思った箇所があります。

リフレッシュトークンの取得が必要

ブラウザを開かないので、リフレッシュトークンを取得するための処理を事前準備として行う必要がありました。
色々調べたのですがここではブラウザを開くしかなさそうでした。

ライブラリはgoogleapisを使用しまして、

const oauth2Client = new google.auth.OAuth2(
      process.env.CLIENT_ID,
      process.env.CLIENT_SECRET,
      `${process.env.NEXT_PUBLIC_APP_BASE_URL}/api/auth/callback/google`);

このリダイレクト先でURLからcodeが取得できるので、それを使って

//省略
const { tokens } = await oauth2Client.getToken(code);
return NextResponse.json({
      refreshToken: tokens.refresh_token,
});

これで確認したrefreshTokenを環境変数に置いておきます。

メール送信を行う際に必要になるのは、access_tokenなのですが、こちらは時間が経つと値が変わってしまうので、refreshTokenを使ってaccess_tokenを取得する処理が必要でした。

redirectUriは必須

リダイレクト先でgoogle.auth.OAuth2のインスタンスを生成する際のコンストラクタの引数なのですが、最初クライアントIDとクライアントシークレットだけにしてredirectUriを書いていなくて認証エラーになっていました。
すでにリダイレクトされた先で行う処理だから必要ないと思ったんです。

型確認してもオプショナルなので余計に必要ないと思ったんです。

AuthPlus.OAuth2: new (clientId?: string, clientSecret?: string, redirectUri?: string) => OAuth2Client (+1 overload)

でもエラー出てあれこれやってる中でここも必要なんだと気づきました。
というか数打てば当たる精神でいつもエラー潰しているのですが、ひたすら試している中でここに入れてみたら出来たって感じです。

const oauth2Client = new google.auth.OAuth2(
    process.env.CLIENT_ID,
    process.env.CLIENT_SECRET,
  );

↑これだとダメなのでお気をつけて・・

ログインユーザー以外のメールアドレスを取得する

こちらはオマケです。公式みたらすぐできる内容ですので。。
supabaseですが、今回は通知を受け取る人のメールアドレスが送信先になるのですが、ログインユーザーではないんですよね。

これは管理者権限が必要な処理なので、SUPABASE_SERVICE_ROLE_KEYが必要でした。

import { createClient } from "@supabase/supabase-js";

export const supabaseAdmin = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY! //NEXT_PUBLICつけたらだめ
);

こちらを用意して、

const { data,error } = await supabaseAdmin.auth.admin.getUserById(
      user.supabaseUserId
    );

このようにしたらOKです。

おわりに

公式のサンプル見てもサーバーサイドの方はJavaとPythonしかなかったり、そのままドンとコピペしてちょっといじれば行ける感じではなかったり、ライブラリも色々ありどれがいいのか悩みながらでしたが、なんとかなりました。

オリアプのお問い合わせフォームとかでメール送信の機能は使うこともあるかもしれないので参考になったら嬉しいです。

まだTEST送信に成功しただけなのであとちょっと、頑張ります!!

シェア!

Threads
user
吉本茜
山口在住/二児の母/育休中
Loading...
記事一覧に戻る
Threads
0