mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-07 09:33:39 +02:00
Allow selecting blocklists
This commit is contained in:
@@ -3373,7 +3373,7 @@ class Core {
|
||||
boolean blocklist = false;
|
||||
for (Address sender : senders) {
|
||||
String email = ((InternetAddress) sender).getAddress();
|
||||
if (DnsBlockList.isJunk(email)) {
|
||||
if (DnsBlockList.isJunk(context, email)) {
|
||||
blocklist = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,12 @@ package eu.faircode.email;
|
||||
Copyright 2018-2021 by Marcel Bokhorst (M66B)
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
@@ -34,7 +38,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DnsBlockList {
|
||||
private static final List<BlockList> BLOCKLISTS = Collections.unmodifiableList(Arrays.asList(
|
||||
static final List<BlockList> BLOCKLISTS = Collections.unmodifiableList(Arrays.asList(
|
||||
// https://www.spamhaus.org/zen/
|
||||
new BlockList(true, "Spamhaus/zen", "zen.spamhaus.org", true, new String[]{
|
||||
// https://www.spamhaus.org/faq/section/DNSBL%20Usage#200
|
||||
@@ -73,15 +77,29 @@ public class DnsBlockList {
|
||||
private static final long CACHE_EXPIRY_AFTER = 3600 * 1000L; // milliseconds
|
||||
private static final Map<String, CacheEntry> cache = new Hashtable<>();
|
||||
|
||||
static List<String> getNames() {
|
||||
static void setEnabled(Context context, BlockList blocklist, boolean enabled) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().putBoolean("blocklist." + blocklist.name, enabled).apply();
|
||||
|
||||
synchronized (cache) {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isEnabled(Context context, BlockList blocklist) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
return prefs.getBoolean("blocklist." + blocklist.name, blocklist.enabled);
|
||||
}
|
||||
|
||||
static List<String> getNames(Context context) {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (BlockList blocklist : BLOCKLISTS)
|
||||
if (blocklist.enabled)
|
||||
if (isEnabled(context, blocklist))
|
||||
names.add(blocklist.name);
|
||||
return names;
|
||||
}
|
||||
|
||||
static boolean isJunk(String email) {
|
||||
static boolean isJunk(Context context, String email) {
|
||||
if (TextUtils.isEmpty(email))
|
||||
return false;
|
||||
|
||||
@@ -89,10 +107,10 @@ public class DnsBlockList {
|
||||
if (at < 0)
|
||||
return false;
|
||||
|
||||
return isJunk(email.substring(at + 1), BLOCKLISTS);
|
||||
return isJunk(context, email.substring(at + 1), BLOCKLISTS);
|
||||
}
|
||||
|
||||
private static boolean isJunk(String domain, List<BlockList> blocklists) {
|
||||
private static boolean isJunk(Context context, String domain, List<BlockList> blocklists) {
|
||||
synchronized (cache) {
|
||||
CacheEntry entry = cache.get(domain);
|
||||
if (entry != null && !entry.isExpired())
|
||||
@@ -101,7 +119,7 @@ public class DnsBlockList {
|
||||
|
||||
boolean blocked = false;
|
||||
for (BlockList blocklist : blocklists)
|
||||
if (blocklist.enabled && isJunk(domain, blocklist)) {
|
||||
if (isEnabled(context, blocklist) && isJunk(domain, blocklist)) {
|
||||
blocked = true;
|
||||
break;
|
||||
}
|
||||
@@ -212,13 +230,17 @@ public class DnsBlockList {
|
||||
}
|
||||
|
||||
static class BlockList {
|
||||
int id;
|
||||
boolean enabled;
|
||||
String name;
|
||||
String address;
|
||||
boolean numeric;
|
||||
InetAddress[] responses;
|
||||
|
||||
private static int nextid = 1;
|
||||
|
||||
BlockList(boolean enabled, String name, String address, boolean numeric, String[] responses) {
|
||||
this.id = nextid++;
|
||||
this.enabled = enabled;
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
|
||||
@@ -245,7 +245,7 @@ public class FragmentDialogJunk extends FragmentDialogBase {
|
||||
cbBlockDomain.setEnabled(false);
|
||||
ibMore.setImageLevel(1);
|
||||
cbBlocklist.setChecked(check_blocklist && use_blocklist);
|
||||
tvBlocklist.setText(TextUtils.join(", ", DnsBlockList.getNames()));
|
||||
tvBlocklist.setText(TextUtils.join(", ", DnsBlockList.getNames(context)));
|
||||
grpInJunk.setVisibility(inJunk ? View.GONE : View.VISIBLE);
|
||||
grpMore.setVisibility(inJunk ? View.VISIBLE : View.GONE);
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.app.TimePickerDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -86,7 +85,7 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
private SwitchCompat swCheckReply;
|
||||
private SwitchCompat swCheckMx;
|
||||
private SwitchCompat swCheckBlocklist;
|
||||
private TextView tvCheckBlocklistHint;
|
||||
private RecyclerView rvBlocklist;
|
||||
private SwitchCompat swUseBlocklist;
|
||||
private SwitchCompat swTuneKeepAlive;
|
||||
private Group grpExempted;
|
||||
@@ -144,7 +143,7 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
swCheckReply = view.findViewById(R.id.swCheckReply);
|
||||
swCheckMx = view.findViewById(R.id.swCheckMx);
|
||||
swCheckBlocklist = view.findViewById(R.id.swCheckBlocklist);
|
||||
tvCheckBlocklistHint = view.findViewById(R.id.tvCheckBlocklistHint);
|
||||
rvBlocklist = view.findViewById(R.id.rvBlocklist);
|
||||
swUseBlocklist = view.findViewById(R.id.swUseBlocklist);
|
||||
swTuneKeepAlive = view.findViewById(R.id.swTuneKeepAlive);
|
||||
grpExempted = view.findViewById(R.id.grpExempted);
|
||||
@@ -346,9 +345,15 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||
prefs.edit().putBoolean("check_blocklist", checked).apply();
|
||||
swUseBlocklist.setEnabled(checked);
|
||||
rvBlocklist.setVisibility(checked ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
rvBlocklist.setHasFixedSize(false);
|
||||
rvBlocklist.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
AdapterBlocklist badapter = new AdapterBlocklist(getContext(), DnsBlockList.BLOCKLISTS);
|
||||
rvBlocklist.setAdapter(badapter);
|
||||
|
||||
swUseBlocklist.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||
@@ -381,8 +386,6 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
}
|
||||
});
|
||||
|
||||
tvCheckBlocklistHint.setText(TextUtils.join(", ", DnsBlockList.getNames()));
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
return view;
|
||||
@@ -454,6 +457,7 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
swCheckReply.setChecked(prefs.getBoolean("check_reply_domain", true));
|
||||
swCheckMx.setChecked(prefs.getBoolean("check_mx", false));
|
||||
swCheckBlocklist.setChecked(prefs.getBoolean("check_blocklist", false));
|
||||
rvBlocklist.setVisibility(swCheckBlocklist.isChecked() ? View.VISIBLE : View.GONE);
|
||||
swUseBlocklist.setChecked(prefs.getBoolean("use_blocklist", false));
|
||||
swUseBlocklist.setEnabled(swCheckBlocklist.isChecked());
|
||||
swTuneKeepAlive.setChecked(prefs.getBoolean("tune_keep_alive", true));
|
||||
@@ -502,7 +506,7 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
}
|
||||
}
|
||||
|
||||
public class AdapterAccountExempted extends RecyclerView.Adapter<AdapterAccountExempted.ViewHolder> {
|
||||
public static class AdapterAccountExempted extends RecyclerView.Adapter<AdapterAccountExempted.ViewHolder> {
|
||||
private Context context;
|
||||
private LifecycleOwner owner;
|
||||
private LayoutInflater inflater;
|
||||
@@ -641,4 +645,75 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
|
||||
holder.wire();
|
||||
}
|
||||
}
|
||||
|
||||
public static class AdapterBlocklist extends RecyclerView.Adapter<AdapterBlocklist.ViewHolder> {
|
||||
private Context context;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
private List<DnsBlockList.BlockList> items;
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener {
|
||||
private CheckBox cbEnabled;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
cbEnabled = itemView.findViewById(R.id.cbEnabled);
|
||||
}
|
||||
|
||||
private void wire() {
|
||||
cbEnabled.setOnCheckedChangeListener(this);
|
||||
}
|
||||
|
||||
private void unwire() {
|
||||
cbEnabled.setOnCheckedChangeListener(null);
|
||||
}
|
||||
|
||||
private void bindTo(DnsBlockList.BlockList blocklist) {
|
||||
cbEnabled.setText(blocklist.name);
|
||||
cbEnabled.setChecked(DnsBlockList.isEnabled(context, blocklist));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
int pos = getAdapterPosition();
|
||||
if (pos == RecyclerView.NO_POSITION)
|
||||
return;
|
||||
|
||||
DnsBlockList.BlockList blocklist = items.get(pos);
|
||||
DnsBlockList.setEnabled(context, blocklist, isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
AdapterBlocklist(Context context, List<DnsBlockList.BlockList> items) {
|
||||
this.context = context;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
|
||||
setHasStableIds(true);
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return items.get(position).id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(inflater.inflate(R.layout.item_blocklist_enabled, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
holder.unwire();
|
||||
DnsBlockList.BlockList blocklist = items.get(position);
|
||||
holder.bindTo(blocklist);
|
||||
holder.wire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user