← back to Sample Followup Sweep

lib/pre-send-gate.js

120 lines

'use strict';

const parse5 = require('parse5');

const REQUIRED_FROM = 'info@designerwallcoverings.com';
const ADDRESS_PATTERN = /15442\s+Ventura\s+Blvd(?:\.|\s)*(?:#|Suite)?\s*102[\s\S]*Sherman\s+Oaks,?\s*CA\s+91403/i;
const MISLEADING_SUBJECT_PATTERN = /\b(?:re|fw|fwd)\s*:/i;
const NON_RENDERED_ELEMENTS = new Set(['script', 'style', 'template', 'noscript', 'head', 'svg', 'canvas']);

function decodeHtmlEntities(value) {
  return String(value || '')
    .replace(/ | | /gi, ' ')
    .replace(/&/gi, '&')
    .replace(/&lt;/gi, '<')
    .replace(/&gt;/gi, '>')
    .replace(/&quot;/gi, '"')
    .replace(/&#39;|&apos;/gi, "'")
    .replace(/&#(\d+);/g, (_, code) => String.fromCodePoint(Number(code)))
    .replace(/&#x([0-9a-f]+);/gi, (_, code) => String.fromCodePoint(parseInt(code, 16)));
}

function attrs(node) {
  return Object.fromEntries((node.attrs || []).map(({ name, value }) => [name.toLowerCase(), value]));
}

function isHiddenElement(node) {
  if (!node.tagName) return false;
  const tag = node.tagName.toLowerCase();
  if (NON_RENDERED_ELEMENTS.has(tag)) return true;
  const attributes = attrs(node);
  if (Object.hasOwn(attributes, 'hidden')) return true;
  if (String(attributes['aria-hidden'] || '').trim().toLowerCase() === 'true') return true;
  if (tag === 'input' && String(attributes.type || '').trim().toLowerCase() === 'hidden') return true;
  const style = String(attributes.style || '')
    .replace(/\/\*[\s\S]*?\*\//g, '')
    .replace(/\s+/g, '')
    .toLowerCase();
  return /(?:^|;)display:none(?:!important)?(?:;|$)/.test(style)
    || /(?:^|;)visibility:hidden(?:!important)?(?:;|$)/.test(style);
}

function renderedContent(body) {
  const fragment = parse5.parseFragment(String(body || ''));
  const text = [];
  const anchors = [];
  function visit(node, hidden = false, activeAnchor = null) {
    const nowHidden = hidden || isHiddenElement(node);
    if (!nowHidden && node.nodeName === '#text') {
      const value = node.value || '';
      text.push(value);
      if (activeAnchor) activeAnchor.text.push(value);
    }
    let childAnchor = activeAnchor;
    if (!nowHidden && String(node.tagName || '').toLowerCase() === 'a') {
      const href = attrs(node).href;
      if (href) {
        childAnchor = { href: href.trim(), text: [] };
        anchors.push(childAnchor);
      }
    }
    for (const child of node.childNodes || []) visit(child, nowHidden, childAnchor);
    if (node.content) visit(node.content, true, null);
  }
  visit(fragment);
  return {
    visibleText: text.join(' ').replace(/\s+/g, ' ').trim(),
    anchors: anchors.map(({ href, text: label }) => ({ href, visibleLabel: label.join(' ').replace(/\s+/g, ' ').trim() })),
  };
}

function visibleTextFromHtml(body) {
  return renderedContent(body).visibleText;
}

function isCanonicalOptOutMailto(url) {
  if (url.protocol !== 'mailto:' || url.hash) return false;
  let recipient;
  try { recipient = decodeURIComponent(url.pathname); } catch { return false; }
  if (recipient.toLowerCase() !== REQUIRED_FROM) return false;
  const entries = [...url.searchParams.entries()];
  if (entries.length !== 1 || entries[0][0] !== 'subject') return false;
  const subject = entries[0][1];
  if (!subject || /[\r\n\0]/.test(subject)) return false;
  return /(?:unsubscribe|opt\s*out|stop\s+receiving)/i.test(subject);
}

function hasWorkingOptOutLink(body) {
  const { anchors } = renderedContent(body);
  return anchors.some(({ href, visibleLabel }) => {
    try {
      if (!/(?:unsubscribe|opt\s*out|stop\s+receiving)/i.test(visibleLabel)) return false;
      const url = new URL(href);
      if (url.protocol === 'mailto:') return isCanonicalOptOutMailto(url);
      // No canonical DW-hosted unsubscribe endpoint is registered yet. Fail closed
      // instead of treating an attacker-controlled HTTPS URL as a working opt-out.
      return false;
    } catch {
      return false;
    }
  });
}

function assertPreSendCompliance({ from, subject, body }) {
  const errors = [];
  if (String(from || '').trim().toLowerCase() !== REQUIRED_FROM) errors.push(`From must be ${REQUIRED_FROM}`);
  if (!String(subject || '').trim()) errors.push('Subject is required');
  if (MISLEADING_SUBJECT_PATTERN.test(String(subject || ''))) errors.push('Subject must not imply a reply or forward');
  if (!ADDRESS_PATTERN.test(visibleTextFromHtml(body))) errors.push('Body must include the DW physical postal address in visible content');
  if (!hasWorkingOptOutLink(body)) errors.push('Body must include a working unsubscribe or opt-out link');
  if (errors.length) {
    const error = new Error(`PRE-SEND COMPLIANCE GATE BLOCKED: ${errors.join('; ')}`);
    error.code = 'PRE_SEND_COMPLIANCE_BLOCKED';
    error.reasons = errors;
    throw error;
  }
  return true;
}

module.exports = { assertPreSendCompliance, hasWorkingOptOutLink, isCanonicalOptOutMailto, renderedContent, visibleTextFromHtml, REQUIRED_FROM };