noxz-sites

A collection of a builder and various scripts creating the noxz.tech sites
git clone https://noxz.tech/git/noxz-sites.git
noxz-sites

commit: 7ec3fe97bbbf2e15825f2288526ed1da8915304e
parent: bee708b82f61322eacc72052e2f8ac0861015bef
author: Chris Noxz <chris@noxz.tech>
date:   Sat, 11 Jun 2022 20:20:35 +0200
add new article about mail filters
Mnoxz.tech/articles/index.www7++
Anoxz.tech/articles/simple_way_to_filter_email/.assemble1+
Anoxz.tech/articles/simple_way_to_filter_email/.buildignore0
Anoxz.tech/articles/simple_way_to_filter_email/index.www132++++++++++++++++++++
4 files changed, 140 insertions(+)
diff --git a/noxz.tech/articles/index.www b/noxz.tech/articles/index.www
@@ -4,6 +4,13 @@ Articles
 
 .DIVS articles
 .ULS
+.LI
+.URL "simple_way_to_filter_email" "Simple way to filter email"
+posted on
+.B "2022-06-11"
+by
+.B "Chris Noxz"
+
 .LI
 .URL "askpass_implementation_for_doas" "Askpass implementation for doas"
 posted on
diff --git a/noxz.tech/articles/simple_way_to_filter_email/.assemble b/noxz.tech/articles/simple_way_to_filter_email/.assemble
@@ -0,0 +1 @@
+index.html
diff --git a/noxz.tech/articles/simple_way_to_filter_email/.buildignore b/noxz.tech/articles/simple_way_to_filter_email/.buildignore
diff --git a/noxz.tech/articles/simple_way_to_filter_email/index.www b/noxz.tech/articles/simple_way_to_filter_email/index.www
@@ -0,0 +1,132 @@
+.HnS 0
+Simple way to filter email
+.HnE
+
+posted on
+.B "2022-06-11"
+by
+.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 ,
+and
+.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 ,
+or
+.I tmp .
+
+This is the script I came up with (feel free to use it as you like):
+
+.CDS
+.COS
+#!/bin/sh
+
+# Copyright © 2022 Chris Noxz <chris@noxz.tech>
+# 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 http://www.wtfpl.net/ for more details.
+
+# declare default configuration variables
+MAILDIR="${MAILDIR:-"${HOME}/mail"}"
+MAILFILTERRC="${MAILFILTERRC:-"${HOME}/.config/mfrc"}"
+
+# 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 me@domain.com/INBOX
+# pat: regex pattern applied to mail header eg. ^From:.*me@domain.com
+# dst: destination directory relative to MAILDIR eg. Archive or My/Mail
+# example rule: INBOX|^From:.*github.com|github
+# this moves mail from INBOX to github retrieved from the domain github.com
+#
+# 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
+done
+.COE
+.CDE
+
+Rules created in the
+.ICD mfrc
+file can look like this:
+
+.CDS
+.COS
+# === chris@noxz.tech ===
+# =======================
+
+# move messages from github.com
+chris@noxz.tech/INBOX|^From:.*github.com|chris@noxz.tech/github
+
+# move messages from list: wiki.suckless.org
+chris@noxz.tech/INBOX|^List-Id:.*wiki.suckless.org|chris@noxz.tech/suckless-mailing-list/wiki
+
+# move 10 day old messages from INBOX to Archive
+chris@noxz.tech/INBOX|$AGE+10|chris@noxz.tech/Archive
+.COE
+.CDE
+
+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.