A collection of a builder and various scripts creating the sites
git clone
Log | Files | README | LICENSE

commit: 7ec3fe97bbbf2e15825f2288526ed1da8915304e
parent: bee708b82f61322eacc72052e2f8ac0861015bef
author: Chris Noxz <>
date:   Sat, 11 Jun 2022 20:20:35 +0200
add new article about mail filters
4 files changed, 140 insertions(+)
diff --git a/ b/
@@ -4,6 +4,13 @@ Articles
 .DIVS articles
+.URL "simple_way_to_filter_email" "Simple way to filter email"
+posted on
+.B "2022-06-11"
+.B "Chris Noxz"
 .URL "askpass_implementation_for_doas" "Askpass implementation for doas"
 posted on
diff --git a/ b/
@@ -0,0 +1 @@
diff --git a/ b/
diff --git a/ b/
@@ -0,0 +1,132 @@
+.HnS 0
+Simple way to filter email
+posted on
+.B "2022-06-11"
+.B "Chris Noxz"
+Having a lot of different types of email had bugged me for some time, so I 
+sought to find a solution to this problem. The logical way of solving this would
+be to somehow filter email automatically into directories based on the type of 
+email, i.e., sender, list id, subject, etc.
+I looked into various already available solutions like procmail, notmuch, and 
+alike. The problem with these ways of solving the issue was that they were 
+overly complicated for the problem I needed to solve.
+So, I did what I usually do and implemented my own solution instead. As I only 
+wanted to filter email, both new and old ones, by various header data and their 
+age, I only needed to use
+.ICD awk ,
+.ICD grep ,
+.ICD find ,
+.ICD mv .
+To keep it somewhat structured, I wrote everything as a POSIX compliant script, 
+which I programmed to accept a configuration file. As I’m using maildir to store
+my email I made sure the script moved each email based on the directory it 
+resides in \(en
+.I new ,
+.I cur ,
+.I tmp .
+This is the script I came up with (feel free to use it as you like):
+# Copyright © 2022 Chris Noxz <>
+# This work is free. You can redistribute it and/or modify it under the
+# terms of the Do What The Fuck You Want To Public License, Version 2,
+# as published by Sam Hocevar. See for more details.
+# declare default configuration variables
+# This script is used for applying sorting/filtering rules to maildirs
+# Use the following format for rules:
+# src|pat|dst
+# src: source directory relative to MAILDIR eg. INBOX or
+# pat: regex pattern applied to mail header eg. ^From:.*
+# dst: destination directory relative to MAILDIR eg. Archive or My/Mail
+# example rule: INBOX|^From:.*|github
+# this moves mail from INBOX to github retrieved from the domain
+# age based patterns can be used for archiving old emails ($AGE+<days>).
+# example rule: INBOX|$AGE+365|Archive
+# this archives mail from INBOX to Archive that are 365 days or older
+# rules are read from ~/.config/mfrc by default
+# extract rules from rule file based on pattern "src|pat|dst"
+grep -o "^[^#][^|]\\+|[^|]\\+|[^|]\\+$" "${MAILFILTERRC}" | while read -r rule; do
+	# extract source directory
+	src="${MAILDIR}/${rule%%|*}"
+	# extract destination directory
+	dst="${MAILDIR}/${rule##*|}"
+	# extract pattern
+	ptn="${rule#*|}"
+	ptn="${ptn%%|*}"
+	# validate input (at least somewhat)
+	[ ! -d "${src}" ] && continue   # skip if source doesn't exist
+	[ ! -d "${dst}" ] && continue   # skip if destination doesn't exist
+	[ -z "${ptn}" ] && continue     # skip if rule is empty
+	# check if age based rule: ^$AGE+...
+	if echo "${ptn}" | grep "^\\$AGE+" >/dev/null; then
+		age="${ptn##*+}"
+		if [ -n "$age" ] && [ "$age" -eq "$age" 2>/dev/null ]; then
+			# find file/mail based on age and move file/mail into correct
+			# subdirectory at destination
+			find "${src}"/* -maxdepth 1 -mtime +"${age}" -type f -exec \\
+			sh -c "f=\\"{}\\"; mv \\"\\${f}\\" \\"${dst}/\\$(dirname \\"\\${f}\\" | xargs basename)/\\"" \\;
+		fi
+		continue # done with this rule, continue with the next one
+	fi
+	# find pattern in file/mail until first empty line (only check header)...
+	awk "/^$/{nextfile} /${ptn}/{print FILENAME; nextfile}" "${src}"/*/* |\\
+	while read -r f; do
+		# ...and move file/mail into correct subdirectory at destination
+		mv "$f" "${dst}/$(dirname "${f}" | xargs basename)/"
+	done
+Rules created in the
+.ICD mfrc
+file can look like this:
+# === ===
+# =======================
+# move messages from|^From:.*|
+# move messages from list:|^List-Id:.*|
+# move 10 day old messages from INBOX to Archive|$AGE+10|
+I can now run the script either on demand or automatically each time I run
+.ICD mbsync
+to retrieve new email. As it turned out, it was easier to create my own script 
+instead of using an existing way of solving my problem. This solution, however,
+is not the most efficient because every email is examined each time the script 
+runs, rather than just the new ones. This could, of course, be fixed, but would
+mean I would have to create a new function for executing the filter on every 
+email as well.