Upload folder using huggingface_hub
Browse files- app/validator/mx_intel.py +23 -1
- tests/test_trusted_mx.py +60 -0
app/validator/mx_intel.py
CHANGED
|
@@ -30,8 +30,11 @@ _MX_PATTERNS: tuple[tuple[str, str, bool, bool], ...] = (
|
|
| 30 |
("office365.com", "microsoft365", True, False),
|
| 31 |
("mimecast.com", "mimecast", True, False),
|
| 32 |
("pphosted.com", "proofpoint", True, False),
|
|
|
|
| 33 |
("proofpoint.com", "proofpoint", True, False),
|
| 34 |
("barracudanetworks.com", "barracuda", True, False),
|
|
|
|
|
|
|
| 35 |
("yahoodns.net", "yahoo", False, True),
|
| 36 |
("yahoo.com", "yahoo", False, True),
|
| 37 |
("aol.com", "yahoo", False, True),
|
|
@@ -42,6 +45,18 @@ _MX_PATTERNS: tuple[tuple[str, str, bool, bool], ...] = (
|
|
| 42 |
("protonmail.ch", "proton", False, True),
|
| 43 |
("proton.me", "proton", False, True),
|
| 44 |
("secureserver.net", "godaddy", False, False),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
("fastmail.com", "fastmail", False, True),
|
| 46 |
("messagingengine.com", "fastmail", False, True),
|
| 47 |
("yandex.net", "yandex", False, True),
|
|
@@ -88,12 +103,19 @@ _TRUSTED_MX_PROVIDERS = frozenset({
|
|
| 88 |
"google", # Google Workspace (paid for custom domains)
|
| 89 |
"microsoft365", # Microsoft 365 / Exchange Online
|
| 90 |
"mimecast", # enterprise email security gateway
|
| 91 |
-
"proofpoint", # enterprise
|
| 92 |
"barracuda", # enterprise email security gateway
|
|
|
|
|
|
|
| 93 |
"zoho", # Zoho Mail (paid for custom domains)
|
| 94 |
"proton", # Proton Business
|
| 95 |
"fastmail", # Fastmail (paid custom domain)
|
| 96 |
"apple", # iCloud+ Custom Email Domain
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
})
|
| 98 |
|
| 99 |
|
|
|
|
| 30 |
("office365.com", "microsoft365", True, False),
|
| 31 |
("mimecast.com", "mimecast", True, False),
|
| 32 |
("pphosted.com", "proofpoint", True, False),
|
| 33 |
+
("ppe-hosted.com", "proofpoint", True, False),
|
| 34 |
("proofpoint.com", "proofpoint", True, False),
|
| 35 |
("barracudanetworks.com", "barracuda", True, False),
|
| 36 |
+
("mailchannels.net", "mailchannels", True, False),
|
| 37 |
+
("emailsecurity.app", "emailsecurity", True, False),
|
| 38 |
("yahoodns.net", "yahoo", False, True),
|
| 39 |
("yahoo.com", "yahoo", False, True),
|
| 40 |
("aol.com", "yahoo", False, True),
|
|
|
|
| 45 |
("protonmail.ch", "proton", False, True),
|
| 46 |
("proton.me", "proton", False, True),
|
| 47 |
("secureserver.net", "godaddy", False, False),
|
| 48 |
+
("registrar-servers.com", "namecheap", False, False),
|
| 49 |
+
("ionos.com", "ionos", False, False),
|
| 50 |
+
("1and1.com", "ionos", False, False),
|
| 51 |
+
("serverdata.net", "serverdata", False, False),
|
| 52 |
+
("hostgator.com", "hostgator", False, False),
|
| 53 |
+
("bluehost.com", "bluehost", False, False),
|
| 54 |
+
("siteground.com", "siteground", False, False),
|
| 55 |
+
("dreamhost.com", "dreamhost", False, False),
|
| 56 |
+
("networksolutions.com", "netsol", False, False),
|
| 57 |
+
("rackspace.com", "rackspace", False, False),
|
| 58 |
+
("emailsrvr.com", "rackspace", False, False),
|
| 59 |
+
("workmail.com", "amazon", False, False),
|
| 60 |
("fastmail.com", "fastmail", False, True),
|
| 61 |
("messagingengine.com", "fastmail", False, True),
|
| 62 |
("yandex.net", "yandex", False, True),
|
|
|
|
| 103 |
"google", # Google Workspace (paid for custom domains)
|
| 104 |
"microsoft365", # Microsoft 365 / Exchange Online
|
| 105 |
"mimecast", # enterprise email security gateway
|
| 106 |
+
"proofpoint", # enterprise + Essentials gateway (pphosted/ppe-hosted)
|
| 107 |
"barracuda", # enterprise email security gateway
|
| 108 |
+
"mailchannels", # mail infrastructure for hosting providers (paid)
|
| 109 |
+
"emailsecurity", # hosted email security gateway
|
| 110 |
"zoho", # Zoho Mail (paid for custom domains)
|
| 111 |
"proton", # Proton Business
|
| 112 |
"fastmail", # Fastmail (paid custom domain)
|
| 113 |
"apple", # iCloud+ Custom Email Domain
|
| 114 |
+
# Business hosting / mailbox providers: a paid, domain-verified account is
|
| 115 |
+
# required, so their customers are real businesses (observed in the user's
|
| 116 |
+
# 800-row export: ionos, namecheap, serverdata).
|
| 117 |
+
"godaddy", "namecheap", "ionos", "serverdata", "hostgator",
|
| 118 |
+
"bluehost", "siteground", "dreamhost", "netsol", "rackspace", "amazon",
|
| 119 |
})
|
| 120 |
|
| 121 |
|
tests/test_trusted_mx.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import unittest
|
| 2 |
+
|
| 3 |
+
from app.validator.mx_intel import mx_is_trusted
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class TrustedMxProviderTests(unittest.TestCase):
|
| 7 |
+
"""Direct coverage of the trusted-MX gate.
|
| 8 |
+
|
| 9 |
+
The gate decides whether the ML advisory may speak at all: a trusted host
|
| 10 |
+
means "paid business mail platform, disposable domains are implausible
|
| 11 |
+
here". Missing a real provider therefore re-introduces the exact false
|
| 12 |
+
positive the gate exists to prevent (a legitimate SMB flagged disposable).
|
| 13 |
+
|
| 14 |
+
Providers below were observed in the user's real 800-row export.
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
TRUSTED = [
|
| 18 |
+
# enterprise platforms
|
| 19 |
+
"aspmx.l.google.com", "alt3.aspmx.l.google.com", "smtp.google.com",
|
| 20 |
+
"aspmx2.googlemail.com",
|
| 21 |
+
"contoso-com.mail.protection.outlook.com",
|
| 22 |
+
# email-security gateways in front of corporate mail
|
| 23 |
+
"mx1-us1.ppe-hosted.com", "mx2-usg2.ppe-hosted.com",
|
| 24 |
+
"mx1.mailchannels.net", "mx1-us.emailsecurity.app",
|
| 25 |
+
# business hosting / mailbox providers (paid custom domains)
|
| 26 |
+
"mx00.ionos.com", "mx01.ionos.com",
|
| 27 |
+
"eforward1.registrar-servers.com", "eforward2.registrar-servers.com",
|
| 28 |
+
"west.smtp.mx.exch122.serverdata.net",
|
| 29 |
+
"mx.zoho.com", "mx1.fastmail.com", "mail.protonmail.ch",
|
| 30 |
+
"mx01.mail.icloud.com",
|
| 31 |
+
]
|
| 32 |
+
|
| 33 |
+
UNTRUSTED = [
|
| 34 |
+
# self-hosted / unknown MX: nowhere near enough signal to skip the model
|
| 35 |
+
"mail.abcoimport.com", "mx.sketchy-host.test", "mx.example.com",
|
| 36 |
+
"tempmail.example.net",
|
| 37 |
+
# spoof-adjacent hostnames must NOT match a trusted suffix
|
| 38 |
+
"google.com.evil.test", "notgoogle.com", "xn--google.com",
|
| 39 |
+
"protection.outlook.com.evil.test", "fake-ppe-hosted.com",
|
| 40 |
+
]
|
| 41 |
+
|
| 42 |
+
def test_real_business_providers_are_trusted(self):
|
| 43 |
+
untrusted = [h for h in self.TRUSTED if not mx_is_trusted(h)]
|
| 44 |
+
self.assertEqual(untrusted, [], f"legit providers not trusted: {untrusted}")
|
| 45 |
+
|
| 46 |
+
def test_unknown_and_spoofed_hosts_are_not_trusted(self):
|
| 47 |
+
trusted = [h for h in self.UNTRUSTED if mx_is_trusted(h)]
|
| 48 |
+
self.assertEqual(trusted, [], f"untrustworthy hosts trusted: {trusted}")
|
| 49 |
+
|
| 50 |
+
def test_matching_is_case_and_trailing_dot_insensitive(self):
|
| 51 |
+
for host in ("ASPmx.L.Google.COM", "aspmx.l.google.com.", " aspmx.l.google.com "):
|
| 52 |
+
self.assertTrue(mx_is_trusted(host), host)
|
| 53 |
+
|
| 54 |
+
def test_empty_and_none_are_not_trusted(self):
|
| 55 |
+
self.assertFalse(mx_is_trusted(""))
|
| 56 |
+
self.assertFalse(mx_is_trusted(None))
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
if __name__ == "__main__":
|
| 60 |
+
unittest.main()
|