diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index c5dbb5aa1d..7546a25c6f 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -117,6 +117,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB static final int REQUEST_ATTACHMENTS = 3; static final int REQUEST_DECRYPT = 4; static final int REQUEST_SENDER = 5; + static final int REQUEST_RECIPIENT = 6; static final String ACTION_VIEW_MESSAGES = BuildConfig.APPLICATION_ID + ".VIEW_MESSAGES"; static final String ACTION_VIEW_THREAD = BuildConfig.APPLICATION_ID + ".VIEW_THREAD"; diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index e73a0deaaa..71fcbdba29 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -26,8 +26,11 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.Enumeration; +import java.util.List; import java.util.regex.Pattern; import javax.mail.Address; @@ -83,6 +86,7 @@ public class EntityRule { try { JSONObject jcondition = new JSONObject(condition); + // Sender JSONObject jsender = jcondition.optJSONObject("sender"); if (jsender != null) { String value = jsender.getString("value"); @@ -104,6 +108,31 @@ public class EntityRule { return false; } + // Recipient + JSONObject jrecipient = jcondition.optJSONObject("recipient"); + if (jrecipient != null) { + String value = jrecipient.getString("value"); + boolean regex = jrecipient.getBoolean("regex"); + + boolean matches = false; + List
recipients = new ArrayList<>(); + if (message.to != null) + recipients.addAll(Arrays.asList(message.to)); + if (message.cc != null) + recipients.addAll(Arrays.asList(message.cc)); + for (Address recipient : recipients) { + InternetAddress ia = (InternetAddress) recipient; + String personal = ia.getPersonal(); + String formatted = ((personal == null ? "" : personal + " ") + "<" + ia.getAddress() + ">"); + if (matches(context, value, formatted, regex)) { + matches = true; + break; + } + } + if (!matches) + return false; + } + JSONObject jsubject = jcondition.optJSONObject("subject"); if (jsubject != null) { String value = jsubject.getString("value"); @@ -133,7 +162,7 @@ public class EntityRule { } // Safeguard - if (jsender == null && jsubject == null && jheader == null) + if (jsender == null && jrecipient == null && jsubject == null && jheader == null) return false; } catch (JSONException ex) { Log.e(ex); diff --git a/app/src/main/java/eu/faircode/email/FragmentRule.java b/app/src/main/java/eu/faircode/email/FragmentRule.java index 1fa0f8299d..404cd8a1f5 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRule.java +++ b/app/src/main/java/eu/faircode/email/FragmentRule.java @@ -62,26 +62,37 @@ public class FragmentRule extends FragmentBase { private ViewGroup view; private ScrollView scroll; private ConstraintLayout content; + private TextView tvFolder; private EditText etName; private EditText etOrder; private CheckBox cbEnabled; private CheckBox cbStop; + private EditText etSender; private CheckBox cbSender; private ImageView ivSender; + + private EditText etRecipient; + private CheckBox cbRecipient; + private ImageView ivRecipient; + private EditText etSubject; private CheckBox cbSubject; + private EditText etHeader; private CheckBox cbHeader; + private Spinner spAction; private TextView tvActionRemark; private Spinner spTarget; private Spinner spIdent; private Spinner spAnswer; private CheckBox cbCc; + private BottomNavigationView bottom_navigation; private ContentLoadingProgressBar pbWait; + private Group grpReady; private Group grpMove; private Group grpAnswer; @@ -116,26 +127,37 @@ public class FragmentRule extends FragmentBase { // Get controls scroll = view.findViewById(R.id.scroll); content = view.findViewById(R.id.content); + tvFolder = view.findViewById(R.id.tvFolder); etName = view.findViewById(R.id.etName); etOrder = view.findViewById(R.id.etOrder); cbEnabled = view.findViewById(R.id.cbEnabled); cbStop = view.findViewById(R.id.cbStop); + etSender = view.findViewById(R.id.etSender); cbSender = view.findViewById(R.id.cbSender); ivSender = view.findViewById(R.id.ivSender); + + etRecipient = view.findViewById(R.id.etRecipient); + cbRecipient = view.findViewById(R.id.cbRecipient); + ivRecipient = view.findViewById(R.id.ivRecipient); + etSubject = view.findViewById(R.id.etSubject); cbSubject = view.findViewById(R.id.cbSubject); + etHeader = view.findViewById(R.id.etHeader); cbHeader = view.findViewById(R.id.cbHeader); + spAction = view.findViewById(R.id.spAction); tvActionRemark = view.findViewById(R.id.tvActionRemark); spTarget = view.findViewById(R.id.spTarget); spIdent = view.findViewById(R.id.spIdent); spAnswer = view.findViewById(R.id.spAnswer); cbCc = view.findViewById(R.id.cbCc); + bottom_navigation = view.findViewById(R.id.bottom_navigation); pbWait = view.findViewById(R.id.pbWait); + grpReady = view.findViewById(R.id.grpReady); grpMove = view.findViewById(R.id.grpMove); grpAnswer = view.findViewById(R.id.grpAnswer); @@ -151,6 +173,17 @@ public class FragmentRule extends FragmentBase { } }); + ivRecipient.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent pick = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Email.CONTENT_URI); + if (pick.resolveActivity(getContext().getPackageManager()) == null) + Snackbar.make(view, R.string.title_no_contacts, Snackbar.LENGTH_LONG).show(); + else + startActivityForResult(Helper.getChooser(getContext(), pick), ActivityView.REQUEST_RECIPIENT); + } + }); + adapterAction = new ArrayAdapter<>(getContext(), R.layout.spinner_item1, android.R.id.text1, new ArrayList()); adapterAction.setDropDownViewResource(R.layout.spinner_item1_dropdown); spAction.setAdapter(adapterAction); @@ -295,14 +328,14 @@ public class FragmentRule extends FragmentBase { public void onActivityResult(int requestCode, int resultCode, Intent data) { Log.i("Request=" + requestCode + " result=" + resultCode + " data=" + data); if (resultCode == RESULT_OK) { - if (requestCode == ActivityView.REQUEST_SENDER) { - if (data != null) - handlePickContact(data); - } + if (data != null && requestCode == ActivityView.REQUEST_SENDER) + handlePickContact(data, true); + if (data != null && requestCode == ActivityView.REQUEST_RECIPIENT) + handlePickContact(data, false); } } - private void handlePickContact(Intent data) { + private void handlePickContact(Intent data, boolean sender) { Uri uri = data.getData(); if (uri == null) return; try (Cursor cursor = getContext().getContentResolver().query(uri, @@ -311,7 +344,10 @@ public class FragmentRule extends FragmentBase { }, null, null, null)) { if (cursor != null && cursor.moveToFirst()) - etSender.setText(cursor.getString(0)); + if (sender) + etSender.setText(cursor.getString(0)); + else + etRecipient.setText(cursor.getString(0)); } catch (Throwable ex) { Log.e(ex); Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); @@ -338,6 +374,7 @@ public class FragmentRule extends FragmentBase { JSONObject jaction = (rule == null ? new JSONObject() : new JSONObject(rule.action)); JSONObject jsender = jcondition.optJSONObject("sender"); + JSONObject jrecipient = jcondition.optJSONObject("recipient"); JSONObject jsubject = jcondition.optJSONObject("subject"); JSONObject jheader = jcondition.optJSONObject("header"); @@ -345,10 +382,16 @@ public class FragmentRule extends FragmentBase { etOrder.setText(rule == null ? null : Integer.toString(rule.order)); cbEnabled.setChecked(rule == null || rule.enabled); cbStop.setChecked(rule != null && rule.stop); + etSender.setText(jsender == null ? args.getString("sender") : jsender.getString("value")); cbSender.setChecked(jsender != null && jsender.getBoolean("regex")); + + etRecipient.setText(jrecipient == null ? null : jrecipient.getString("value")); + cbRecipient.setChecked(jrecipient != null && jrecipient.getBoolean("regex")); + etSubject.setText(jsubject == null ? args.getString("subject") : jsubject.getString("value")); cbSubject.setChecked(jsubject != null && jsubject.getBoolean("regex")); + etHeader.setText(jheader == null ? null : jheader.getString("value")); cbHeader.setChecked(jheader != null && jheader.getBoolean("regex")); @@ -507,10 +550,11 @@ public class FragmentRule extends FragmentBase { JSONObject jcondition = new JSONObject(condition); JSONObject jsender = jcondition.optJSONObject("sender"); + JSONObject jrecipient = jcondition.optJSONObject("recipient"); JSONObject jsubject = jcondition.optJSONObject("subject"); JSONObject jheader = jcondition.optJSONObject("header"); - if (jsender == null && jsubject == null && jheader == null) + if (jsender == null && jrecipient == null && jsubject == null && jheader == null) throw new IllegalArgumentException(context.getString(R.string.title_rule_condition_missing)); if (TextUtils.isEmpty(order)) @@ -576,6 +620,14 @@ public class FragmentRule extends FragmentBase { jcondition.put("sender", jsender); } + String recipient = etRecipient.getText().toString(); + if (!TextUtils.isEmpty(recipient)) { + JSONObject jrecipient = new JSONObject(); + jrecipient.put("value", recipient); + jrecipient.put("regex", cbRecipient.isChecked()); + jcondition.put("recipient", jrecipient); + } + String subject = etSubject.getText().toString(); if (!TextUtils.isEmpty(subject)) { JSONObject jsubject = new JSONObject(); diff --git a/app/src/main/res/layout/fragment_rule.xml b/app/src/main/res/layout/fragment_rule.xml index 313616a0e4..5c6c40575c 100644 --- a/app/src/main/res/layout/fragment_rule.xml +++ b/app/src/main/res/layout/fragment_rule.xml @@ -143,7 +143,7 @@ app:layout_constraintTop_toTopOf="@id/etSender" /> + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/tvAndRecipient" /> + app:layout_constraintTop_toBottomOf="@id/tvAndSubject" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ed6c21f2dd..3baa6c6d5c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -450,6 +450,7 @@ Enabled Stop processing rules after executing this rule Sender contains + Recipient contains Subject contains Header contains Regex