📝

Gemini API を使った要約機能付き受信メール通知 LINE Bot

2024/02/07に公開

やりたいこと

メールの着信を LINE 通知. そのときにメールの内容を要約して表示したい.

環境

GAS + GCE(Node.js)

仕組み

  1. [GAS] 新着メールを定期的に確認し、検知したら内容を 2 へ送信
  2. [GCE] Express HTTP サーバが 1 からのリクエストを受信したら、Gemini にメールを要約するようにプロンプトを送信
  3. Gemini がプロンプトに対して返答し 2 へ返す
  4. [GCE] 3 からの返答を 5 へ送信
  5. [GAS] LINE Messaging API へ通知データを送信
  6. LINE Messagine API から LINE に通知が届く

GAS
├ main.gs (Gmailへのアクセス)
└ do-post.gs (LINE 通知要請プログラム)

GCE
└ Express サーバ

詳しい設定方法はこちら
https://github.com/bbsfish/gemini-bot-server/tree/main

ステップ

  1. Gemini API アクセス
    Gemini へプロンプトを送信し、結果を取得するプログラム.
  2. Gmail へのアクセス
    Gmail を定期的に確認する GAS プログラム.
  3. LINE 通知要請プログラム
    LINE Messaging API に通知内容を送信する GAS プログラムである.
  4. Express サーバ作成
    1 のプログラムと連携し、Gemini に問い合わせるための HTTP サーバ.
    API を公開し、GAS(2) からのリクエストを受け付け、Gemini を通したメッセージを GAS(3) にリクエストするプログラム.

1. Gemini API アクセス

  • Gemini API Key を作成する
    Google AI Studio を使うと簡単に取得できる
  • 公式 SDK パッケージ GoogleGenerativeAI をインストールする
npm i @google/generative-ai
  • 今回は gemini-api.js をモジュールとして使うためにマイナーチェンジ
gemini-api.js
const { GoogleGenerativeAI } = require("@google/generative-ai");

// ↓ your-gemini-api-key には生成した API Key を入れる. (実装時は環境変数を使う)
const genAI = new GoogleGenerativeAI('<your-gemini-api-key>');

async function run(_prompt) {
  // For text-only input, use the gemini-pro model
  const model = genAI.getGenerativeModel({ model: "gemini-pro"});

  const prompt = _prompt;

  const result = await model.generateContent(prompt);
  const response = result.response;
  const text = response.text();
  return text;
}

module.exports.run = run; // Module Export

2. Gmail へのアクセス

GAS で次のコードを作成し、main 関数を 10 分おきに起動する設定を行う.
Gmail を "is:unread" で定期的に検索し、ヒットしたら、Express サーバに送信する.

main.gs
function main() {
    const GmailSreadLimit = 3; // 取得するメール検索結果のスレッド数

    const masking = (text) => text
        .replace(/ID:.*$|ID.*|PW:.*$/g, "*****") // 必要に応じた個人情報マスキング
        .replace(/\r\n/g, '\n');

    const threads = GmailApp.search('is:unread', 0, // メール検索
        GmailSreadLimit);
    const msgsInThreads = threads.map((t) => {
        if (t) return t.getMessages();
    });
    const mails = msgsInThreads.map((msgs) => {
        return msgs.map((m) => {
            m.markRead(); // 取得したメールを既読にする
            const plainBody = m.getPlainBody(); // メール本文
        
            return {
                from: m.getFrom(),
                subject: masking(m.getSubject()),
                body: masking(plainBody),
            };
        });
    });

    const arr = mails.flat();
    arr.forEach((m) => {
      sendPostRequest(m); // データを POST
    });
}

// data を Express サーバに POST する関数
function sendPostRequest(data) {
  const options = {
    "method": "POST",
    "headers": {
      "Content-Type": "application/json"
    },
    "payload": JSON.stringify(data)
  };

  UrlFetchApp.fetch("http://xxx.xxx.xxx.x:3000", // Express サーバアドレス
    options);
}

3. LINE 通知要請プログラム

POST があったら LINE Messaging API に通知内容を POST する GAS プログラムである.
LINE Messaging API へのアクセスには、ライブラリをお借りした.
インポートが必要.
ライブラリID: 1EvYoqrPLkKgsV8FDgSjnHjW1jLp3asOSfDGEtLFO86pPSIm9PbuCQU7b
https://qiita.com/kobanyan/items/1a590cda9deb85e86296

また、GAS スクリプトプロパティに LINE_USER_ID を追加する.
LINE の プッシュ通知には、友達追加済みの既知の LINE USER ID が必要.

コードを作成したら、それをウェブアプリケーションとして公開し、URL を取得する.

do-post.gs
const AccessToken = PropertiesService // LINE_ACCESS_TOKEN スクリプトプロパティ
  .getScriptProperties().getProperty("LINE_ACCESS_TOKEN");
const LineUserId = PropertiesService // LINE_USER_ID スクリプトプロパティ
  .getScriptProperties().getProperty("LINE_USER_ID");

function doPost(e) {
  if (e === undefined) return;

  const LnClient = new LineBotSDK // API Client 作成
    .Client({ channelAccessToken: AccessToken });

    const contents = JSON.parse(e.postData.contents);

    const mailData = contents.content;
    LnClient.pushMessage(LineUserId, { // POST 送信
      'type': 'text',
      'text': `
        ${mailData.from}\n
        ーーーーーーーーーーーーーーー\n
        ${mailData.subject}\n
        ーーーーーーーーーーーーーーー
        ${mailData.body}`
    });

    return;
}

ちなみに、上記のコードは、LINE Developpers の Webhook 検証に失敗する.
しかし、通知はできるので OK.

4. Express サーバ

ソースコードはこちら. これを GCE で 起動しておく. (初期は Port 3000)
エンドポイントに POST があれば、gemini-api.js でプロンプトを送信. その返答を前項で作成した GAS ウェブアプリケーション の URL に POST するシステム.
URL 等は適宜変更が必要.
https://github.com/bbsfish/gemini-bot-server

Discussion