Scoring — Email
mercury.score.score_email(link_emails: list[str], customer_emails: list[str]) -> float
Normalization
mercury.normalize.normalize_email lowercases and strips surrounding whitespace. No local-part canonicalization (no +tag stripping, no .-ignoring) — those belong in a later iteration.
Agreement rule
The score is 1.0 if any entry in link_emails normalizes to a value present in customer_emails; 0.0 otherwise. Exact match on the normalized string only — domain-only and local-part-only agreement are deliberately not credited in v1.
Candidate construction
The caller (mercury.match.evaluate) assembles customer_emails as the union of:
- every
user.emailon the Mercury company record; - the company’s
contactEmail.
This is what makes link 5 match: the link’s ram@example.fr doesn’t match the user’s ram@example.com, but it does match the company contactEmail. Treating every Mercury-known email as a candidate is essential.
Edge cases
- Empty link emails → 0.0.
- Empty candidates → 0.0 (defensive — shouldn’t happen in production).
- TLD-only mismatch (e.g.
ram@example.comvsram@example.fr) is a full 0.0 — the TLD is significant.
Combiner contribution
Weight: EMAIL_WEIGHT = 1.5 (see scoring-combiner). An email match alone does not clear the 2.5 threshold.