From 0aa628dc994398615088c80c2df17897d8b4ba8b Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 29 Apr 2024 15:32:58 +0200 Subject: [PATCH] Added Jsoup expression function --- FAQ.md | 1 + .../java/eu/faircode/email/EntityRule.java | 33 +++++++++++++++++++ index.html | 1 + 3 files changed, 35 insertions(+) diff --git a/FAQ.md b/FAQ.md index 393e3344db..a5e425ea7e 100644 --- a/FAQ.md +++ b/FAQ.md @@ -2779,6 +2779,7 @@ The following extra functions are available: * *onBlocklist()* (returns a boolean indicating if the sender/server is on a DNS blocklist; since version 1.2179) * *hasMx()* (returns a boolean indicating if the from/reply-to address has an associated MX record; since version 1.2179) * *attachments()* (returns an integer indicating number of attachments; since version 1.2179) +* *Jsoup()* (returns an array of selected strings; since version 1.2179) Example conditions: diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index a727b53180..5a5e144ef3 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -788,6 +788,37 @@ public class EntityRule { } } + @FunctionParameter(name = "value") + public static class JsoupFunction extends AbstractFunction { + private final Context context; + private final EntityMessage message; + + JsoupFunction(Context context, EntityMessage message) { + this.context = context; + this.message = message; + } + + @Override + public EvaluationValue evaluate( + Expression expression, Token functionToken, EvaluationValue... parameterValues) { + List result = new ArrayList<>(); + + if (message != null && message.content && parameterValues.length == 1) + try { + String query = parameterValues[0].getStringValue(); + File file = message.getFile(context); + Document d = JsoupEx.parse(file); + for (Element element : d.select(query)) + result.add(element.text()); + } catch (Throwable ex) { + Log.e("EXPR", ex); + } + + Log.i("EXPR jsoup(" + parameterValues[0] + ")=" + TextUtils.join(", ", result)); + return new EvaluationValue(result, ExpressionConfiguration.defaultConfiguration()); + } + } + @InfixOperator(precedence = OPERATOR_PRECEDENCE_COMPARISON) public static class ContainsOperator extends AbstractOperator { private final boolean regex; @@ -871,6 +902,7 @@ public class EntityRule { BlocklistFunction fBlocklist = new BlocklistFunction(context, message, headers); MxFunction fMx = new MxFunction(context, message); AttachmentsFunction fAttachments = new AttachmentsFunction(context, message); + JsoupFunction fJsoup = new JsoupFunction(context, message); ContainsOperator oContains = new ContainsOperator(false); ContainsOperator oMatches = new ContainsOperator(true); @@ -883,6 +915,7 @@ public class EntityRule { configuration.getFunctionDictionary().addFunction("onBlocklist", fBlocklist); configuration.getFunctionDictionary().addFunction("hasMx", fMx); configuration.getFunctionDictionary().addFunction("attachments", fAttachments); + configuration.getFunctionDictionary().addFunction("Jsoup", fJsoup); configuration.getOperatorDictionary().addOperator("Contains", oContains); configuration.getOperatorDictionary().addOperator("Matches", oMatches); diff --git a/index.html b/index.html index 435c983671..bdceee734c 100644 --- a/index.html +++ b/index.html @@ -1520,6 +1520,7 @@ X-Google-Original-From: Somebody <somebody+extra@example.org>
  • onBlocklist() (returns a boolean indicating if the sender/server is on a DNS blocklist; since version 1.2179)
  • hasMx() (returns a boolean indicating if the from/reply-to address has an associated MX record; since version 1.2179)
  • attachments() (returns an integer indicating number of attachments; since version 1.2179)
  • +
  • Jsoup() (returns an array of selected strings; since version 1.2179)
  • Example conditions:

    header("X-Mailer") contains "Open-Xchange" && from matches ".*service@.*"