aboutsummaryrefslogtreecommitdiffstats
path: root/mailctl.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-12 11:43:36 +0200
committerDanilo M. <danix@danix.xyz>2026-08-12 11:43:36 +0200
commitf479318ea8f890122f2f28a7a224802dbf4e870b (patch)
treeaf0bfba5dde4e1ad07560fa8e937393ae856ff95 /mailctl.py
parentf1890fc7b5fe1094445ce8b83c2d2f15258fceec (diff)
downloadmailctl-f479318ea8f890122f2f28a7a224802dbf4e870b.tar.gz
mailctl-f479318ea8f890122f2f28a7a224802dbf4e870b.zip
feat(rules): dry-run counts what a rule matches
Two numbers per rule: what it matches across all mail, and what it would tag on the next sync. The first is what decides whether a rule is still earning its place.
Diffstat (limited to 'mailctl.py')
-rwxr-xr-xmailctl.py27
1 files changed, 27 insertions, 0 deletions
diff --git a/mailctl.py b/mailctl.py
index ea31286..550e56c 100755
--- a/mailctl.py
+++ b/mailctl.py
@@ -509,6 +509,27 @@ def cmd_rules_show(args):
sys.exit(1)
+def cmd_rules_dry_run(args):
+ """What each rule matches right now. Two numbers, because they answer
+ different questions: the corpus count says whether a rule is still doing
+ anything and whether it would bury real correspondence, the pending count
+ says what the next sync would tag."""
+ store = mailrules.load()
+ rules = [r for r in store.rules if not args.id or r.id == args.id]
+ if not rules:
+ print(f"No rule with id '{args.id}'", file=sys.stderr)
+ sys.exit(1)
+
+ print(f"{'rule':<28} {'corpus':>8} {'pending':>8}")
+ for rule in rules:
+ corpus = run_notmuch(["count", mailrules.scoped_query(rule, None)])
+ pending = run_notmuch(["count",
+ mailrules.scoped_query(rule, "tag:new")])
+ state = "" if rule.enabled else " (disabled)"
+ print(f"{rule.id:<28.28} {corpus.strip():>8} "
+ f"{pending.strip():>8}{state}")
+
+
def build_parser():
p = argparse.ArgumentParser(
prog="mailctl",
@@ -600,6 +621,12 @@ def build_parser():
rp.add_argument("id")
rp.set_defaults(func=cmd_rules_show)
+ rp = rules_sub.add_parser("dry-run",
+ help="count what each rule matches, changing "
+ "nothing")
+ rp.add_argument("id", nargs="?", help="one rule, default is all")
+ rp.set_defaults(func=cmd_rules_dry_run)
+
return p