Added rule not header condition

This commit is contained in:
M66B 2024-04-15 09:11:36 +02:00
parent 6fef2235fd
commit 80692be12d
3 changed files with 117 additions and 92 deletions

View File

@ -349,99 +349,15 @@ public class EntityRule {
// Header
JSONObject jheader = jcondition.optJSONObject("header");
if (jheader != null) {
boolean not = jheader.optBoolean("not");
String value = jheader.getString("value");
boolean regex = jheader.getBoolean("regex");
if (!regex &&
value.startsWith("$") &&
value.endsWith("$")) {
String keyword = value.substring(1, value.length() - 1);
if ("$tls".equals(keyword)) {
if (!Boolean.TRUE.equals(message.tls))
return false;
} else if ("$aligned".equals(keyword)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean native_dkim = prefs.getBoolean("native_dkim", false);
if (!native_dkim)
return false;
if (message.signedby == null)
return false;
if (message.from == null || message.from.length != 1)
return false;
String domain = UriHelper.getEmailDomain(((InternetAddress) message.from[0]).getAddress());
if (domain == null)
return false;
boolean valid = false;
for (String signer : message.signedby.split(","))
if (Objects.equals(
UriHelper.getRootDomain(context, signer),
UriHelper.getRootDomain(context, domain))) {
valid = true;
break;
}
if (!valid)
return false;
} else if ("$dkim".equals(keyword)) {
if (!Boolean.TRUE.equals(message.dkim))
return false;
} else if ("$spf".equals(keyword)) {
if (!Boolean.TRUE.equals(message.spf))
return false;
} else if ("$dmarc".equals(keyword)) {
if (!Boolean.TRUE.equals(message.dmarc))
return false;
} else if ("$auth".equals(keyword)) {
if (!Boolean.TRUE.equals(message.auth))
return false;
} else if ("$mx".equals(keyword)) {
if (!Boolean.TRUE.equals(message.mx))
return false;
} else if ("$blocklist".equals(keyword)) {
if (!Boolean.FALSE.equals(message.blocklist))
return false;
} else if ("$replydomain".equals(keyword)) {
if (!Boolean.TRUE.equals(message.reply_domain))
return false;
} else if ("$nofrom".equals(keyword)) {
if (message.from != null && message.from.length > 0)
return false;
} else if ("$multifrom".equals(keyword)) {
if (message.from == null || message.from.length < 2)
return false;
} else if ("$automatic".equals(keyword)) {
if (!Boolean.TRUE.equals(message.auto_submitted))
return false;
} else if ("$lowpriority".equals(keyword)) {
if (!EntityMessage.PRIORITIY_LOW.equals(message.priority))
return false;
} else if ("$highpriority".equals(keyword)) {
if (!EntityMessage.PRIORITIY_HIGH.equals(message.priority))
return false;
} else if ("$signed".equals(keyword)) {
if (!message.isSigned())
return false;
} else if ("$encrypted".equals(keyword)) {
if (!message.isEncrypted())
return false;
} else {
List<String> keywords = new ArrayList<>();
keywords.addAll(Arrays.asList(message.keywords));
if (message.ui_seen)
keywords.add("$seen");
if (message.ui_answered)
keywords.add("$answered");
if (message.ui_flagged)
keywords.add("$flagged");
if (message.ui_deleted)
keywords.add("$deleted");
if (message.infrastructure != null)
keywords.add('$' + message.infrastructure);
if (!keywords.contains(keyword))
return false;
}
if (matchKeywords(context, message, value) != not)
return false;
} else {
if (headers == null) {
if (message.headers == null)
@ -459,7 +375,7 @@ public class EntityRule {
break;
}
}
if (!matches)
if (matches == not)
return false;
}
}
@ -566,6 +482,98 @@ public class EntityRule {
return true;
}
private static boolean matchKeywords(Context context, EntityMessage message, String value) {
String keyword = value.substring(1, value.length() - 1);
if ("$tls".equals(keyword)) {
if (!Boolean.TRUE.equals(message.tls))
return true;
} else if ("$aligned".equals(keyword)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean native_dkim = prefs.getBoolean("native_dkim", false);
if (!native_dkim)
return true;
if (message.signedby == null)
return true;
if (message.from == null || message.from.length != 1)
return true;
String domain = UriHelper.getEmailDomain(((InternetAddress) message.from[0]).getAddress());
if (domain == null)
return true;
boolean valid = false;
for (String signer : message.signedby.split(","))
if (Objects.equals(
UriHelper.getRootDomain(context, signer),
UriHelper.getRootDomain(context, domain))) {
valid = true;
break;
}
if (!valid)
return true;
} else if ("$dkim".equals(keyword)) {
if (!Boolean.TRUE.equals(message.dkim))
return true;
} else if ("$spf".equals(keyword)) {
if (!Boolean.TRUE.equals(message.spf))
return true;
} else if ("$dmarc".equals(keyword)) {
if (!Boolean.TRUE.equals(message.dmarc))
return true;
} else if ("$auth".equals(keyword)) {
if (!Boolean.TRUE.equals(message.auth))
return true;
} else if ("$mx".equals(keyword)) {
if (!Boolean.TRUE.equals(message.mx))
return true;
} else if ("$blocklist".equals(keyword)) {
if (!Boolean.FALSE.equals(message.blocklist))
return true;
} else if ("$replydomain".equals(keyword)) {
if (!Boolean.TRUE.equals(message.reply_domain))
return true;
} else if ("$nofrom".equals(keyword)) {
if (message.from != null && message.from.length > 0)
return true;
} else if ("$multifrom".equals(keyword)) {
if (message.from == null || message.from.length < 2)
return true;
} else if ("$automatic".equals(keyword)) {
if (!Boolean.TRUE.equals(message.auto_submitted))
return true;
} else if ("$lowpriority".equals(keyword)) {
if (!EntityMessage.PRIORITIY_LOW.equals(message.priority))
return true;
} else if ("$highpriority".equals(keyword)) {
if (!EntityMessage.PRIORITIY_HIGH.equals(message.priority))
return true;
} else if ("$signed".equals(keyword)) {
if (!message.isSigned())
return true;
} else if ("$encrypted".equals(keyword)) {
if (!message.isEncrypted())
return true;
} else {
List<String> keywords = new ArrayList<>();
keywords.addAll(Arrays.asList(message.keywords));
if (message.ui_seen)
keywords.add("$seen");
if (message.ui_answered)
keywords.add("$answered");
if (message.ui_flagged)
keywords.add("$flagged");
if (message.ui_deleted)
keywords.add("$deleted");
if (message.infrastructure != null)
keywords.add('$' + message.infrastructure);
if (!keywords.contains(keyword))
return true;
}
return false;
}
private boolean matches(Context context, EntityMessage message, String needle, String haystack, boolean regex) {
boolean matched = false;
if (needle != null && haystack != null)

View File

@ -111,6 +111,7 @@ public class FragmentRule extends FragmentBase {
private CheckBox cbAttachments;
private EditText etMimeType;
private CheckBox cbHeaderNot;
private EditText etHeader;
private ImageButton ibHeader;
private CheckBox cbHeader;
@ -310,6 +311,7 @@ public class FragmentRule extends FragmentBase {
cbAttachments = view.findViewById(R.id.cbAttachments);
etMimeType = view.findViewById(R.id.etMimeType);
cbHeaderNot = view.findViewById(R.id.cbHeaderNot);
etHeader = view.findViewById(R.id.etHeader);
ibHeader = view.findViewById(R.id.ibHeader);
cbHeader = view.findViewById(R.id.cbHeader);
@ -1259,6 +1261,7 @@ public class FragmentRule extends FragmentBase {
etMimeType.setText(jcondition.optString("mimetype"));
etMimeType.setEnabled(cbAttachments.isChecked());
cbHeaderNot.setChecked(jheader != null && jheader.optBoolean("not"));
etHeader.setText(jheader == null ? null : jheader.getString("value"));
cbHeader.setChecked(jheader != null && jheader.getBoolean("regex"));
@ -1665,6 +1668,7 @@ public class FragmentRule extends FragmentBase {
String header = etHeader.getText().toString();
if (!TextUtils.isEmpty(header)) {
JSONObject jheader = new JSONObject();
jheader.put("not", cbHeaderNot.isChecked());
jheader.put("value", header);
jheader.put("regex", cbHeader.isChecked());
jcondition.put("header", jheader);

View File

@ -455,15 +455,27 @@
app:layout_constraintTop_toBottomOf="@id/tvMimeType" />
<TextView
android:id="@+id/tvAndAttachments"
android:id="@+id/tvHeaderCondition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/title_rule_and"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintBottom_toBottomOf="@+id/cbHeaderNot"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/cbHeaderNot" />
<CheckBox
android:id="@+id/cbHeaderNot"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="24dp"
android:text="@string/title_rule_not"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tvHeaderCondition"
app:layout_constraintTop_toBottomOf="@+id/etMimeType" />
<View
@ -472,7 +484,7 @@
android:layout_height="1dp"
android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvAndAttachments" />
app:layout_constraintTop_toBottomOf="@id/cbHeaderNot" />
<TextView
android:id="@+id/tvHeader"
@ -1383,7 +1395,8 @@
vSeparatorRecipient,tvRecipient,cbRecipient,etRecipient,ibRecipient,
tvSubjectCondition,cbSubjectNot,
vSeparatorSubject,tvSubject,cbSubject,etSubject,tvAndSubject,
vSeparatorAttachments,cbAttachments,tvMimeType,etMimeType,tvAndAttachments,
vSeparatorAttachments,cbAttachments,tvMimeType,etMimeType,
tvHeaderCondition,cbHeaderNot,
vSeparatorHeader,tvHeader,ibHeader,cbHeader,etHeader,
tvBodyCondition,cbBodyNot,
vSeparatorBody,tvBody,cbBody,etBody,tvBodyRemark,cbSkipQuotes,tvAndBody,