Browse Source

WIP

* maildroprc needs external binaries in sensible location (maybe /opt) and mail and sub lists in /var
* .fetchmailrc needs to do auth better
* cropswap-sendmail.sh needs debug statements removed or log to syslog
* cropswap-replymail.sh needs to be removed or renamed to cropswap-debug.sh
*
Pi 1 year ago
commit
8dc66d9595
6 changed files with 243 additions and 0 deletions
  1. 17 0
      .fetchmailrc
  2. 28 0
      cropswap-postmaster.sh
  3. 9 0
      cropswap-replymail.sh
  4. 41 0
      cropswap-sendmail.sh
  5. 9 0
      cropswap-subunsub.sh
  6. 139 0
      maildroprc

+ 17 - 0
.fetchmailrc

@@ -0,0 +1,17 @@
+#set daemon 30
+set postmaster pi
+set syslog
+
+poll imap.mailserver.com with protocol IMAP service 993 ;
+    username "USER", with password "PASSWORD", is "pi" here;
+    ssl;
+#    idle;
+    folder "Inbox/Crop Swap Mail Incoming" keep fetchall;
+
+
+mda "/usr/bin/maildrop -f%F"
+
+
+#localdomains cropswap.shandan.one,shandan.one,raspberrypi,raspberrypi.local,localhost,localdomain
+
+

+ 28 - 0
cropswap-postmaster.sh

@@ -0,0 +1,28 @@
+#!/bin/bash
+set -euo pipefail
+
+ACTION="$1"
+ALIAS="$2"
+FROM="$3"
+
+if [ "$ACTION" == "SIGNUP" ]; then
+	TO=postmaster@localhost
+	HEADER="X-MEMBER-ALIAS: $ALIAS"
+else
+	TO=cropswap@shandan.one
+	HEADER="X-IGNORED:"
+fi
+
+#
+# Ideally, FROM should be "postmaster" or "root" or something
+# but to keep the logic (at this time) simpler
+# I impersonate the user
+#
+# However, the origin of these e-mails are still disambiguated
+# by the "From: " header
+maildrop -f "$FROM" <<EOF
+From: postmaster@localhost
+To: ${TO}
+Subject: [${ACTION}]
+${HEADER}
+EOF

+ 9 - 0
cropswap-replymail.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+set -euo pipefail
+MAIL="$(cat -)"
+cat <<EOF > /home/pi/reply
+$(env)
+
+${MAIL}
+EOF
+

+ 41 - 0
cropswap-sendmail.sh

@@ -0,0 +1,41 @@
+#!/bin/bash
+set -euo pipefail
+MAIL="$(cat -)"
+echo "${MAIL}" > /home/pi/original
+
+declare -A SUBSCRIBED
+declare -a actions
+update(){
+	da="${actions[$1-1]:0:1}"
+        db="${2:0:1}"
+	alias="${actions[$1-1]#?}"
+	email="${2#?}"
+	
+	if [ "$da" == "$db" ]; then
+		[ "$da" == "+" ] && SUBSCRIBED["$email"]="$alias" || SUBSCRIBED["$email"]=""
+	else
+		# corrupt list
+		exit 1
+	fi
+}
+
+touch "${SLIST}.txt"
+mapfile -t -c 2 -C update actions < "${SLIST}.txt"
+
+(for email in "${!SUBSCRIBED[@]}"; do
+	if [ -z "${SUBSCRIBED["$email"]}" ]; then continue; fi
+	echo "+$alias"
+        echo "+$email"
+        if [ "${email,,}" == "${NOFORWARD,,}" ]; then continue; fi
+	formail -rkb \
+		-A "Reply-to: ${FROM} <cropswap@shandan.one>" \
+		-i "MIME-Version:" \
+		-i "Content-Type:" \
+	<<<"${MAIL}" \
+	>> /home/pi/reformail
+	#cat /home/pi/reformail | /usr/sbin/sendmail \
+	#	-F "${sendr}" \
+	#	-f "cropswap@shandan.one" \
+	#	-v "${addr}"
+done) > "${SLIST}.txt"
+#TODO: report errors properly

+ 9 - 0
cropswap-subunsub.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+set -euo pipefail
+if [ "${1}" == "UNSUBSCRIBE" ]; then
+	d="-"
+else
+	d="+"
+fi
+printf "%c%s\n%c%s\n" "$d" "$2" "$d" "$3" >> "${SLIST}.txt"
+#TODO: mailbot - You have been successfully (un)subscribed

