Gmailの配信解除リンクを開く前に確認|GASで候補メールをdry-run監査

Gmailの配信解除リンクを開く前に確認|GASで候補メールをdry-run監査

ツールおじ|GoogleアカウントをAIエージェント化

ツールおじ|GoogleアカウントをAIエージェント化

「不要なメルマガを減らしたい。でも、メール内の解除リンクを片っ端から開くのは不安」ということはありませんか。

この記事では、Gmailの標準的な `List-Unsubscribe` ヘッダーを読み取り、配信解除候補をドメイン別に集計します。解除URLへのアクセス、メール送信、削除、既読化、ラベル変更は一切行いません。 まず安全な候補だけを絞り、最終判断は人が行うための無料サンプルです。

このサンプルでできること・できないこと

  • Gmail検索で対象を最大30スレッドに限定します。
  • 配信解除用ヘッダーの有無と、HTTPS・メール送信・ワンクリック方式への対応を確認します。
  • 件名、本文、送信者の完全なメールアドレス、メッセージID、解除URLはログへ出しません。
  • 配信解除リンクは開かず、解除メールも送りません。
  • 正規の送信元か、解除してよい契約・通知かは自動判定しません。

配信解除ヘッダーがないメールや、サービス利用に必要な通知もあります。結果が出ても即実行せず、送信元の公式画面で契約状況を確認してください。

準備するもの

  1. Google Apps Scriptで新しいプロジェクトを作ります。
  2. 左側の「サービス」から Gmail API を追加します。
  3. 下のコードを貼り付けます。
  4. 最初は `QUERY` と `MAX_THREADS` を変えず、少量で試します。

検索条件は `category:promotions older_than:14d` です。受信トレイ全体ではなく、14日より前のプロモーション候補だけを確認します。

コピーして使える最小コード

const CONFIG = Object.freeze({
  DRY_RUN: true,
  QUERY: 'category:promotions older_than:14d',
  MAX_THREADS: 30,
  LOG_DETAILS: false
});

