[object Object]

← back to Rentv 2026

pr/website: shared isJunkContactEmail() filter for BOTH extractors — extractPressContacts had NO junk filter (proven: it stored 'photo@2x.png' / 'noreply@firm.com' as press emails, skipping the real one), and extractPeople's inline filter missed no-reply/.gif/.svg/.webp/.jpeg. Both now pick the first NON-junk email per block (a junk match no longer blocks the real one). Verified junk skipped, real+press@ emails preserved

d308a6f1d5c7529996b1e56165a556c755fa9e02 · 2026-08-05 20:25:23 -0700 · Steve

Files touched

Diff

commit d308a6f1d5c7529996b1e56165a556c755fa9e02
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Aug 5 20:25:23 2026 -0700

    pr/website: shared isJunkContactEmail() filter for BOTH extractors — extractPressContacts had NO junk filter (proven: it stored 'photo@2x.png' / 'noreply@firm.com' as press emails, skipping the real one), and extractPeople's inline filter missed no-reply/.gif/.svg/.webp/.jpeg. Both now pick the first NON-junk email per block (a junk match no longer blocks the real one). Verified junk skipped, real+press@ emails preserved
---
 src/pr/adapters/website.js | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/pr/adapters/website.js b/src/pr/adapters/website.js
index ae6ac755..591b9753 100644
--- a/src/pr/adapters/website.js
+++ b/src/pr/adapters/website.js
@@ -20,6 +20,12 @@ const PAGE_HINTS = {
 const EMAIL_RE = /\b[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}\b/gi;
 const PRESSY_EMAIL = /press|media|pr@|news|communications|comms/i;
 const PHONE_RE = /\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}/g;
+// A string that PASSES the email FORMAT check but is NOT a usable human contact — image
+// filenames mistaken as emails ("photo@2x.png"), tracking/CMS addresses, and no-reply system
+// mailboxes. Used by BOTH extractors so press + team pages filter consistently.
+function isJunkContactEmail(em) {
+  return /example\.|sentry|wixpress|schema\.org|googleapis|\.(png|jpe?g|gif|svg|webp)(\b|$)|@2x|\bno[-.]?reply\b|\bdo[-.]?not[-.]?reply\b/i.test(String(em || ''));
+}
 
 function absolutize(href, base) {
   try { return new URL(href, base).toString(); } catch { return null; }
@@ -70,14 +76,13 @@ function extractPeople(html, opts = {}) {
   const INLINE_RE = /^([A-Z][a-z]+(?:\s+[A-Z]\.?)?(?:\s+[A-Z][a-z'’-]+){1,2})\s*[,|–—-]\s+(.{3,90})$/;
   // nav/boilerplate lines that are not a job title (only used to gate the allTeam pass)
   const NOT_TITLE = /^(read more|view|see all|subscribe|sign ?in|sign ?up|log ?in|newsletter|menu|search|share|follow|contact|home|about|privacy|terms|cookie|advertise|copyright|©|all rights|back to|next|previous|load more)/i;
-  const EMAIL1 = /[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}/i;
   const PHONE1 = /(?:\+?1[\s.-]?)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}/;
   // pull an email + phone from the person's block (their line + next 3)
   const blockContact = (idx) => {
     const blk = lines.slice(idx, idx + 4).join('  ');
     const out = {};
-    const em = (blk.match(EMAIL1) || [])[0];
-    if (em && !/example\.|sentry|wixpress|schema\.org|\.png|\.jpg|@2x/i.test(em)) out.public_work_email = em.toLowerCase();
+    const em = (blk.match(EMAIL_RE) || []).find((e) => !isJunkContactEmail(e)); // first REAL email in the block, skipping junk
+    if (em) out.public_work_email = em.toLowerCase();
     const ph = (blk.match(PHONE1) || [])[0];
     if (ph) out.public_business_phone = ph.trim();
     return out;
@@ -133,8 +138,8 @@ function extractPressContacts(html, pageUrl) {
     for (let j = 1; j <= 8 && i + j < lines.length; j++) {
       const l = lines[i + j];
       if (MARKER.test(l)) break;
-      const em = l.match(EMAIL_RE);
-      if (em && !email) email = normalizeEmail(em[0]);
+      const em = (l.match(EMAIL_RE) || []).find((e) => !isJunkContactEmail(e)); // skip image/tracking/no-reply junk
+      if (em && !email) email = normalizeEmail(em);
       const ph = l.match(PHONE_RE);
       if (ph && !phone) phone = ph[0];
       if (!full_name) {

← 270d4b18 auto-save: 2026-08-05T20:15:24 (7 files) — data/deals-regist  ·  back to Rentv 2026  ·  pr/website: Cody gate — (1) wire the THIRD email-scan (profi 0f85ba30 →