+ 139 - 0
maildroprc

@@ -0,0 +1,139 @@
+# Global maildrop filter file
+
+# Uncomment this line to make maildrop default to ~/Maildir for
+# delivery- this is where courier-imap (amongst others) will look.
+#DEFAULT="$HOME/Maildir"
+SHELL="/bin/bash"
+SENDMAIL="/home/pi/cropswap-sendmail.sh"
+REPLYMAIL="/home/pi/cropswap-replymail.sh"
+MLIST="/home/pi/mlist"
+SLIST="/home/pi/slist"
+SUBUNSUB="/home/pi/cropswap-subunsub.sh"
+
+SUFFIX=0
+
+HANDLE=0
+FORWARD=0
+SUBSCRIBE=""
+CONTINUE=0
+
+UNHANDLED=5
+BADREQUEST=4
+UNREGISTERED=3
+UNSUBSCRIBED=2
+FATAL=1
+
+foreach /^(To|Cc):.*/
+{
+   ADDR=getaddr($MATCH)
+   foreach $ADDR =~ /^postmaster@localhost$/
+   {
+      CONTINUE=1
+      HANDLE=1
+   }
+   foreach $ADDR =~ /^cropswap@shandan\.one$/
+   {
+      CONTINUE=1
+   }
+}
+if (!$CONTINUE)
+{
+   EXITCODE=$UNHANDLED
+   exit
+}
+
+if ($HANDLE)
+{
+   if (/^Subject:\s*\[SIGNUP\]\s*$/)
+   {
+      if (/^X-MEMBER-ALIAS:\s*(.*)\s*$/)
+      {
+         gdbmopen($MLIST, "W")
+         ALIAS=$MATCH1
+         KEY=$ALIAS
+         EXISTS=gdbmfetch($ALIAS)
+         while ($EXISTS ne "" && $EXISTS ne gdbmfetch(tolower($FROM)))
+         {
+            SUFFIX=($SUFFIX + 1)
+            KEY="$ALIAS $SUFFIX"
+            EXISTS=gdbmfetch($KEY)
+         }
+         if (gdbmstore(tolower($FROM), $ALIAS) == 0 && gdbmstore($ALIAS, tolower($FROM)) == 0)
+         {
+            gdbmclose
+            #TODO: mailbot - You have been registered as $ALIAS
+            exit
+         }
+         else
+         {
+            gdbmclose
+            EXITCODE=$FATAL
+            exit
+         }
+      }
+      EXITCODE=$BADREQUEST
+      # No response to unregistered users
+      exit
+   }
+   #cc "|$REPLYMAIL"
+   EXITCODE=$UNHANDLED
+   # No response to unregistered users
+   exit
+}
+
+
+gdbmopen($MLIST, "R")
+ALIAS=gdbmfetch(tolower($FROM))
+if ($ALIAS eq "")
+{
+    gdbmclose
+    EXITCODE=$UNREGISTERED
+    exit
+}
+gdbmclose
+
+
+#
+# REGISTERED USERS ONLY
+#
+if (/^Subject:\s*\[(SUBSCRIBE|UNSUBSCRIBE)\]\s*$/)
+{
+   SUBSCRIBE=$MATCH1
+}
+
+if ($SUBSCRIBE ne "")
+{
+   gdbmopen($SLIST, "W")
+   if (gdbmstore(tolower($FROM), $SUBSCRIBE) == 0)
+   {
+      gdbmclose
+      system "$SUBUNSUB '$SUBSCRIBE' '$ALIAS' '$FROM'"
+      exit
+   }
+   else
+   {
+      gdbmclose
+      EXITCODE=$FATAL
+      exit
+   }
+}
+
+
+gdbmopen($SLIST, "R")
+FORWARD=(gdbmfetch(tolower($FROM)) eq "SUBSCRIBE")
+gdbmclose
+
+
+if (!$FORWARD)
+{
+   EXITCODE=$UNSUBSCRIBED
+   exit
+}
+
+#
+# SUBSCRIBED USERS ONLY
+#
+NOFORWARD=$FROM
+FROM=$ALIAS
+to "!"
+