From d9528a3ca444e998af3b0673b4295c1815c0c9dd Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 18 Jan 2019 13:04:05 +0000 Subject: [PATCH] Header rules, improvements --- .../java/eu/faircode/email/EntityRule.java | 38 ++++++++--- .../java/eu/faircode/email/FragmentRule.java | 18 ++++- .../eu/faircode/email/ServiceSynchronize.java | 2 +- app/src/main/res/layout/fragment_rule.xml | 68 +++++++++++++++---- app/src/main/res/values/strings.xml | 2 - 5 files changed, 101 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index f12466e99d..adde2b3d52 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -24,10 +24,13 @@ import android.content.Context; import org.json.JSONException; import org.json.JSONObject; -import java.io.IOException; +import java.util.Enumeration; import java.util.regex.Pattern; import javax.mail.Address; +import javax.mail.Header; +import javax.mail.Message; +import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import androidx.annotation.NonNull; @@ -72,13 +75,13 @@ public class EntityRule { static final int TYPE_UNSEEN = 2; static final int TYPE_MOVE = 3; - boolean matches(Context context, EntityMessage message) throws IOException { + boolean matches(Context context, EntityMessage message, Message imessage) throws MessagingException { try { JSONObject jcondition = new JSONObject(condition); JSONObject jsender = jcondition.optJSONObject("sender"); if (jsender != null) { - String sender = jsender.getString("value"); + String value = jsender.getString("value"); boolean regex = jsender.getBoolean("regex"); boolean matches = false; @@ -87,7 +90,7 @@ public class EntityRule { InternetAddress ia = (InternetAddress) from; String personal = ia.getPersonal(); String formatted = ((personal == null ? "" : personal + " ") + "<" + ia.getAddress() + ">"); - if (matches(sender, formatted, regex)) { + if (matches(value, formatted, regex)) { matches = true; break; } @@ -99,15 +102,34 @@ public class EntityRule { JSONObject jsubject = jcondition.optJSONObject("subject"); if (jsubject != null) { - String subject = jsubject.getString("value"); + String value = jsubject.getString("value"); boolean regex = jsubject.getBoolean("regex"); - if (!matches(subject, message.subject, regex)) + if (!matches(value, message.subject, regex)) + return false; + } + + JSONObject jheader = jcondition.optJSONObject("header"); + if (jheader != null) { + String value = jheader.getString("value"); + boolean regex = jheader.getBoolean("regex"); + + boolean matches = false; + Enumeration
headers = imessage.getAllHeaders(); + while (headers.hasMoreElements()) { + Header header = headers.nextElement(); + String formatted = header.getName() + ": " + header.getValue(); + if (matches(value, formatted, regex)) { + matches = true; + break; + } + } + if (!matches) return false; } // Safeguard - if (jsender == null && jsubject == null) + if (jsender == null && jsubject == null && jheader == null) return false; } catch (JSONException ex) { Log.e(ex); @@ -127,7 +149,7 @@ public class EntityRule { Pattern pattern = Pattern.compile(needle); return pattern.matcher(haystack).matches(); } else - return haystack.contains(needle); + return haystack.toLowerCase().contains(needle.toLowerCase()); } void execute(Context context, DB db, EntityMessage message) { diff --git a/app/src/main/java/eu/faircode/email/FragmentRule.java b/app/src/main/java/eu/faircode/email/FragmentRule.java index 453ccd1bd3..3a29c5fdbe 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRule.java +++ b/app/src/main/java/eu/faircode/email/FragmentRule.java @@ -56,6 +56,8 @@ public class FragmentRule extends FragmentBase { private CheckBox cbSender; private EditText etSubject; private CheckBox cbSubject; + private EditText etHeader; + private CheckBox cbHeader; private Spinner spAction; private Spinner spTarget; private BottomNavigationView bottom_navigation; @@ -95,6 +97,8 @@ public class FragmentRule extends FragmentBase { cbSender = view.findViewById(R.id.cbSender); 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); spTarget = view.findViewById(R.id.spTarget); bottom_navigation = view.findViewById(R.id.bottom_navigation); @@ -208,6 +212,7 @@ public class FragmentRule extends FragmentBase { JSONObject jsender = jcondition.optJSONObject("sender"); JSONObject jsubject = jcondition.optJSONObject("subject"); + JSONObject jheader = jcondition.optJSONObject("header"); etName.setText(rule == null ? null : rule.name); etOrder.setText(rule == null ? null : Integer.toString(rule.order)); @@ -217,6 +222,8 @@ public class FragmentRule extends FragmentBase { cbSender.setChecked(jsender != null && jsender.optBoolean("regex", false)); etSubject.setText(jsubject == null ? null : jsubject.optString("value")); cbSubject.setChecked(jsubject != null && jsubject.optBoolean("regex", false)); + etHeader.setText(jheader == null ? null : jheader.optString("value")); + cbHeader.setChecked(jheader != null && jheader.optBoolean("regex", false)); int type = jaction.optInt("type", -1); for (int pos = 0; pos < adapterAction.getCount(); pos++) @@ -329,6 +336,14 @@ public class FragmentRule extends FragmentBase { jcondition.put("subject", jsubject); } + String header = etHeader.getText().toString(); + if (!TextUtils.isEmpty(header)) { + JSONObject jheader = new JSONObject(); + jheader.put("value", header); + jheader.put("regex", cbHeader.isChecked()); + jcondition.put("header", jheader); + } + JSONObject jaction = new JSONObject(); Action action = (Action) spAction.getSelectedItem(); @@ -378,8 +393,9 @@ public class FragmentRule extends FragmentBase { JSONObject jcondition = new JSONObject(condition); JSONObject jsender = jcondition.optJSONObject("sender"); JSONObject jsubject = jcondition.optJSONObject("subject"); + JSONObject jheader = jcondition.optJSONObject("header"); - if (jsender == null && jsubject == null) + if (jsender == null && jsubject == null && jheader == null) throw new IllegalArgumentException(context.getString(R.string.title_rule_condition_missing)); if (TextUtils.isEmpty(order)) diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 59099e1f6e..f35651f478 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -2589,7 +2589,7 @@ public class ServiceSynchronize extends LifecycleService { if (filter) for (EntityRule rule : rules) - if (rule.matches(context, message)) { + if (rule.matches(context, message, imessage)) { rule.execute(context, db, message); if (rule.stop) break; diff --git a/app/src/main/res/layout/fragment_rule.xml b/app/src/main/res/layout/fragment_rule.xml index 919c51dd1f..407463fa3c 100644 --- a/app/src/main/res/layout/fragment_rule.xml +++ b/app/src/main/res/layout/fragment_rule.xml @@ -104,6 +104,7 @@ android:id="@+id/etSender" android:layout_width="0dp" android:layout_height="wrap_content" + android:hint="@string/title_optional" android:inputType="textEmailAddress" android:textAppearance="@style/TextAppearance.AppCompat.Medium" app:layout_constraintEnd_toEndOf="parent" @@ -148,12 +149,58 @@ android:id="@+id/etSubject" android:layout_width="0dp" android:layout_height="wrap_content" - android:inputType="textEmailAddress" + android:hint="@string/title_optional" + android:inputType="text" android:textAppearance="@style/TextAppearance.AppCompat.Medium" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/cbSubject" /> + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/etHeader" /> - - + app:layout_constraintTop_toBottomOf="@id/spAction" /> + app:constraint_referenced_ids="tvName,etName,tvOrder,etOrder,cbEnabled,cbStop,tvSender,cbSender,etSender,tvAndSender,tvSubject,cbSubject,etSubject,tvAction,spAction" /> + app:constraint_referenced_ids="spTarget" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bf003bcbf4..fcfd8763cd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -390,8 +390,6 @@ Regex AND Action - To - Mark as read Rule name missing Condition missing