From 84c94c79db1fe4d77f28c31b3ec3eb40fecb5629 Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 29 Jan 2022 13:22:53 +0100 Subject: [PATCH] Added option to block return path --- .../eu/faircode/email/AdapterMessage.java | 1 + app/src/main/java/eu/faircode/email/Core.java | 34 +++++++++++-------- .../eu/faircode/email/FragmentDialogJunk.java | 18 +++++++++- .../eu/faircode/email/FragmentMessages.java | 12 +++++-- .../java/eu/faircode/email/MessageHelper.java | 31 +++++++++++++++++ app/src/main/res/layout/dialog_junk.xml | 33 +++++++++++++++++- app/src/main/res/values/strings.xml | 1 + 7 files changed, 112 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 53ac52e593..fa9920c6dc 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -4973,6 +4973,7 @@ public class AdapterMessage extends RecyclerView.Adapter froms = new ArrayList<>(); if (message.from != null) - for (Address from : message.from) { - String email = ((InternetAddress) from).getAddress(); - if (TextUtils.isEmpty(email)) - continue; + froms.addAll(Arrays.asList(message.from)); + if (!BuildConfig.PLAY_STORE_RELEASE && message.return_path != null) + froms.addAll(MessageHelper.exclusive(message.return_path, message.from)); - EntityContact badboy = db.contact().getContact(message.account, EntityContact.TYPE_JUNK, email); - if (badboy != null) { - EntityFolder junk = db.folder().getFolderByType(message.account, EntityFolder.JUNK); - if (junk != null) { - EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id); - message.ui_hide = true; - executed = true; - } - break; + for (Address from : froms) { + String email = ((InternetAddress) from).getAddress(); + if (TextUtils.isEmpty(email)) + continue; + + EntityContact badboy = db.contact().getContact(message.account, EntityContact.TYPE_JUNK, email); + if (badboy != null) { + EntityFolder junk = db.folder().getFolderByType(message.account, EntityFolder.JUNK); + if (junk != null) { + EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id); + message.ui_hide = true; + executed = true; } + break; } + } + } if (executed && !message.hasKeyword(MessageHelper.FLAG_FILTERED)) diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogJunk.java b/app/src/main/java/eu/faircode/email/FragmentDialogJunk.java index dbf926ba51..d7fc0f3cc5 100644 --- a/app/src/main/java/eu/faircode/email/FragmentDialogJunk.java +++ b/app/src/main/java/eu/faircode/email/FragmentDialogJunk.java @@ -42,7 +42,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.constraintlayout.widget.Group; -import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.preference.PreferenceManager; @@ -66,6 +65,7 @@ public class FragmentDialogJunk extends FragmentDialogBase { final long folder = args.getLong("folder"); final String type = args.getString("type"); final Address[] froms = DB.Converters.decodeAddresses(args.getString("from")); + final Address[] return_path = DB.Converters.decodeAddresses(args.getString("return_path")); final boolean inJunk = args.getBoolean("inJunk"); final Context context = getContext(); @@ -73,6 +73,8 @@ public class FragmentDialogJunk extends FragmentDialogBase { final TextView tvMessage = view.findViewById(R.id.tvMessage); final ImageButton ibInfoProvider = view.findViewById(R.id.ibInfoProvider); final CheckBox cbBlockSender = view.findViewById(R.id.cbBlockSender); + final CheckBox cbBlockReturn = view.findViewById(R.id.cbBlockReturn); + final TextView tvReturnPath = view.findViewById(R.id.tvReturnPath); final CheckBox cbBlockDomain = view.findViewById(R.id.cbBlockDomain); final ImageButton ibMore = view.findViewById(R.id.ibMore); final TextView tvMore = view.findViewById(R.id.tvMore); @@ -85,6 +87,7 @@ public class FragmentDialogJunk extends FragmentDialogBase { final ImageButton ibRules = view.findViewById(R.id.ibRules); final ImageButton ibManage = view.findViewById(R.id.ibManage); final Group grpInJunk = view.findViewById(R.id.grpInJunk); + final Group grpReturnPath = view.findViewById(R.id.grpReturnPath); final Group grpMore = view.findViewById(R.id.grpMore); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -110,6 +113,7 @@ public class FragmentDialogJunk extends FragmentDialogBase { cbBlockSender.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + cbBlockReturn.setEnabled(isChecked); cbBlockDomain.setEnabled(isChecked && ActivityBilling.isPro(context)); } }); @@ -334,8 +338,19 @@ public class FragmentDialogJunk extends FragmentDialogBase { ? getString(R.string.title_folder_junk) : getString(R.string.title_ask_spam_who, MessageHelper.formatAddresses(froms))); cbBlockSender.setEnabled(canBlock); + cbBlockReturn.setEnabled(false); cbBlockDomain.setEnabled(false); + cbBlockSender.setChecked(canBlock && block_sender); + cbBlockReturn.setChecked(false); + + List
returns = MessageHelper.exclusive(return_path, froms); + + grpReturnPath.setVisibility(!BuildConfig.PLAY_STORE_RELEASE && returns.size() > 0 + ? View.VISIBLE : View.GONE); + tvReturnPath.setText(MessageHelper.formatAddresses( + returns.toArray(new Address[0]), + MessageHelper.AddressFormat.EMAIL_ONLY, false)); cbBlockDomain.setText(getString(R.string.title_block_sender_domain, TextUtils.join(",", domains))); if (common) { @@ -407,6 +422,7 @@ public class FragmentDialogJunk extends FragmentDialogBase { public void onClick(DialogInterface dialog, int which) { prefs.edit().putBoolean("block_sender", cbBlockSender.isChecked()).apply(); getArguments().putBoolean("block_sender", cbBlockSender.isChecked()); + getArguments().putBoolean("block_return", cbBlockReturn.isChecked()); getArguments().putBoolean("block_domain", cbBlockDomain.isChecked()); sendResult(Activity.RESULT_OK); } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index b7d5dd4a98..d96b2c8aef 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -2669,6 +2669,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. aargs.putLong("folder", message.folder); aargs.putString("type", message.folderType); aargs.putString("from", DB.Converters.encodeAddresses(message.from)); + aargs.putString("return_path", DB.Converters.encodeAddresses(message.return_path)); aargs.putBoolean("inJunk", EntityFolder.JUNK.equals(message.folderType)); FragmentDialogJunk ask = new FragmentDialogJunk(); @@ -8290,6 +8291,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. protected Void onExecute(Context context, Bundle args) throws JSONException { long id = args.getLong("id"); boolean block_sender = args.getBoolean("block_sender"); + boolean block_return = args.getBoolean("block_return"); boolean block_domain = args.getBoolean("block_domain"); DB db = DB.getInstance(context); @@ -8307,10 +8309,16 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (!message.folder.equals(junk.id)) EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id); - if (block_sender) + if (block_sender) { + List
froms = new ArrayList<>(); + if (message.from != null) + froms.addAll(Arrays.asList(message.from)); + if (block_return && message.return_path != null) + froms.addAll(MessageHelper.exclusive(message.return_path, message.from)); EntityContact.update(context, - message.account, message.from, + message.account, froms.toArray(new Address[0]), EntityContact.TYPE_JUNK, message.received); + } if (block_domain) { List rules = EntityRule.blockSender(context, message, junk, block_domain); diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 98898227dc..37de9136ba 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -4051,6 +4051,37 @@ public class MessageHelper { return result.toArray(new InternetAddress[0]); } + static List
exclusive(Address[] address, Address[] base) { + if (address == null || address.length == 0 || + base == null || base.length == 0) + return Arrays.asList(address == null ? new Address[0] : address); + + // Should dedup + List
result = new ArrayList<>(); + for (Address a : address) + if (a instanceof InternetAddress) { + String email = ((InternetAddress) a).getAddress(); + if (TextUtils.isEmpty(email)) + continue; + + boolean found = false; + for (Address b : base) + if (b instanceof InternetAddress) { + String other = ((InternetAddress) b).getAddress(); + if (TextUtils.isEmpty(other)) + continue; + if (email.equalsIgnoreCase(other)) { + found = true; + break; + } + } + if (!found) + result.add(a); + } + + return result; + } + static boolean isRemoved(Throwable ex) { while (ex != null) { if (ex instanceof MessageRemovedException || diff --git a/app/src/main/res/layout/dialog_junk.xml b/app/src/main/res/layout/dialog_junk.xml index 9ed2d72f64..996c3d9516 100644 --- a/app/src/main/res/layout/dialog_junk.xml +++ b/app/src/main/res/layout/dialog_junk.xml @@ -60,6 +60,30 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvJunkHint" /> + + + + + app:layout_constraintTop_toBottomOf="@id/tvReturnPath" /> + + Block %1$s Block sender + Block return-path Block domain \'%1$s\' Blocking a sender is a free feature.