🧹

年末だからGmailをお掃除しよう

に公開

Unipos Advent Calendar 2025 23日目の記事です。

Uniposでプロダクト開発組織の組織開発を担当しているチャリです。

Gmailの容量がいっぱいです

様々なサービスを登録すると、沢山の通知やプロモーションが届きますよね。
僕はいちいちオプトアウトしていないせいでかなり溜まってしまっています。

gmailを開いたら、ついにこんなお知らせが表示されてました。

Googleのサービスはアカウント単位で容量を持つようです。
つまり、gmailもドライブも同じ容量を共有しているようですね。
考えてみれば当たり前ですが。

僕の場合は、ドライブとフォトがかなりの割合を占めてしまっていますが、メールも3GBも占有しています。

今回はメールを何とかします。

特にプロモーション系のメールには画像が含まれており、これがかなり食っているみたいです。

さぁ、お掃除しましょう。

お掃除タイム

エンジニアですし賢く効率的にやりましょうか。1つづつ選んで削除、なんてスマートじゃないですね。
また、今後のことも考えて自動で掃除してくれるようにしておきましょう。

戦略

メール容量を圧迫しない方法としては

  1. メールを削除する
  2. そもそも不要なメールを受信しない
    が考えられます。
    まずは1でごそっと削除しつつ、2番でオプトアウトしていきましょう。

メール削除はGoogle様が用意している便利な機能もありますが、
せっかくなので自動化しましょう。GASを使います。

  1. 不要なドメインをフィルタリング
  2. 条件にマッチしたメールに削除ラベルをつける
  3. 削除ラベルがついたメールを定期的に削除
    のワークフローを作成し定期的に実行させます。

これでも炙れてしまうメールが出てきたら不用ドメインを随時追加しましょう。

まずは容量の大きいメールを特定

メール容量が1MB以上のものを検索してみましょう。

以下クエリで検索ができます。

larger:1M

これをすべて一括で削除するのは怖いですね、、、
重要なメールも削除してしまうかもしれない。

続いて、送信者アドレスの一覧を出して見ましょう。
これはGmailの画面からは検索できないので、GASを使います。

function listLargeMailDomains() {
  const query = 'larger:1M has:attachment';
  const threads = GmailApp.search(query, 0, 500); // 最大500スレッド
  
  const domainCount = {};
  
  threads.forEach(thread => {
    thread.getMessages().forEach(msg => {
      const from = msg.getFrom(); 
      const match = from.match(/@([a-zA-Z0-9.-]+)/);
      if (!match) return;
      
      const domain = match[1].toLowerCase();
      domainCount[domain] = (domainCount[domain] || 0) + 1;
    });
  });

  const sheet = SpreadsheetApp.create('大容量メール_ドメイン一覧')
    .getActiveSheet();
  sheet.appendRow(['ドメイン', '件数']);

  Object.entries(domainCount)
    .sort((a, b) => b[1] - a[1])
    .forEach(([domain, count]) => {
      sheet.appendRow([domain, count]);
    });
}

出ました。

この中から本当に不要なドメインにラベルをつけましょう。

削除ラベルをつける


検索に条件を入力して「フィルタを作成」


ラベルを付けて、一致するスレッドにも適応する

削除する準備が整いました。

削除ラベルがついたメールを定期的に削除

削除のスクリプト全体像。

function deleteMail() {
  let date = new Date();
  date.setDate(date.getDate() - 7);

  
  const getFilterdThreadList = () => {
     // 削除予定ラベルのついたメールを取得
    const labelObject = GmailApp.getUserLabelByName('削除予定');
    const labeledThreadList = labelObject.getThreads();
    
    return labeledThreadList.filter(thread => date > thread.getLastMessageDate() && !thread.hasStarredMessages());
  }

  const deleteThread = (retryCount) => {
    if(retryCount < 3){
      try{
        // 削除予定ラベルのついたメールを取得
        const labelObject = GmailApp.getUserLabelByName('削除予定');
        const labeledThreadList = labelObject.getThreads();

        // 削除対象に絞り込み
        const targetThreadList = labeledThreadList.filter(thread => date > thread.getLastMessageDate() && !thread.hasStarredMessages());

        console.log(`${targetThreadList.length}件のスレッドを削除開始(${retryCount+1}回目)`);
        // 削除実行
        for(let i = 0; i < targetThreadList.length; i++){
          targetThreadList[i].moveToTrash();
        }
      }catch(e){
        console.error(e);
        deleteThread(retryCount+1);
      }
    }else{
      console.log(`終了`);
    }
  }

  deleteThread(0);
}

削除ラベルを検索

const getFilterdThreadList = () => {
     // 削除予定ラベルのついたメールを取得
    const labelObject = GmailApp.getUserLabelByName('削除予定');
    const labeledThreadList = labelObject.getThreads();
    
    return labeledThreadList.filter(thread => date > thread.getLastMessageDate() && !thread.hasStarredMessages());
  }

検索対象を削除。
たまに削除キューが詰まって失敗することも考慮して、
リトライカウントを設定し再帰的に実行できるようにしています。

const deleteThread = (retryCount) => {
    if(retryCount < 3){
      try{
        // 削除予定ラベルのついたメールを取得
        const labelObject = GmailApp.getUserLabelByName('削除予定');
        const labeledThreadList = labelObject.getThreads();

        // 削除対象に絞り込み
        const targetThreadList = labeledThreadList.filter(thread => date > thread.getLastMessageDate() && !thread.hasStarredMessages());

        console.log(`${targetThreadList.length}件のスレッドを削除開始(${retryCount+1}回目)`);
        // 削除実行
        for(let i = 0; i < targetThreadList.length; i++){
          targetThreadList[i].moveToTrash();
        }
      }catch(e){
        console.error(e);
        deleteThread(retryCount+1);
      }
    }else{
      console.log(`終了`);
    }
  }

GASは1実行あたり6分の実行時間が許可されています。
これを超えるとタイムアウトするようになっています。
削除対象が多いとタイムアウトしてしまうので、定期実行できるようにしましょう。


左タブから時計マーク、トリガーを追加

時間主導型で感覚はお好みで登録してください。

結果

2GBほど減らせました。
良きGoogleライフを〜

Unipos Tech Blog

Discussion