シュッと Gmail から Discord への通知

ちゃっす(/・ω・)/


最近無駄にポニョポニョしたツールを作ったりしているので備忘録的に残すのである(/・ω・)/


Gmail でサブスクしてるメールとか Discord に通知するぞ☆


な話。


必要なもの

  • Googleアカウント

  • Discordサーバーの管理権限


Discordウェブフックの設定をしますわよ

  • Discordサーバーの設定を開く

  • 「連携サービス」→「ウェブフック」を選ぶ

  • 新しいウェブフックを作成して、転送先のチャンネルを選択

  • ウェブフックURLをコピーして、安全な場所に保存


Google Apps Scriptプロジェクトを作成しますわよ

  • Google Apps Script にアクセス

  • 「新しいプロジェクト」をクリック

  • プロジェクト名は「Gmail to Discord Notifier」とか適当に付けちゃって


スクリプト

プロジェクトエディタでコピペでポン☆

function sendToDiscord() {
  var webhookUrl = PropertiesService.getScriptProperties().getProperty('DISCORD_WEBHOOK_URL');

  if (!webhookUrl) {
    Logger.log('Webhook URL is not set. Please set the DISCORD_WEBHOOK_URL property.');
    return;
  }

  var oneDayAgo = new Date();
  oneDayAgo.setHours(oneDayAgo.getHours() - 24);

  var searchQuery = 'label:To-Discord after:' + oneDayAgo.toISOString().split('T')[0];
  var threads = GmailApp.search(searchQuery, 0, 50);

  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();

    for (var j = 0; j < messages.length; j++) {
      var message = messages[j];
      sendEmailToDiscord(message, webhookUrl);
    }
  }
}

function sendEmailToDiscord(message, webhookUrl) {
  var subject = message.getSubject();
  var sender = message.getFrom();
  var body = message.getPlainBody();
  var receivedDate = message.getDate();

  // Shorten URLs in the body
  body = shortenUrls(body);

  var chunks = splitContent(body, 4000);

  for (var k = 0; k < chunks.length; k++) {
    var isFirstChunk = (k === 0);
    var isLastChunk = (k === chunks.length - 1);

    var discordMessage = {
      embeds: [{
        title: isFirstChunk ? subject : "",
        description: chunks[k],
        fields: isLastChunk ? [
          {
            name: "From",
            value: sender,
            inline: true
          },
          {
            name: "Received",
            value: receivedDate.toLocaleString(),
            inline: true
          },
          {
            name: "Status",
            value: message.isUnread() ? "Unread" : "Read",
            inline: true
          }
        ] : [],
        footer: {
          text: isLastChunk ? "Email ID: " + message.getId() : "Continued in next message..."
        }
      }]
    };

    var options = {
      'method': 'post',
      'contentType': 'application/json',
      'payload': JSON.stringify(discordMessage),
      'muteHttpExceptions': true
    };

    var response = UrlFetchApp.fetch(webhookUrl, options);

    if (response.getResponseCode() != 204 && response.getResponseCode() != 200) {
      Logger.log('Error sending to Discord. Status code: ' + response.getResponseCode() + '. Response: ' + response.getContentText());
    } else {
      Logger.log('Successfully sent message to Discord. Status code: ' + response.getResponseCode());
    }
  }
}

function splitContent(content, maxLength) {
  var chunks = [];
  while (content.length > 0) {
    if (content.length <= maxLength) {
      chunks.push(content);
      break;
    }

    var chunk = content.substr(0, maxLength);
    var lastNewline = chunk.lastIndexOf('\n');

    if (lastNewline > maxLength / 2) {
      chunk = content.substr(0, lastNewline);
    }

    chunks.push(chunk);
    content = content.substr(chunk.length);
  }
  return chunks;
}

function shortenUrls(text) {
  var urlRegex = /(https?:\/\/[^\s]+)/g;
  return text.replace(urlRegex, function (url) {
    if (url.length > 30) {  // Only shorten URLs longer than 30 characters
      var shortUrl = getTinyUrl(url);
      return shortUrl;
    }
    return url;
  });
}

function getTinyUrl(longUrl) {
  var tinyUrlApi = "http://tinyurl.com/api-create.php?url=" + encodeURIComponent(longUrl);
  var response = UrlFetchApp.fetch(tinyUrlApi);
  if (response.getResponseCode() == 200) {
    return response.getContentText();
  } else {
    Logger.log('Error shortening URL: ' + response.getContentText());
    return longUrl;  // Return the original URL if shortening fails
  }
}



