From 8471b06dde3793f64d0eefba7d62d7efca39db35 Mon Sep 17 00:00:00 2001 From: M66B Date: Tue, 29 Jun 2021 14:06:30 +0200 Subject: [PATCH] Check last received header against blocklists --- app/src/main/java/eu/faircode/email/Core.java | 21 ++----- .../java/eu/faircode/email/DnsBlockList.java | 55 +++++++++++++------ 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 2c719810cc..3553ac2fa7 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -3377,22 +3377,13 @@ class Core { } boolean check_blocklist = prefs.getBoolean("check_blocklist", false); - if (check_blocklist && !self) { - List
senders = new ArrayList<>(); - if (message.from != null) - senders.addAll(Arrays.asList(message.from)); - if (message.reply != null) - senders.addAll(Arrays.asList(message.reply)); - boolean blocklist = false; - for (Address sender : senders) { - String email = ((InternetAddress) sender).getAddress(); - if (DnsBlockList.isJunk(context, email)) { - blocklist = true; - break; - } + if (check_blocklist && !EntityFolder.isOutgoing(folder.type)) + try { + message.blocklist = DnsBlockList.isJunk( + context, imessage.getHeader("Received")); + } catch (Throwable ex) { + Log.w(folder.name, ex); } - message.blocklist = blocklist; - } try { db.beginTransaction(); diff --git a/app/src/main/java/eu/faircode/email/DnsBlockList.java b/app/src/main/java/eu/faircode/email/DnsBlockList.java index 6c77fdfbbc..c2e32f9836 100644 --- a/app/src/main/java/eu/faircode/email/DnsBlockList.java +++ b/app/src/main/java/eu/faircode/email/DnsBlockList.java @@ -35,8 +35,11 @@ import java.util.Collections; import java.util.Date; import java.util.Hashtable; import java.util.List; +import java.util.Locale; import java.util.Map; +import javax.mail.internet.MimeUtility; + public class DnsBlockList { static final List BLOCKLISTS = Collections.unmodifiableList(Arrays.asList( // https://www.spamhaus.org/zen/ @@ -115,46 +118,61 @@ public class DnsBlockList { return names; } - static boolean isJunk(Context context, String email) { - if (TextUtils.isEmpty(email)) - return false; - - int at = email.indexOf('@'); - if (at < 0) - return false; + static Boolean isJunk(Context context, String[] received) { + if (received == null || received.length == 0) + return null; + + String h = MimeUtility.unfold(received[received.length - 1]); + String[] words = h.split("\\s+"); + for (int i = 0; i < words.length - 1; i++) + if ("from".equalsIgnoreCase(words[i])) { + String host = words[i + 1].toLowerCase(Locale.ROOT); + if (!TextUtils.isEmpty(host)) + return isJunk(context, host, BLOCKLISTS); + } - return isJunk(context, email.substring(at + 1), BLOCKLISTS); + return null; } - private static boolean isJunk(Context context, String domain, List blocklists) { + private static boolean isJunk(Context context, String host, List blocklists) { synchronized (cache) { - CacheEntry entry = cache.get(domain); + CacheEntry entry = cache.get(host); if (entry != null && !entry.isExpired()) return entry.isJunk(); } boolean blocked = false; for (BlockList blocklist : blocklists) - if (isEnabled(context, blocklist) && isJunk(domain, blocklist)) { + if (isEnabled(context, blocklist) && isJunk(host, blocklist)) { blocked = true; break; } synchronized (cache) { - cache.put(domain, new CacheEntry(blocked)); + cache.put(host, new CacheEntry(blocked)); } return blocked; } - private static boolean isJunk(String domain, BlockList blocklist) { + private static boolean isJunk(String host, BlockList blocklist) { + boolean numeric = host.startsWith("[") && host.endsWith("]"); + if (numeric) + host = host.substring(1, host.length() - 1); try { if (blocklist.numeric) { long start = new Date().getTime(); - InetAddress[] addresses = InetAddress.getAllByName(domain); + InetAddress[] addresses = InetAddress.getAllByName(host); long elapsed = new Date().getTime() - start; - Log.i("isJunk resolved=" + domain + " elapse=" + elapsed + " ms"); - for (InetAddress addr : addresses) + Log.i("isJunk resolved=" + host + " elapse=" + elapsed + " ms"); + for (InetAddress addr : addresses) { + if (addr.isLoopbackAddress() || + addr.isLinkLocalAddress() || + addr.isSiteLocalAddress() || + addr.isMulticastAddress()) { + Log.i("isJunk local=" + addr); + continue; + } try { StringBuilder lookup = new StringBuilder(); if (addr instanceof Inet4Address) { @@ -177,9 +195,10 @@ public class DnsBlockList { } catch (Throwable ex) { Log.w(ex); } - } else { + } + } else if (!numeric) { long start = new Date().getTime(); - String lookup = domain + "." + blocklist.address; + String lookup = host + "." + blocklist.address; boolean junk = isJunk(lookup, blocklist.responses); long elapsed = new Date().getTime() - start; Log.i("isJunk" + " " + lookup + "=" + junk + " elapsed=" + elapsed);