/**
 * Emerge Mail — Gmail bounce forwarder.
 *
 * Gmail doesn't push webhooks, so delivery failures arrive as "Mail Delivery
 * Subsystem" (DSN) messages in this mailbox. This script scans for them and
 * forwards a normalized summary to your WordPress site's Emerge Mail endpoint,
 * which records each one in the Activity Log and fires the bounce action.
 *
 * Your site's secret token is already baked into the URL below.
 *
 * SETUP (one time, ~1 minute):
 *   1. Go to https://script.google.com → New project.
 *   2. Delete the sample code, paste this whole file, and Save.
 *   3. Pick `emergeSetup` in the function dropdown and click Run.
 *      Approve the Gmail permission when asked (it's your own script, so
 *      click through the "unverified" notice).
 *
 * That's it — `emergeSetup` installs a recurring trigger for you, so there's
 * no need to add one by hand. Bounces will start appearing in your Activity
 * Log within a few minutes.
 */

var EMERGE_WEBHOOK_URL       = '__EMERGE_WEBHOOK_URL__';
var EMERGE_TRIGGER_MINUTES   = 15;                          // how often to run (allowed: 1, 5, 10, 15, 30)
var EMERGE_LOOKBACK_INTERVAL = EMERGE_TRIGGER_MINUTES + 5;  // minutes scanned each run (trigger + 5 min buffer)
var EMERGE_LABEL             = 'EmergeMailProcessed';       // applied so nothing is sent twice
var EMERGE_MAX_THREADS       = 50;                          // per run

/**
 * Run this once. It (re)installs the time-driven trigger and then does a first
 * pass immediately. Safe to re-run — it clears any previous trigger first.
 */
function emergeSetup() {
  ScriptApp.getProjectTriggers().forEach(function (trigger) {
    if (trigger.getHandlerFunction() === 'emergeForwardBounces') {
      ScriptApp.deleteTrigger(trigger);
    }
  });

  ScriptApp.newTrigger('emergeForwardBounces')
    .timeBased()
    .everyMinutes(EMERGE_TRIGGER_MINUTES)
    .create();

  emergeForwardBounces();
}

function emergeForwardBounces() {
  var label  = GmailApp.getUserLabelByName(EMERGE_LABEL) || GmailApp.createLabel(EMERGE_LABEL);
  // Gmail search only does day-granularity for newer_than:, so use an epoch
  // cutoff (after: accepts a Unix timestamp) to scan just the last interval.
  var cutoff = Math.floor((Date.now() - EMERGE_LOOKBACK_INTERVAL * 60 * 1000) / 1000);
  var query  = 'from:mailer-daemon after:' + cutoff + ' -label:' + EMERGE_LABEL;
  var threads = GmailApp.search(query, 0, EMERGE_MAX_THREADS);
  if (!threads.length) { return; }

  var mailbox = Session.getActiveUser().getEmail();
  var events = [];

  threads.forEach(function (thread) {
    thread.getMessages().forEach(function (msg) {
      var parsed = emergeParseBounce_(msg);
      if (parsed) { events.push(parsed); }
    });
    thread.addLabel(label);
  });

  if (!events.length) { return; }

  UrlFetchApp.fetch(EMERGE_WEBHOOK_URL, {
    method: 'post',
    contentType: 'application/json',
    muteHttpExceptions: true,
    payload: JSON.stringify({ emerge_source: 'gmail', mailbox: mailbox, events: events })
  });
}

/**
 * Pull the failed recipient + status out of an RFC 3464 delivery-status report.
 * Returns null for anything that isn't a clear failure.
 */
function emergeParseBounce_(msg) {
  var raw = msg.getRawContent();

  var action = (raw.match(/Action:\s*(\w+)/i) || [])[1] || '';
  if (action.toLowerCase() !== 'failed') { return null; }

  var rcpt = (raw.match(/Final-Recipient:\s*[^;]+;\s*([^\s]+)/i) || [])[1] || '';
  if (!rcpt) { return null; }

  var status = (raw.match(/Status:\s*([245]\.\d+\.\d+)/i) || [])[1] || '';
  var diag   = (raw.match(/Diagnostic-Code:\s*(.+)/i) || [])[1] || '';

  // The DSN quotes the original message's headers after the delivery-status
  // part, so the LAST Subject:/Message-ID: lines are the original's (the first
  // belong to the daemon's own "Delivery Status Notification"). The Message-ID
  // matches the one Emerge Mail stamped at send, so the bounce links straight
  // back to the original; the subject is the human-readable fallback.
  var subjects = raw.match(/^Subject:\s*(.+)$/gim) || [];
  var subject  = subjects.length ? subjects[subjects.length - 1].replace(/^Subject:\s*/i, '').trim() : '';

  var ids       = raw.match(/^Message-ID:\s*(<[^>]+>)/gim) || [];
  var messageId = ids.length ? ids[ids.length - 1].replace(/^Message-ID:\s*/i, '').trim() : '';

  return {
    email:       rcpt.replace(/[<>]/g, '').trim(),
    disposition: status.charAt(0) === '5' ? 'hard' : 'soft',
    message_id:  messageId,
    subject:     subject,
    reason:      (diag || status).trim()
  };
}
