Gmailのメール本文をCosense(旧scrapbox)にインポートするアプリをSveltekitで作ってみました
前置き
皆さん、普段のナレッジはどうしていますか? そもそもどこまでナレッジとしてアウトプットしていますか?
恐らく大半の人は、インターネットで見つけた有益な情報や記事をどこかに保存したり、ストックしたり、あるいは自分のメモ書きをナレッジとして蓄積していたりすると思います。
私は普段、頭に思い浮かんだすべてのアイディアや気になったこと、世間で話題になっていることに対する自分の考えなどを、Cosense にその都度必ず書き残すようにしています。私にとっては日々の感情もナレッジの一部になります。なので、うっすら記憶にある昔の出来事を思い出したときは、とりあえずCosenseを見に行くような習慣になっています。
前回は SlackのスレッドからCosense(旧Scrapbox)ページを作ってくれるBotを作った話 という記事を投稿し、SlackからCosenseにナレッジを移すアプリを作った話をしたのですが、最近Gmailに保存されている情報がCosenseにないことに気づき、前回の続き第2弾として、Gmailのメール本文をCosense(旧Scrapbox)にインポートするアプリを作ってみました。
完成物
先に完成物をお見せします。
UIはそのうちもう少しきれいにしたいと思っています🙇
必要な情報を登録します。
Gmail側でラベルを作成し、メールにラベルを付けます。
動画です。
同期できたらDiscordにも通知が来ます。
レポジトリはこちら
目指したゴール
ゴールとしては以下を目指しています。
- なるべくコードを触らず、セットアップもできるだけ簡潔で、すぐに動かせるようなアプリにしたい
- 複数のGmailアカウントから同じCosenseプロジェクトにインポートできるようにしたい
- 自動でページ作成をしてくれるようにしたい
- 取り込んだページリストをDiscordに通知したい
実現方法を考えてみる
流れとしては、Gmail APIからデータを取得してCosenseに書き込むだけなので、やり方はいろいろあると思います。
GASを使う
Google Apps Scriptを使ってGmail APIとCosense APIを叩く方法です。GASはGoogleのサービスなので、Gmail APIを叩く際にOAuth認証が不要で、スクリプトエディタから直接Gmail APIを叩けます。手軽に始められ、一番自然だと思います。
しかし、GAS上で動かすとなるとライブラリが自由に使えなかったり、実行時間制限があったり、それぞれのユーザー設定をコード内に書く必要があったりと拡張性に欠けるため、今回は見送りました。
Pub/Subを使ってトリガーする
GmailはGoogleのサービスなので、GCPのインフラを使えばとても自然に組み合わせられます。しかし、Pub/Subを使うとなるとGCP側の設定がいろいろ必要で、私が目指している「なるべくコードを触らずにセットアップも簡潔にしてすぐ動かせるアプリ」というゴールからは外れてしまうので、これも見送りました。
自前でアプリを作る
いろいろ考えた結果、自前でアプリを作り、cronで定期実行してメールをインポートする方法をとりました。
アプリの構成
- フレームワーク: SvelteKit + TypeScript
- UIフレームワーク: Tailwind CSS
- デプロイ: Vercel
- データベース: Upstash
- 認証: Google OAuth2 (Arctic)
- Gmail API: Google APIs Node.js Client
- 通知: Discord Webhook
フレームワークについては、私はSvelteKitのデータフローがとても好きで、個人のプロジェクトではよく使っているので、今回もSvelteKitを選びました。
機能
- Googleアカウントでログイン
- Cosenseプロジェクト名とCosenseのセッションIDを設定
- DiscordのWebhook URLを設定
- 一日に一回定期実行
- Gmailの「cosense」ラベルが付いたメールをインポート
Gmail APIを使うのでOAuth認証が必要になります。そのため、最初の一回だけGoogleアカウントでログインしてアクセストークンを取得し、cronでの定期実行時にそのトークンを使ってメール本文を取得し、Cosenseにインポートするようにしています。
そのため、データを保存するデータベースが必要です。いろいろ検討した結果、手軽に始められるようにVercelのサーバーレス関数と組み合わせて使えるUpstashを採用しました。
本当はステートフルなPostgreSQLの方が確実ですが、個人利用にはオーバースペックに感じたため、Redisを選びました。UpstashはサーバーレスRedisなのでデータが消える心配はなく、公式にもDBとして使えると明言されているため安心して利用できます。
アプリを使うためのセットアップ
Vercelにデプロイすることを前提に作っているので、ここではVercelを前提に解説します。Cloud Runなど別のインフラで動かしたい場合は自由にforkして使ってください。
必要なもの
- Googleアカウント
- Cosenseアカウント
- Vercelアカウント
- Upstashアカウント(Redis)
- GCPのプロジェクト・OAuthクライアントID・シークレット
上の3つのアカウント系については、この記事を読んでいる方は大体持っていると思うので割愛します。
Upstashに登録してRedisを作成
クレジットカードの登録不要でアカウントが作れるので、そのまま登録してDBを作成してください。
Redisを作成したら環境変数を控えておきましょう。
Gmail APIの有効化
Gmail APIを使うには、GCPのプロジェクトを作成し(既存のものでOK)、Gmail APIを有効化してOAuthクライアントIDとシークレットを取得する必要があります。
手順は以下の通りです。
GCPでプロジェクト作成
Gmail APIを有効化
認証情報作成
Google OAuth Platformがない場合は、まず作成する必要があります。
この後は必要な情報を入力していくだけなので割愛します。
OAuthクライアント作成
Google OAuth Platformが登録できたら、OAuthクライアントを作成します。
ここでJSONをダウンロードし、Client IDとClient Secretを控えてください。
中身は以下のようになります。
{
"web": {
"client_id": "*******.apps.googleusercontent.com",
"project_id": "gmail-to-cosense",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "*******",
"redirect_uris": [
"http://localhost:5174/login/google/callback",
"https://yourdomain.vercel.app/login/google/callback"
]
}
}
OAuthクライアントにデータスコープ追加
最低限必要なスコープを追加します。
自分自身をテストユーザーに追加
アプリを公開するか、自分をテストユーザーに追加するかのどちらかをしないと、OAuth認証後にrefreshTokenが取得できません。今回は自分しか使わないので、自分をテストユーザーに追加します。
本番モードにする
理由はテストモードだとアプリ側でのrefresh_tokenには規制がかかってるようになっているみたいです、3日ぐらいで期限切れてしまい、クローリングが失敗してしまいました。
Vercelにデプロイ
レポジトリ内のREADMEにある Deploy to Vercel ボタンをクリックすれば、そのままVercelにデプロイできます。
環境変数の設定が必要になるので、以下のように設定してください。
GCPのOAuthクライアントIDとシークレット
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
UpstashのRedis URLとトークン
UPSTASH_REDIS_URL=https://your-redis-url.upstash.io
UPSTASH_REDIS_TOKEN=your_redis_token
refreshトークンを暗号化するためのキー(32文字ランダム文字列)
TOKEN_ENCRYPTION_KEY=your_32_character_encryption_key
Vercelのcronジョブ用のシークレットキー(ランダムなセキュア文字列)
CRON_SECRET=your_random_cron_secret
その他
CosenseのセッションIDは、Cosenseにログインし、DevToolsを開き、cookiesから connect.sid の値を確認してください。
Cosenseの他のAPIについては以下のドキュメントを参考にしてください。
後置き
いかがでしたでしょうか?
スピード重視で作ったためテストは書いていません。もしバグなどあれば、issueやPRを立てていただけると助かります。🙇

























Discussion