sitcod3 commited on
Commit
c4729ea
·
verified ·
1 Parent(s): 0eff3fe

Upload folder using huggingface_hub

Browse files
app/validator/disposable.py CHANGED
@@ -11,7 +11,18 @@ FREE_PROVIDERS = {
11
  "yahoo.de", "yahoo.it", "yahoo.es", "yahoo.com.br",
12
  "hotmail.fr", "hotmail.de", "hotmail.it", "hotmail.es",
13
  "hotmail.co.uk", "fastmail.com", "tutanota.com",
14
- "pm.me", "proton.me", "hey.com", "duck.com"
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
 
17
  # Role-based email prefixes
 
11
  "yahoo.de", "yahoo.it", "yahoo.es", "yahoo.com.br",
12
  "hotmail.fr", "hotmail.de", "hotmail.it", "hotmail.es",
13
  "hotmail.co.uk", "fastmail.com", "tutanota.com",
14
+ "pm.me", "proton.me", "hey.com", "duck.com",
15
+ # ISP mailbox domains: legitimate consumer mailboxes handled by the
16
+ # deterministic free-provider path, never by the ML advisory (the model has
17
+ # no training signal for them and flagged sbcglobal.net as disposable).
18
+ "sbcglobal.net", "att.net", "comcast.net", "verizon.net",
19
+ "bellsouth.net", "cox.net", "charter.net", "earthlink.net",
20
+ "roadrunner.com", "rr.com", "shaw.ca", "rogers.com",
21
+ "btinternet.com", "sky.com", "virginmedia.com", "orange.fr",
22
+ "wanadoo.fr", "free.fr", "laposte.net", "web.de",
23
+ "t-online.de", "arcor.de", "libero.it", "virgilio.it",
24
+ "terra.com.br", "uol.com.br", "bol.com.br", "seznam.cz",
25
+ "naver.com", "daum.net", "hanmail.net", "rediffmail.com",
26
  }
27
 
28
  # Role-based email prefixes
tests/test_free_providers.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import unittest
2
+
3
+ from app.validator.disposable import FREE_PROVIDERS, check_disposable, domain_is_known
4
+
5
+
6
+ class FreeProviderCoverageTests(unittest.TestCase):
7
+ """ISP and consumer mailbox domains must be recognised deterministically.
8
+
9
+ Found live: `g.lombardi@sbcglobal.net` (AT&T's consumer mail) was passed to
10
+ the ML advisory, which flagged it DISPOSABLE at 0.995. Consumer ISP domains
11
+ are not disposable — they belong to the deterministic free-provider path,
12
+ which also removes them from the model's remit entirely.
13
+ """
14
+
15
+ ISP_DOMAINS = [
16
+ "sbcglobal.net", # AT&T
17
+ "att.net", "comcast.net", "verizon.net", "bellsouth.net",
18
+ "cox.net", "charter.net", "earthlink.net",
19
+ "btinternet.com", "sky.com", "virginmedia.com",
20
+ "web.de", "t-online.de", "laposte.net", "free.fr",
21
+ "naver.com", "rediffmail.com",
22
+ ]
23
+
24
+ def test_isp_domains_are_free_providers(self):
25
+ missing = [d for d in self.ISP_DOMAINS if d not in FREE_PROVIDERS]
26
+ self.assertEqual(missing, [], f"ISP domains missing: {missing}")
27
+
28
+ def test_isp_domains_are_known_and_not_disposable(self):
29
+ for domain in self.ISP_DOMAINS:
30
+ with self.subTest(domain=domain):
31
+ self.assertTrue(domain_is_known(domain))
32
+ result = check_disposable(f"user@{domain}", domain)
33
+ self.assertTrue(result.is_free_provider)
34
+ self.assertFalse(result.is_disposable)
35
+
36
+ def test_known_domains_are_never_sent_to_the_ml_advisory(self):
37
+ # The engine gates the model on `not domain_is_known(domain)`; this
38
+ # asserts the gate input for every ISP domain.
39
+ for domain in self.ISP_DOMAINS:
40
+ with self.subTest(domain=domain):
41
+ self.assertTrue(
42
+ domain_is_known(domain),
43
+ f"{domain} would reach the ML advisory",
44
+ )
45
+
46
+
47
+ if __name__ == "__main__":
48
+ unittest.main()