aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/plans/2026-09-08-parse.md104
1 files changed, 88 insertions, 16 deletions
diff --git a/docs/plans/2026-09-08-parse.md b/docs/plans/2026-09-08-parse.md
index 579ff0e..8d30cae 100644
--- a/docs/plans/2026-09-08-parse.md
+++ b/docs/plans/2026-09-08-parse.md
@@ -1781,18 +1781,69 @@ from pathlib import Path
from abusectl import parse
-# Sending ranges the providers publish themselves. Static rather than read
-# from SPF at runtime: SPF is a DNS lookup, and while the never-resolve rule
-# is about parsing hostile mail rather than setup, a static table keeps the
-# boundary unambiguous. Verify against the provider's own documentation
-# before adding an entry.
+# Sending ranges the providers publish in their own SPF records, transcribed
+# on 2026-09-08 from:
+#
+# gmail dig TXT _spf.google.com
+# fastmail dig TXT spf.messagingengine.com
+# proton dig TXT _spf.protonmail.ch + _spf2.protonmail.ch
+# outlook dig TXT spf.protection.outlook.com
+# zoho dig TXT spf.zoho.eu
+#
+# Static rather than read from SPF at runtime: SPF is a DNS lookup, and while
+# the never-resolve rule is about parsing hostile mail rather than setup, a
+# static table keeps the boundary unambiguous.
+#
+# IPv4 only. An IPv6 hop from one of these providers is simply not matched by
+# the table, which is the safe direction: the user is asked instead of a hop
+# being wrongly trusted.
+#
+# THESE GO STALE. A range that has been reassigned means a hop is treated as
+# the user's own and the real sender is never reported, so re-check the SPF
+# records before a release rather than trusting the date above.
PROVIDERS: dict[str, list[str]] = {
- "gmail": ["35.190.247.0/24", "64.233.160.0/19", "66.102.0.0/20",
- "66.249.80.0/20", "72.14.192.0/18", "74.125.0.0/16",
- "108.177.8.0/21", "173.194.0.0/16", "209.85.128.0/17",
- "216.58.192.0/19", "216.239.32.0/19"],
- "fastmail": ["66.111.4.0/24", "103.168.172.0/22"],
- "proton": ["185.70.40.0/22", "51.89.119.103/32"],
+ "gmail": [
+ "74.125.0.0/16",
+ "209.85.128.0/17",
+ ],
+ "fastmail": [
+ "103.168.172.128/27",
+ "202.12.124.128/27",
+ "204.75.18.128/27",
+ ],
+ "proton": [
+ "185.70.40.0/24",
+ "185.70.41.0/24",
+ "185.70.43.0/24",
+ "79.135.106.0/24",
+ "79.135.107.0/24",
+ "109.224.244.0/24",
+ "85.9.206.169/32",
+ "85.9.210.45/32",
+ "37.187.220.204/32",
+ "51.83.17.38/32",
+ "57.129.93.249/32",
+ ],
+ "outlook": [
+ "40.92.0.0/15",
+ "40.107.0.0/16",
+ "52.100.0.0/15",
+ "52.102.0.0/16",
+ "52.103.0.0/17",
+ "104.47.0.0/17",
+ ],
+ "zoho": [
+ "185.20.209.0/24",
+ "31.186.226.0/24",
+ "31.186.243.0/24",
+ "89.36.170.0/24",
+ "185.20.211.0/24",
+ "185.172.199.0/24",
+ "91.135.68.104/29",
+ "185.230.214.0/23",
+ "136.143.168.0/22",
+ "34.241.242.183/32",
+ ],
}
@@ -1957,12 +2008,33 @@ def write(path: Path, answers: dict, force: bool = False) -> Path:
Run: `python3 -m unittest tests.test_init -v`
Expected: PASS, 15 tests
-- [ ] **Step 5: Verify the shipped provider ranges before trusting them**
+- [ ] **Step 5: Re-verify the shipped provider ranges against SPF**
+
+The table was transcribed from the providers' own SPF records on 2026-09-08,
+which is the authoritative source: these are the addresses each provider
+declares it sends from. It still goes stale, and a range that has been
+reassigned means a hop is treated as the user's own and the real sender is
+never reported.
+
+Re-check before relying on it:
+
+```bash
+for d in _spf.google.com spf.messagingengine.com _spf.protonmail.ch \
+ _spf2.protonmail.ch spf.protection.outlook.com spf.zoho.eu; do
+ printf '%-32s ' "$d"; dig +short TXT "$d"
+done
+```
+
+Compare each `ip4:` entry against `PROVIDERS`. Anything that has moved gets
+corrected in the table and the transcription date updated.
-The table is static data and can go stale. Confirm each provider's ranges
-against its own published documentation, and record the date checked in a
-comment above `PROVIDERS`. A wrong range here means a hop is treated as the
-user's own and the real sender is never reported.
+Two properties of this table are deliberate. It is **IPv4 only**: an IPv6 hop
+from one of these providers simply does not match, so the user is asked rather
+than a hop being wrongly trusted. And Google publishes a much broader
+`goog.json` of all its infrastructure, which is **not** what belongs here:
+`_spf.google.com` is two ranges, `goog.json` is over a hundred, and using the
+latter would trust every Google-hosted service as if it were the user's own
+mail path.
- [ ] **Step 6: Commit**