Added option to block return path

pull/194/merge
M66B 3 years ago
parent 220eb6dfda
commit 84c94c79db

@ -4973,6 +4973,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
aargs.putLong("folder", message.folder); aargs.putLong("folder", message.folder);
aargs.putString("type", message.folderType); aargs.putString("type", message.folderType);
aargs.putString("from", DB.Converters.encodeAddresses(message.from)); 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)); aargs.putBoolean("inJunk", EntityFolder.JUNK.equals(message.folderType));
FragmentDialogJunk ask = new FragmentDialogJunk(); FragmentDialogJunk ask = new FragmentDialogJunk();

@ -4499,24 +4499,30 @@ class Core {
break; break;
} }
if (EntityFolder.INBOX.equals(folder.type)) if (EntityFolder.INBOX.equals(folder.type)) {
List<Address> froms = new ArrayList<>();
if (message.from != null) if (message.from != null)
for (Address from : message.from) { froms.addAll(Arrays.asList(message.from));
String email = ((InternetAddress) from).getAddress(); if (!BuildConfig.PLAY_STORE_RELEASE && message.return_path != null)
if (TextUtils.isEmpty(email)) froms.addAll(MessageHelper.exclusive(message.return_path, message.from));
continue;
EntityContact badboy = db.contact().getContact(message.account, EntityContact.TYPE_JUNK, email); for (Address from : froms) {
if (badboy != null) { String email = ((InternetAddress) from).getAddress();
EntityFolder junk = db.folder().getFolderByType(message.account, EntityFolder.JUNK); if (TextUtils.isEmpty(email))
if (junk != null) { continue;
EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id);
message.ui_hide = true; EntityContact badboy = db.contact().getContact(message.account, EntityContact.TYPE_JUNK, email);
executed = true; if (badboy != null) {
} EntityFolder junk = db.folder().getFolderByType(message.account, EntityFolder.JUNK);
break; if (junk != null) {
EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id);
message.ui_hide = true;
executed = true;
} }
break;
} }
}
}
if (executed && if (executed &&
!message.hasKeyword(MessageHelper.FLAG_FILTERED)) !message.hasKeyword(MessageHelper.FLAG_FILTERED))

