DNS-based Email Service Provider (ESP) detection library
Project description
sufyaanmx
DNS-based Email Service Provider (ESP) detection library.
Given a domain, sufyaanmx returns every detected ESP, a per-provider
confidence score, and the raw DNS signals that drove each decision.
Features
- Detects 14+ ESP providers out of the box (Google Workspace, Microsoft 365, SendGrid, Mailgun, Amazon SES, Postmark, Zoho, Mimecast, Proofpoint, HubSpot, Klaviyo, Brevo, Mailchimp/Mandrill, Fastmail)
- Recursive SPF include resolution (depth-limited, loop-safe)
- Structured, typed output via dataclasses — no raw dicts
- Multiple providers can be returned per domain
- Additive confidence scoring: MX hit (+0.6) + SPF hit (+0.4), capped at 1.0
- Fault-tolerant: DNS failures and invalid domains degrade gracefully
- Easily extensible fingerprint registry
- Single external dependency:
dnspython
Installation
pip install sufyaanmx
Or install from source:
git clone https://github.com/sufyaan-t/sufyaanmx.git
cd sufyaanmx
pip install -e .
Quick Start
from sufyaanmx import detect, bulk_detect
# Single domain
result = detect("example.com")
print(result.domain) # "example.com"
print(result.providers) # ["Google Workspace"] ← sorted by confidence
print(result.confidence) # 1.0
print(result.signals) # {"mx_records": [...], "spf_record": "...", ...}
# Bulk
results = bulk_detect(["github.com", "stripe.com", "mailchimp.com"])
for r in results:
print(r.domain, r.providers, r.confidence)
Output Model
@dataclass
class DetectionResult:
domain: str
providers: List[str] # sorted by confidence descending
confidence: float # 0.0 – 1.0
signals: Dict[str, Any] # mx_records, spf_record, matched_fingerprints, ...
signals keys
| Key | Type | Description |
|---|---|---|
mx_records |
List[str] |
Raw MX hostnames resolved for the domain |
spf_record |
str | None |
Raw SPF TXT record, if found |
spf_includes |
List[str] |
All recursively expanded SPF include domains |
matched_fingerprints |
List[dict] |
Per-provider match details (score, mx_matches, spf_matches) |
provider_scores |
Dict[str, float] |
Raw scores keyed by provider name |
Scoring Logic
| Signal | Weight |
|---|---|
| MX hostname matches a fingerprint pattern | +0.6 |
| SPF include/record matches a fingerprint pattern | +0.4 |
Scores are additive within a provider and capped at 1.0. Multiple providers can be returned.
Extending Fingerprints
Add entries to sufyaanmx/fingerprints.py:
FINGERPRINTS["My Custom ESP"] = {
"mx": ["mail.myesp.com"],
"spf": ["spf.myesp.com"],
}
Project Structure
sufyaanmx/
├── __init__.py # Public API surface
├── core.py # Detection orchestration
├── dns.py # DNS resolution layer (dnspython)
├── fingerprints.py # ESP fingerprint registry
├── models.py # DetectionResult, ProviderMatch dataclasses
├── spf.py # SPF parsing & recursive include resolution
├── utils.py # Domain validation, clamping helpers
└── exceptions.py # Custom exception hierarchy
Author
Sufyaan T
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sufyaanmx-0.1.0.tar.gz.
File metadata
- Download URL: sufyaanmx-0.1.0.tar.gz
- Upload date:
- Size: 11.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ad76ca30f36f2f2c30d6aa4a12f34541d29a8dbc6ab5bad42f6a86335742ef9
|
|
| MD5 |
cbfa2156e1fb4359329e32bfc4cf3201
|
|
| BLAKE2b-256 |
35236558d4382c7592e435afbb288add1bd0bcc92d6856f2564e67879a8e582d
|
File details
Details for the file sufyaanmx-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sufyaanmx-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1171156fefb56fd9e6af819108f7c7883c13077ae3db77e96f9c2dc9788eff5
|
|
| MD5 |
6f0d2a9349433e593cec7f7b9ff86d69
|
|
| BLAKE2b-256 |
cbd88883ee91b0489f674590c3920397bd32f89233b62f49e9401b7353b3cdd9
|