通知用Gmail送信に苦戦した話
投稿日: 2025年02月24日
麹帳というアプリでアプリを開けば何件コメント来ているというのはわかるようにしていたのですが、メール通知もやってみようと思い、取り組んでいました。
最初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を取得する処理が必要でした。
リダイレクト先で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送信に成功しただけなのであとちょっと、頑張ります!!