@ -42,7 +42,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group; import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -66,6 +65,7 @@ public class FragmentDialogJunk extends FragmentDialogBase {
final long folder = args.getLong("folder"); final long folder = args.getLong("folder");
final String type = args.getString("type"); final String type = args.getString("type");
final Address[] froms = DB.Converters.decodeAddresses(args.getString("from")); 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 boolean inJunk = args.getBoolean("inJunk");
final Context context = getContext(); final Context context = getContext();
@ -73,6 +73,8 @@ public class FragmentDialogJunk extends FragmentDialogBase {
final TextView tvMessage = view.findViewById(R.id.tvMessage); final TextView tvMessage = view.findViewById(R.id.tvMessage);
final ImageButton ibInfoProvider = view.findViewById(R.id.ibInfoProvider); final ImageButton ibInfoProvider = view.findViewById(R.id.ibInfoProvider);
final CheckBox cbBlockSender = view.findViewById(R.id.cbBlockSender); 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 CheckBox cbBlockDomain = view.findViewById(R.id.cbBlockDomain);
final ImageButton ibMore = view.findViewById(R.id.ibMore); final ImageButton ibMore = view.findViewById(R.id.ibMore);
final TextView tvMore = view.findViewById(R.id.tvMore); 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 ibRules = view.findViewById(R.id.ibRules);
final ImageButton ibManage = view.findViewById(R.id.ibManage); final ImageButton ibManage = view.findViewById(R.id.ibManage);
final Group grpInJunk = view.findViewById(R.id.grpInJunk); final Group grpInJunk = view.findViewById(R.id.grpInJunk);
final Group grpReturnPath = view.findViewById(R.id.grpReturnPath);
final Group grpMore = view.findViewById(R.id.grpMore); final Group grpMore = view.findViewById(R.id.grpMore);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@ -110,6 +113,7 @@ public class FragmentDialogJunk extends FragmentDialogBase {
cbBlockSender.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { cbBlockSender.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
cbBlockReturn.setEnabled(isChecked);
cbBlockDomain.setEnabled(isChecked && ActivityBilling.isPro(context)); 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_folder_junk)
: getString(R.string.title_ask_spam_who, MessageHelper.formatAddresses(froms))); : getString(R.string.title_ask_spam_who, MessageHelper.formatAddresses(froms)));
cbBlockSender.setEnabled(canBlock); cbBlockSender.setEnabled(canBlock);
cbBlockReturn.setEnabled(false);
cbBlockDomain.setEnabled(false); cbBlockDomain.setEnabled(false);
cbBlockSender.setChecked(canBlock && block_sender); cbBlockSender.setChecked(canBlock && block_sender);
cbBlockReturn.setChecked(false);
List<Address> 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))); cbBlockDomain.setText(getString(R.string.title_block_sender_domain, TextUtils.join(",", domains)));
if (common) { if (common) {
@ -407,6 +422,7 @@ public class FragmentDialogJunk extends FragmentDialogBase {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
prefs.edit().putBoolean("block_sender", cbBlockSender.isChecked()).apply(); prefs.edit().putBoolean("block_sender", cbBlockSender.isChecked()).apply();
getArguments().putBoolean("block_sender", cbBlockSender.isChecked()); getArguments().putBoolean("block_sender", cbBlockSender.isChecked());
getArguments().putBoolean("block_return", cbBlockReturn.isChecked());
getArguments().putBoolean("block_domain", cbBlockDomain.isChecked()); getArguments().putBoolean("block_domain", cbBlockDomain.isChecked());
sendResult(Activity.RESULT_OK); sendResult(Activity.RESULT_OK);
} }

@ -2669,6 +2669,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
aargs.putLong("folder", message.folder); aargs.putLong("folder", message.folder);
aargs.putString("type", message.folderType); aargs.putString("type", message.folderType);
aargs.putString("from", DB.Converters.encodeAddresses(message.from)); 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)); aargs.putBoolean("inJunk", EntityFolder.JUNK.equals(message.folderType));
FragmentDialogJunk ask = new FragmentDialogJunk(); FragmentDialogJunk ask = new FragmentDialogJunk();
@ -8290,6 +8291,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
protected Void onExecute(Context context, Bundle args) throws JSONException { protected Void onExecute(Context context, Bundle args) throws JSONException {
long id = args.getLong("id"); long id = args.getLong("id");
boolean block_sender = args.getBoolean("block_sender"); boolean block_sender = args.getBoolean("block_sender");
boolean block_return = args.getBoolean("block_return");
boolean block_domain = args.getBoolean("block_domain"); boolean block_domain = args.getBoolean("block_domain");
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -8307,10 +8309,16 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (!message.folder.equals(junk.id)) if (!message.folder.equals(junk.id))
EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id); EntityOperation.queue(context, message, EntityOperation.MOVE, junk.id);
if (block_sender) if (block_sender) {
List<Address> 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, EntityContact.update(context,
message.account, message.from, message.account, froms.toArray(new Address[0]),
EntityContact.TYPE_JUNK, message.received); EntityContact.TYPE_JUNK, message.received);
}
if (block_domain) { if (block_domain) {
List<EntityRule> rules = EntityRule.blockSender(context, message, junk, block_domain); List<EntityRule> rules = EntityRule.blockSender(context, message, junk, block_domain);

@ -4051,6 +4051,37 @@ public class MessageHelper {
return result.toArray(new InternetAddress[0]); return result.toArray(new InternetAddress[0]);
} }
static List<Address> 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<Address> 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) { static boolean isRemoved(Throwable ex) {
while (ex != null) { while (ex != null) {
if (ex instanceof MessageRemovedException || if (ex instanceof MessageRemovedException ||

@ -60,6 +60,30 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvJunkHint" /> app:layout_constraintTop_toBottomOf="@id/tvJunkHint" />
<CheckBox
android:id="@+id/cbBlockReturn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:text="@string/title_block_return_path"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbBlockSender" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvReturnPath"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:text="return@example.com"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbBlockReturn" />
<CheckBox <CheckBox
android:id="@+id/cbBlockDomain" android:id="@+id/cbBlockDomain"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -69,7 +93,7 @@
android:text="@string/title_block_sender_domain" android:text="@string/title_block_sender_domain"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbBlockSender" /> app:layout_constraintTop_toBottomOf="@id/tvReturnPath" />
<eu.faircode.email.FixedTextView <eu.faircode.email.FixedTextView
android:id="@+id/tvBlockHint" android:id="@+id/tvBlockHint"
@ -255,6 +279,13 @@
tvBlockHint,cbBlockSender,cbBlockDomain, tvBlockHint,cbBlockSender,cbBlockDomain,
ibMore,tvMore" /> ibMore,tvMore" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpReturnPath"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="
cbBlockReturn,tvReturnPath" />
<androidx.constraintlayout.widget.Group <androidx.constraintlayout.widget.Group
android:id="@+id/grpMore" android:id="@+id/grpMore"
android:layout_width="0dp" android:layout_width="0dp"

@ -93,6 +93,7 @@
<string name="title_block">Block %1$s</string> <string name="title_block">Block %1$s</string>
<string name="title_block_sender">Block sender</string> <string name="title_block_sender">Block sender</string>
<string name="title_block_return_path">Block return-path</string>
<string name="title_block_sender_domain">Block domain \'%1$s\'</string> <string name="title_block_sender_domain">Block domain \'%1$s\'</string>
<string name="title_block_sender_hint"> <string name="title_block_sender_hint">
Blocking a sender is a free feature. Blocking a sender is a free feature.

Loading…
Cancel
Save