見出し画像

Gmailで受信した数々のメールの中から目的の添付ファイルを探し出すGASを作る

 Gmailの検索機能はとても優秀で便利です。最近はGeminiも追加されて、メールのやり取りがとてもスムーズになっています。そんなGmailですが、個人的に悩んでいるのが、目的の添付ファイルを見つけ出すのに苦労することです。特に、メールのスレッドに隠れてしまった添付ファイル、メールのやり取りの中で、どれが最新のものなのかがわからなくなってしまった添付ファイルなど。私がGmailの使い方を熟知していないというのが原因だと思いますが…。
 そこで、目的の添付ファイルを探し出すGASを作って利用をしています。具体的には、Google スプレッドシートのサイドパネルを利用して目的のメールを探し出し、ファイルをダウンロードする、というものです。

Google スプレッドシートのメニューに「添付ファイル検索」を追加し、再度パネルに「添付ファイル検索」を呼び出します。検索窓に送信元に関する情報などのキーワードを入れれば、添付ファイルのあるメールを一覧にしくれます。検索結果は該当するメールへのリンクになっています。


 Gmailを上手く使いこなせている方であれば必要のないGASだと思いますが、私のようにうまく使いこせていない方にはそこそこ便利に使えると思います。


Gmail添付ファイルファインダー


その1: プロジェクトの作成とファイル構成

  1. Googleスプレッドシートを開く:

    • Googleドライブで新しいスプレッドシートを作成し、任意の名前(例:「Gmail検索アプリ」)をつけます。

  2. Apps Scriptエディタを開く:

    • スプレッドシートのメニューから「拡張機能」>「Apps Script」を選択し、スクリプトエディタを開きます。

  3. HTMLファイルを作成する:

    • エディタの左側にあるファイルアイコン(+)をクリックし、「HTML」を選択します。

    • ファイル名を Sidebar と入力して作成します。

これで、コード.gs(または 無題のファイル.gs)と Sidebar.html の2つのファイルが用意されました。


その2: コードの貼り付け

以下のコードを、それぞれ対応するファイルにすべてコピー&ペーストしてください。

2-1. コード.gs に貼り付けるコード(サーバー側ロジック)

このファイルは、Gmailの検索実行、サイドバーの表示、HTML側とのデータのやり取りを担当します。

// --- 1. スプレッドシートを開いたときにカスタムメニューを作成 ---
function onOpen() {
  // スプレッドシートのメニューバーに「📧 添付ファイル検索」という項目を追加
  SpreadsheetApp.getUi()
      .createMenu('📧 添付ファイル検索')
      .addItem('検索サイドバーを開く', 'showSidebar')
      .addToUi();
}

// --- 2. サイドバーを表示する関数 ---
function showSidebar() {
  const html = HtmlService.createTemplateFromFile('Sidebar')
      .evaluate()
      .setTitle('添付ファイル検索ツール');
  SpreadsheetApp.getUi().showSidebar(html);
}