function auditGmailUnsubscribeHeadersFree() {
  validateConfig_();

  const threads = GmailApp.search(CONFIG.QUERY, 0, CONFIG.MAX_THREADS);
  const summaryByDomain = new Map();

  threads.forEach(thread => {
    const messages = thread.getMessages();
    if (!messages.length) return;

    // スレッド内の最新メッセージだけを確認する
    const message = messages[messages.length - 1];
    const metadata = Gmail.Users.Messages.get('me', message.getId(), {
      format: 'metadata',
      metadataHeaders: [
        'From',
        'List-Unsubscribe',
        'List-Unsubscribe-Post'
      ]
    });

    const headers = metadata.payload && metadata.payload.headers
      ? metadata.payload.headers
      : [];
    const fromHeader = getHeader_(headers, 'From');
    const unsubscribeHeader = getHeader_(headers, 'List-Unsubscribe');
    const unsubscribePostHeader = getHeader_(headers, 'List-Unsubscribe-Post');
    const domain = extractDomain_(fromHeader);

    const current = summaryByDomain.get(domain) || {
      domain,
      checked: 0,
      httpsHeader: 0,
      mailtoHeader: 0,
      oneClickHeader: 0,
      headerMissing: 0
    };

    current.checked += 1;
    if (!unsubscribeHeader) {
      current.headerMissing += 1;
    } else {
      if (/<https:\/\//i.test(unsubscribeHeader)) current.httpsHeader += 1;
      if (/<mailto:/i.test(unsubscribeHeader)) current.mailtoHeader += 1;
    }
    if (/list-unsubscribe=one-click/i.test(unsubscribePostHeader)) {
      current.oneClickHeader += 1;
    }

    summaryByDomain.set(domain, current);
  });

  const result = {
    status: 'REVIEW',
    dryRun: CONFIG.DRY_RUN,
    query: CONFIG.QUERY,
    checkedThreads: threads.length,
    domains: [...summaryByDomain.values()]
      .sort((a, b) => b.checked - a.checked)
  };

  // 件名・本文・完全なメールアドレス・解除URLは出力しない
  Logger.log(JSON.stringify(result));

  if (CONFIG.LOG_DETAILS === true) {
    Logger.log('注意: 詳細ログは実装していません。個人情報を追加しないでください。');
  }
}

function validateConfig_() {
  if (CONFIG.DRY_RUN !== true) {
    throw new Error('安全のためDRY_RUNはtrue固定です');
  }
  if (typeof CONFIG.QUERY !== 'string' || !CONFIG.QUERY.trim()) {
    throw new Error('QUERYを空欄にしないでください');
  }
  if (!Number.isInteger(CONFIG.MAX_THREADS) ||
      CONFIG.MAX_THREADS < 1 || CONFIG.MAX_THREADS > 30) {
    throw new Error('MAX_THREADSは1〜30で指定してください');
  }
}

function getHeader_(headers, name) {
  const target = headers.find(header =>
    String(header.name || '').toLowerCase() === name.toLowerCase()
  );
  return target ? String(target.value || '') : '';
}

function extractDomain_(fromHeader) {
  // 表示名や完全なメールアドレスは保持せず、ドメインだけ返す
  const match = String(fromHeader).toLowerCase()
    .match(/@([a-z0-9.-]+\.[a-z]{2,})/i);
  return match ? match[1] : 'unknown';
}

実行手順

  1. Apps Scriptの実行関数で `auditGmailUnsubscribeHeadersFree` を選びます。
  2. 初回だけGmailの読み取り権限を確認し、自分のテスト用アカウントで許可します。
  3. 「実行ログ」を開き、`checkedThreads` と `domains` を確認します。
  4. `oneClickHeader` や `httpsHeader` があるドメインでも、メール内リンクを自動では開きません。
  5. 継続不要と判断した配信だけ、送信元サービスの公式サイトや正規メールから手動で解除します。

ログの見方

  • `checked`: そのドメインで確認したスレッド数
  • `httpsHeader`: HTTPSの解除候補を持つ件数
  • `mailtoHeader`: 解除メール送信方式を持つ件数
  • `oneClickHeader`: ワンクリック解除の標準ヘッダーを持つ件数
  • `headerMissing`: 標準ヘッダーを確認できなかった件数

`headerMissing` は異常確定ではありません。また、ヘッダーがあっても送信元が安全だという保証にはなりません。見覚えのない送信元や不審なドメインはリンクを開かず、Gmailの迷惑メール報告など別の対応を検討してください。

失敗しやすい点と制限

  • Gmail APIを追加していないと `Gmail is not defined` になります。
  • Gmail検索の結果はアカウントの分類状況に左右されます。
  • 配信解除ヘッダーは任意のため、すべてのメールに存在するわけではありません。
  • 実行時間とGmail APIの利用上限があります。まず30件以下で確認してください。
  • 業務アカウントでは、管理者の権限設定により実行できない場合があります。
  • 重要通知、領収書、契約中サービスの連絡まで解除しないよう、人が最終確認してください。

公開前チェックリスト

  • [ ] `DRY_RUN` が `true` のまま
  • [ ] 対象がプロモーション候補か確認した
  • [ ] 件名・本文・完全なメールアドレス・解除URLをログへ追加していない
  • [ ] リンク自動アクセス、メール自動送信、削除、既読化を追加していない
  • [ ] 少量のテスト用アカウントで実行した
  • [ ] 最終解除は公式サイトまたは正規メールから手動で確認する

まとめ

不要メール対策は、いきなり解除リンクを自動実行するより、まず標準ヘッダーの有無を読み取り専用で確認する方が安全です。このコードは候補の集計までに限定し、Gmail上の状態は変えません。

定型メールを送信せずに下書きで確認したい方へ

GasおじのTips商品一覧を見る

※学習・検証用の例です。実データへ適用する前に、少量のテスト環境で権限とログを確認してください。Google公式・Google公認の商品ではありません。


あなたも記事の投稿・販売を
始めてみませんか?

Tipsなら簡単に記事を販売できます!
登録無料で始められます!

Tipsなら、無料ですぐに記事の販売をはじめることができます Tipsの詳細はこちら
 

この記事のライター

ツールおじ|GoogleアカウントをAIエージェント化

おう、Gasおじだ。 AIツールとSaaSに散々突っ込んで遠回りした結果、最後に強かったのは「今あるGoogleアカウント」だった。 今ではAIエージェントであらゆるタスクを自動化して無双してるぞ。 GAS、スプレッドシート、フォーム、Gmail、AIエージェントを組み合わせれば、個人でも小さな会社でも、手作業だらけの業務はかなり自動化できる。 ここでは机上のAI論じゃなく、現場で動くテンプレ、コード、手順だけを置いていくぞ。 高いツールを増やす前に、まずお前さんのGoogleアカウントを仕事するエージェントに変えようじゃないか。

このライターが書いた他の記事

  • Gmailの定型連絡を「送信せず」まとめて下書き化する|Gmail下書きテンプレGAS Pro

    ¥2,980
    2 %獲得
    (59 円相当)
  • 毎朝のToDoを区分・優先度・期限つきでまとめる Morning ToDo Mail Pro

    ¥2,980
    2 %獲得
    (59 円相当)
  • Googleフォームの採点ミスを回答公開前に発見|GASで正解キーをdry-run監査

関連のおすすめ記事

  • USBメモリで持ち運べるLinux Mint 22.1と永続的な書き込み領域の作成法【Rufus だけで作成する方法を初心者向けに徹底解説】

    ¥500
    2 %獲得
    (10 円相当)
    SmartSenior

    SmartSenior

  • Gmailの定型連絡を「送信せず」まとめて下書き化する|Gmail下書きテンプレGAS Pro

    ¥2,980
    2 %獲得
    (59 円相当)
    ツールおじ|GoogleアカウントをAIエージェント化

    ツールおじ|GoogleアカウントをAIエージェント化

  • 毎朝のToDoを区分・優先度・期限つきでまとめる Morning ToDo Mail Pro

    ¥2,980
    2 %獲得
    (59 円相当)
    ツールおじ|GoogleアカウントをAIエージェント化

    ツールおじ|GoogleアカウントをAIエージェント化