Discord Webhook URL を設定しますわよ

  • スクリプトエディタで、歯車アイコンをクリックしてプロジェクト設定を開く

  • 「スクリプトプロパティ」セクションで新しいプロパティを追加

    • 名前: `DISCORD_WEBHOOK_URL`

    • 値: 手順1でコピーしたDiscordウェブフックURL



Gmail ラベルを作成しますわよ

  • Gmailを開いて、左サイドバーの「ラベルを作成」をクリック

  • 新しいラベル名は「To-Discord」にしてね☆

    • コード修正するならなんでもいいけど(/・ω・)/



Gmailフィルタの設定でござる

  • Gmailの検索ボックスの右側にある設定アイコンをクリック、「フィルタとブロック中のアドレス」を選択

  • 「新しいフィルタを作成」をクリック

  • 転送したいメールの条件を設定(例:特定の送信者やキーワード)

  • 「フィルタを作成」をクリック

  • 「ラベルを付ける」にチェックを入れて「To-Discord」を選択

  • 最後に「フィルタを作成」をクリックして保存



スクリプトのトリガー設定しますわよ

  • Apps Scriptエディタで、左サイドバーの時計アイコンをクリック

  • 「トリガーを追加」をクリック

  • 以下の設定をするーの:

    • 実行する関数を選択: `sendToDiscord`

    • 実行するデプロイを選択: 「Head」

    • イベントのソースを選択: 「時間主導型」

    • 時間ベースのトリガーのタイプを選択: 「日タイマー」

    • 時刻を選択: お好みでどぞ~(/・ω・)/

  • 「保存」をクリック☆


スクリプトのテストと確認をしますわよ

  • Apps Scriptエディタで、関数選択ドロップダウンから`sendToDiscord`を選んで、「実行」ボタンをクリックしてテスト

  • 初回実行時は、必要な権限を付与するプロンプトが表示されるから、指示に従ってね (/・ω・)/

  • Gmailで「To-Discord」ラベルを付けたテストメールを送信して、Discordチャンネルに通知が届くことを確認するのじゃ



スクリプトの説明とか注意点を書いてみたり

スクリプトの主な機能

  • メール取得: 「To-Discord」ラベルが付いた過去24時間以内のメールをゲッツ

  • URL短縮: 長いURLを自動的に短縮して、Discordで見やすくするのじゃ☆

  • Discord通知: 取得したメールの内容をDiscordチャンネルに送信☆

  • 長文対応: 長いメール本文を複数のメッセージに分割☆

注意点☆

  • 実行頻度: スクリプトは1日1回実行!頻度を増やすとAPIの制限に引っかかるかもでござるよ (/・ω・)/

  • URL短縮: 大体 URL がくそ長いので TinyURL というサービスで短くしておるので、機密情報には注意してね☆

  • 文字数制限: Discordのメッセージには文字数制限があるから、長文は分割して送るのじゃ(/・ω・)/

  • 添付ファイル: このスクリプトでは本文だけ転送ので添付ファイルは無視するぞ☆

  • エラーハンドリング: エラーはログに記録されるから、Apps Scriptの実行ログを定期的にチェックしてね☆

  • セキュリティ: Discord WebhookのURLはプロパティとして保存して他人に教えちゃダメよ(/・ω・)/

  • カスタマイズ: 必要に応じてスクリプトをカスタマイズしてくらはい (/・ω・)/

API制限とメンテナンス

  • API制限: なんでもそうだけど Gmail と Discord の API には使用制限があるから、大量の処理には注意が必要だぞ☆

  • メンテナンス: APIが変わるとスクリプトの更新が必要になることもあるから、定期的にチェックしてね(/・ω・)/

  • テスト: 大事なメールの転送を始める前に、テストメールでスクリプトを確認してね☆

カスタマイズのヒント

  • メールの件名や送信者でフィルタリングを追加するとか

  • Discordメッセージのフォーマットを変えて特定の情報を強調表示するとか

  • 複数のDiscordチャンネルに転送する場合、条件で異なるWebhook URLを使うとか

ご自由にどぞ~(/・ω・)/

トラブルシューティング

  • エラーが出たら、Apps Scriptの実行ログを見てね☆

  • Discordに送信できない場合は、Webhook URLが正しいかチェックしてね☆

  • スクリプトが動かない場合は、トリガーの設定を確認してね☆


こんな感じで Gmail を Discord に自動転送できますのよん(/・ω・)/


プレーンなテキストを LLM で書いてワタクシ風にリライトさせたかったけど雑にやったらびみょい感じだったので結局ほとんど手直しをしたという今日この頃(/・ω・)/


なんかノリでシュッと書いてるだけなので多分設定の説明漏れとかあるけど、まぁ、許してぴょん (/・ω・)/


なんか今回はシュッとしてない気がするがおしまい。


いいなと思ったら応援しよう!