Email Risk Scoring Explained
Email risk scoring works by summing weighted "signals" — specific, observable facts like a disposable domain, a missing MX record, or an SMTP-confirmed rejection — into a 0–100 score, then mapping that score to a decision band (allow/review/block). Context (signup, B2B lead, payment, etc.) multiplies specific signal weights up or down before the sum happens, and a separate confidence value tracks how much real evidence backed the score.
It's a sum of named signals, not a black-box model
Every risk score here traces back to a fixed list of named signals, each with a base weight. There's no opaque machine-learning score you can't interrogate — every point in the final number came from a signal that's returned in the response alongside a plain-language description of what it means.
| Signal | Base weight | Category |
|---|---|---|
| invalid_syntax | 100 | email_quality |
| smtp_confirmed_invalid | 90 | deliverability |
| domain_not_found | 70 | domain |
| disposable_domain | 60 | disposable |
| no_mx_record | 50 | domain |
| random_local_part | 25 | email_quality |
| low_domain_reputation | 20 | reputation |
| new_domain | 18 | reputation |
| typo_detected / catch_all_domain / keyboard_pattern / repeated_fragment | 15 each | mixed |
| role_based_address | 10 | email_quality |
| missing_spf | 8 | domain |
| excessive_numbers / repeated_characters | 8 each | email_quality |
| missing_dmarc | 5 | domain |
| smtp_unknown | 5 | deliverability |
| free_provider | 3 | provider |
Only signals that actually apply get triggered — a syntactically valid address on an established, reputable domain with SPF/DMARC present and a confirmed mailbox can legitimately score 0. The weights are additive and capped at 100; there's no multiplicative stacking beyond the context adjustment described below.
A worked example
Take an address on a domain registered three weeks ago, with no SPF record, and a local part like a1b2c3x9@domain.com that the local-part analyzer flags as excessive-numbers. In the generic context:
- new_domain: 18
- low_domain_reputation: 20 (domain age feeds directly into the reputation composite)
- missing_spf: 8
- excessive_numbers: 8
- smtp_unknown: 5 (SMTP wasn't run — mode was standard, not full)
Total: 59 → medium band → review decision. Note that no single signal here is severe on its own; the score is a case where several small, independent weak signals accumulate into something worth a second look, which is exactly the scenario a rules-based sum is good at catching and a single pass/fail check would miss entirely.
How context changes the same signals
The context parameter doesn't add new signals — it multiplies the weight of specific existing ones before they're summed. A few real examples:
| Context | Multiplier applied |
|---|---|
| signup | disposable_domain ×1.15, random_local_part / excessive_numbers / repeated_characters / repeated_fragment / keyboard_pattern ×1.3, new_domain ×1.4 |
| b2b_lead | role_based_address ×2.5, free_provider ×2, low_domain_reputation ×1.3 |
| crm | role_based_address ×2, free_provider ×1.8, low_domain_reputation ×1.2 |
| marketplace | disposable_domain ×1.2, random_local_part-family signals ×1.15–1.2, low_domain_reputation ×1.2, new_domain ×1.2 |
| payment | no adjustment — same weights as generic |
Take a role-based address (sales@company.com) with no other issues: in the generic context it contributes 10 points (usually a low-risk outcome). In the b2b_lead context, that same signal contributes 25 points (10 × 2.5) — enough on its own to push a lead into the review band. The address didn't change; what "risky" means for that specific form did.
Confidence is calculated separately from the score
Confidence answers a different question than the score: how much real evidence was actually gathered? It starts at a baseline, and moves based on what evidence was available — live DNS/MX data present adds confidence, a fast-mode check with no cached DNS data available at all subtracts confidence, and a confirmed SMTP result (accepted or rejected — the mailbox itself, not just the domain) adds more than any other single factor, because it's the only signal that speaks to the specific mailbox rather than the domain as a whole. An invalid-syntax result is a special case — confidence there is deliberately near-certain in either direction, because syntax is unambiguous.
The result is capped to a 0.3–0.9 range on purpose. Even a fully-confirmed case — live DNS, healthy MX/SPF/DMARC, SMTP-confirmed mailbox — doesn't read as near-certainty, because strong evidence that a domain is legitimate and a mailbox exists is not proof that the person submitting it is trustworthy.
Why explainability is the actual point
A support team investigating a disputed block, or an engineer tuning which decisions get auto-approved, needs to see why a score landed where it did. Every signal returned includes a severity (low/medium/high/critical), a point impact, and a plain description — so "why was this blocked" is always answerable from the API response itself, not from re-running an opaque model and hoping for the same output twice.
FAQ
Yes, if they're checked with different context values, or if DNS/domain conditions changed between checks (a domain's age, reputation, or SPF/DMARC status can change over time).
No — it means no configured risk signal was triggered given the evidence gathered. It's the absence of red flags, not a positive identity guarantee.
Base weights are fixed, but context multipliers change the effective contribution. A signal's "weight" and its "impact in a specific response" are only the same number in the generic context.
No. Spam scoring typically evaluates message content and sending reputation. Email risk scoring here evaluates the address itself — independent of any message being sent.