← 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
M src/pr/adapters/website.js
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 →