From 0f18d4c123b01d61f5e707093c8e7a196c2b3c4f Mon Sep 17 00:00:00 2001 From: Julien Herr Date: Mon, 25 May 2026 18:00:02 +0200 Subject: [PATCH] refactor(app): parse sender once via EmailAddress, drop infra reach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit email-processor parsed input.from twice — once via EmailAddress for the native-feed base, once via the favicon infra helper extractEmailDomain just to get the domain. CLAUDE.md forbids reaching across a layer to parse a domain: parse once and derive both siteBaseUrl() and domain.value from the EmailAddress VO, removing the infrastructure/favicon-fetcher import. Co-Authored-By: Claude Opus 4.7 --- src/application/email-processor.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/application/email-processor.ts b/src/application/email-processor.ts index e954415..039e3f8 100644 --- a/src/application/email-processor.ts +++ b/src/application/email-processor.ts @@ -3,7 +3,6 @@ import { EmailAddress } from "../domain/value-objects/email-address"; import { AttachmentData, EmailMetadata, Env } from "../types"; import { bumpCounters } from "../application/stats"; import { dispatchFeedEvents } from "../application/feed-events"; -import { extractEmailDomain } from "../infrastructure/favicon-fetcher"; import { parseOneClickUnsubscribe } from "../infrastructure/unsubscribe"; import { getAttachmentBucket } from "../infrastructure/attachments"; import { @@ -196,11 +195,9 @@ async function storeEmail( links: extractLinks(input.content), }); + const sender = EmailAddress.parse(input.from); const nativeFeedList = detectNativeFeeds( - extractFeedLinks( - input.content, - EmailAddress.parse(input.from)?.siteBaseUrl() ?? "", - ), + extractFeedLinks(input.content, sender?.siteBaseUrl() ?? ""), ); const attachmentBucket = getAttachmentBucket(env); @@ -247,7 +244,7 @@ async function storeEmail( // Track the latest sender's domain (feed icon) and capture the RFC 8058 // one-click unsubscribe link, keyed by sender so each newsletter keeps its // own latest URL (fired when the feed is deleted). - const iconDomain = extractEmailDomain(input.from); + const iconDomain = sender?.domain.value; const senderKey = input.senders[0] || iconDomain || input.from; const unsubUrl = parseOneClickUnsubscribe(input.headers ?? {}); const unsub = unsubUrl ? { senderKey, url: unsubUrl } : undefined;