// --- 3. 検索を実行し、結果をHTMLに返す関数 (サーバー側の処理) ---
function searchGmailAndReturnResults(searchTerm) {
  if (!searchTerm || searchTerm.trim() === '') {
    return { error: '検索語を入力してください。' };
  }

  // 検索クエリを作成 (送信元、または件名に検索語が含まれ、添付ファイルがあるもの)
  const searchQuery = `(from:${searchTerm} OR subject:${searchTerm}) has:attachment`;
  const MAX_RESULTS = 50; // 一度の検索で取得する最大スレッド数

  try {
    const threads = GmailApp.search(searchQuery, 0, MAX_RESULTS);
    const results = [];

    if (threads.length === 0) {
      return [];
    }

    threads.forEach(thread => {
      // 最新のメッセージを取得
      const messages = thread.getMessages();
      const latestMessage = messages[messages.length - 1]; 
      const attachments = latestMessage.getAttachments();
      
      if (attachments.length > 0) {
        const threadId = thread.getId();
        // リンクをクリックで開けるようにURLを格納
        const threadLink = `https://mail.google.com/mail/u/0/#all/${threadId}`;
        
        results.push({
          date: Utilities.formatDate(latestMessage.getDate(), Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm'),
          from: latestMessage.getFrom(),
          subject: latestMessage.getSubject(),
          attachmentCount: attachments.length,
          link: threadLink
        });
      }
    });
    
    return results; // 結果をHTML側のJavaScriptに返す

  } catch (e) {
    Logger.log('検索中にエラーが発生しました: ' + e.toString());
    return { error: '検索中にエラーが発生しました。スクリプトログを確認してください。' };
  }
}


2-2. Sidebar.html に貼り付けるコード(ユーザーインターフェース)

このファイルは、検索窓と検索結果の表示、ユーザー操作をGAS側に伝える処理を担当します。

<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <style>
    /* シンプルで見やすいデザイン */
    body { font-family: Roboto, sans-serif; margin: 10px; background-color: #f8f9fa; }
    input[type="text"], button { width: 100%; padding: 10px; margin-bottom: 12px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; }
    button { background-color: #1a73e8; color: white; border: none; cursor: pointer; font-weight: bold; }
    button:hover { background-color: #155bb5; }
    #results-area { margin-top: 15px; padding-top: 10px; }
    .result-row { background-color: #ffffff; border: 1px solid #e0e0e0; border-radius: 4px; padding: 10px; margin-bottom: 10px; font-size: 13px; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
    .result-subject { font-weight: bold; margin-bottom: 5px; }
    .error { color: #d93025; font-weight: bold; }
    #loading { text-align: center; color: #5f6368; padding: 10px; }
  </style>
</head>
<body>
  <h2>添付ファイル検索</h2>
  
  <input type="text" id="searchTerm" placeholder="送信元メールアドレスまたは名前を入力" onkeyup="if(event.key === 'Enter') runSearch()" />
  <button onclick="runSearch()">🔍 検索</button>

  <div id="loading" style="display:none;">検索中...しばらくお待ちください。</div>
  <div id="results-area"></div>

  <script>
    // サーバー側のGAS関数を呼び出す
    function runSearch() {
      const searchTerm = document.getElementById('searchTerm').value.trim();
      const loading = document.getElementById('loading');
      const resultsArea = document.getElementById('results-area');
      
      // UIをリセットし、ローディング表示
      resultsArea.innerHTML = '';
      loading.style.display = 'block';

      // GASの関数を実行し、成功/失敗時のコールバックを設定
      google.script.run
        .withSuccessHandler(displayResults)
        .withFailureHandler(handleFailure)
        .searchGmailAndReturnResults(searchTerm);
    }

    // 検索成功時に結果を表示
    function displayResults(results) {
      document.getElementById('loading').style.display = 'none';
      const resultsArea = document.getElementById('results-area');
      
      if (results.error) {
        resultsArea.innerHTML = `<p class="error">🚨 エラー: ${results.error}</p>`;
        return;
      }

      if (results.length === 0) {
        resultsArea.innerHTML = '<p>指定された条件に一致するメールは見つかりませんでした。</p>';
        return;
      }

      // 結果のリストを作成
      let html = `<h3>✅ 検索結果 (${results.length}件):</h3>`;
      results.forEach(item => {
        // スレッドリンクを<a>タグにして、クリックでGmailを開けるようにする
        html += `
          <div class="result-row">
            <div class="result-subject">
              <a href="${item.link}" target="_blank" title="Gmailで開く">${item.subject}</a>
            </div>
            <div>**送信元**: ${item.from}</div>
            <div>**日付**: ${item.date}</div>
            <div>**添付ファイル数**: ${item.attachmentCount}</div>
          </div>
        `;
      });

      resultsArea.innerHTML = html;
    }

    // 検索失敗時(GAS側で例外が発生など)の処理
    function handleFailure(error) {
      document.getElementById('loading').style.display = 'none';
      document.getElementById('results-area').innerHTML = '<p class="error">💥 サーバーエラーが発生しました。</p>';
      console.error(error);
    }
  </script>
</body>
</html>



その3: 初回実行と権限の承認

  1. 保存: スクリプトエディタ上部の保存ボタン(フロッピーディスクのアイコン)をクリックし、すべてのコードを保存します。

  2. GASの実行:

    • コード.gs を開いた状態で、関数選択ドロップダウンから showSidebar を選択します。

    • メニューバーの「実行」ボタン(▶アイコン)をクリックします。

  3. 権限の確認:

    • 初回実行時に「承認が必要です」というダイアログが表示されるので、「権限を確認」をクリックします。

  4. 権限の許可:

    • ご自身のGoogleアカウントを選択し、警告画面が表示された場合は「詳細」をクリックし、「(プロジェクト名)に移動」を選択して承認を進めます。

    • アクセス権(Gmailの閲覧、Google DriveでのUI操作など)をすべて確認し、「許可」をクリックして実行を完了させます。


その4: ツールを利用する

  1. サイドバーの表示:

    • 初回実行完了後、スプレッドシートに戻ると、画面右側にカスタムの「添付ファイル検索ツール」サイドバーが表示されます。

  2. 次回以降の起動:

    • スプレッドシートを**リロード(再読み込み)**すると、メニューバーに「📧 添付ファイル検索」という新しいカスタムメニューが追加されます。

    • 以降は、このメニューから「検索サイドバーを開く」を選択してツールを起動します。

  3. 検索の実行:

    • サイドバーの検索窓に、探したいメールの送信元メールアドレスまたは件名に含まれるキーワードを入力します。

    • 🔍 検索」ボタンをクリックすると、添付ファイル付きのメールが一覧表示され、リンクから直接Gmailの該当メールを開けます。


 以上です。添付ファイルを探し出すのに、わざわざGoogle スプレッドシートを開くとは…、と私も思いますが、現状ではこちらのGASを利用したほうが早く見つけることができるので、これで良しとしています。Gmailで早く見つけられる方は、このGASは不要です。できれば、私もGmailをもっと使いこなして、このGASを卒業できるようになりたいと思っています。