[pmg-devel] [PATCH v2 pmg-log-tracker 2/3] fix SEntry filter in before-queue case

Mira Limbeck m.limbeck at proxmox.com
Fri Mar 20 13:08:28 CET 2020


With before-queue filtering if we don't accept the mail (e.g.
quarantine), we don't have a queue which means we don't have a QEntry,
so the SEntry has to handle the filter entries (ToEntrys).

This means we can't just return from print() when either a 'from' or 'to'
filter is set or we exclude greylist entries or NDRs and no Noqueue entries
exist or no entry matches any of the filters.

So continue printing if there is no filter parameter set, but an FEntry
reference in the SEntry. If there's an FEntry reference, compare all ToEntrys
to the filter parameter and return if there is no match at all.

Signed-off-by: Mira Limbeck <m.limbeck at proxmox.com>
---
 src/main.rs | 99 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 68 insertions(+), 31 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index aeb390f..3baa0dc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -827,6 +827,72 @@ impl SEntry {
         }
     }
 
+    // if either 'from' or 'to' are set, check if it matches, if not, set
+    // the status of the noqueue entry to Invalid
+    // if exclude_greylist or exclude_ndr are set, check if it matches
+    // and if so, set the status to Invalid so they are no longer included
+    // don't print if any Invalid entry is found
+    fn filter_matches(&mut self, parser: &Parser) -> bool {
+        if !parser.options.from.is_empty()
+            || !parser.options.to.is_empty()
+            || parser.options.exclude_greylist
+            || parser.options.exclude_ndr
+        {
+            let mut found = false;
+            for nq in self.nq_entries.iter_mut().rev() {
+                if (!parser.options.from.is_empty()
+                    && find_lowercase(&nq.from, parser.options.from.as_bytes()).is_none())
+                    || (parser.options.exclude_greylist && nq.dstatus == DStatus::Greylist)
+                    || (parser.options.exclude_ndr && nq.from.is_empty())
+                    || (!parser.options.to.is_empty()
+                        && !nq.to.is_empty()
+                        && find_lowercase(&nq.to, parser.options.to.as_bytes()).is_none())
+                {
+                    nq.dstatus = DStatus::Invalid;
+                }
+
+                if nq.dstatus != DStatus::Invalid {
+                    found = true;
+                }
+            }
+
+            // self.filter only contains an object in the before-queue case
+            // as we have the FEntry referenced in the SEntry when there's no
+            // queue involved, we can't just check the Noqueue entries, but
+            // have to check for a filter and if it exists, we have to check
+            // them for matching 'from' and 'to' if either of those options
+            // are set.
+            // if neither of them is filtered, we can skip this check
+            if let Some(fe) = &self.filter() {
+                let is_filtered = !parser.options.from.is_empty() || !parser.options.to.is_empty();
+                let from_match = !parser.options.from.is_empty()
+                    && find_lowercase(&self.bq_from, parser.options.from.as_bytes()).is_some();
+                let to_option_set = !parser.options.to.is_empty();
+                if !is_filtered && fe.borrow().is_bq && !fe.borrow().is_accepted {
+                    for to in fe.borrow().to_entries.iter() {
+                        if from_match
+                            || (to_option_set
+                                && find_lowercase(&to.to, parser.options.to.as_bytes()).is_some())
+                        {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if !found && is_filtered {
+                        return false;
+                    }
+                }
+            }
+
+            // we can early exit the printing if there's no valid Noqueue entry
+            // and we're in the after-queue case
+            if !found && self.filter.is_none() {
+                return false;
+            }
+        }
+        true
+    }
+
     fn print(&mut self, parser: &mut Parser) {
         // don't print if the output is filtered by the message-id
         // the message-id is only available in a QEntry
@@ -865,37 +931,8 @@ impl SEntry {
             }
         }
 
-        // if either ;from' or 'to' are set, check if it matches, if not, set
-        // the status of the noqueue entry to Invalid
-        // if exclude_greylist or exclude_ndr are set, check if it matches
-        // and if so, set the status to Invalid so they are no longer included
-        // don't print if any Invalid entry is found
-        if !parser.options.from.is_empty()
-            || !parser.options.to.is_empty()
-            || parser.options.exclude_greylist
-            || parser.options.exclude_ndr
-        {
-            let mut found = false;
-            for nq in self.nq_entries.iter_mut().rev() {
-                if (!parser.options.from.is_empty()
-                    && find_lowercase(&nq.from, parser.options.from.as_bytes()).is_none())
-                    || (parser.options.exclude_greylist && nq.dstatus == DStatus::Greylist)
-                    || (parser.options.exclude_ndr && nq.from.is_empty())
-                    || (!parser.options.to.is_empty()
-                        && !nq.to.is_empty()
-                        && find_lowercase(&nq.to, parser.options.to.as_bytes()).is_none())
-                {
-                    nq.dstatus = DStatus::Invalid;
-                }
-
-                if nq.dstatus != DStatus::Invalid {
-                    found = true;
-                }
-            }
-
-            if !found {
-                return;
-            }
+        if !self.filter_matches(parser) {
+            return;
         }
 
         // don't print if there's a string match specified, but none of the
-- 
2.20.1




More information about the pmg-devel mailing list