list

hooks

Hooks to be used to receive/send emails.

curl -O https://dovel.email/hooks.tar.gz tar.gz

5f560a5

Author: brian (git@myr.sh)

Date: Tue Dec 26 19:50:58 2023 -0300

Parent:

Added example receive script

Diff

receive-example.domain

diff --git a/receive-example.domain b/receive-example.domain
new file mode 100755
index 0000000..5559fd4
--- /dev/null
+++ b/receive-example.domain
@@ -0,0 +1,261 @@
+#!/bin/sh
+
+escapehtml() {
+	sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
+}
+
+# update index page
+index() {
+	cat <<- EOF
+	<!DOCTYPE html>
+	<html>
+	<head>
+		<title>dovel</title>
+		<link rel=icon href=/assets/favicon.ico>
+		<meta name="viewport" content="width=device-width, initial-scale=1"/>
+		<meta name="color-scheme" content="light dark"/>
+		<style>body{max-width:600px;padding:0 15px;margin:40px auto;font-family:sans-serif;}a{color:#888}small{float:right;}</style>
+		<link rel="manifest" href="/assets/manifest.json">
+		<link rel="apple-touch-icon" sizes="200x200" href="/logo.png">
+	</head>
+	<body>
+		<center>
+	<pre>
+	_________                 ______
+	______  /________   _________  /
+	_  __  /_  __ \_ | / /  _ \_  / 
+	/ /_/ / / /_/ /_ |/ //  __/  /  
+	\__,_/  \____/_____/ \___//_/   
+	</pre>
+		</center>
+	<a href=compose.html>compose</a>&emsp;
+	<a href=logout.html>logout</a>
+	EOF
+
+	ls -ogdt --time-style long-iso "$HOME/mail"/* | while read -r g x s d t f
+		do
+			f="$(basename "$f" | cut -d ' ' -f -1)"
+			cat <<- EOF
+			<p>
+				<a href="$f/index.html">$f</a>
+				<small>$t $d</small>
+			</p>
+			EOF
+		done
+	cat <<- EOF
+	</body>
+	</html>
+	EOF
+}
+
+# update inbox page
+inbox() {
+	cat <<- EOF
+	<!DOCTYPE html>
+	<html>
+	<head>
+		<title>dovel</title>
+		<link rel=icon href=/assets/favicon.ico>
+		<meta name="viewport" content="width=device-width, initial-scale=1"/>
+		<meta name="color-scheme" content="light dark"/>
+		<style>body{max-width:600px;padding:0 15px;margin:40px auto;font-family:sans-serif}a{color:#888}small{float:right}</style>
+		<link rel="manifest" href="/assets/manifest.json">
+		<link rel="apple-touch-icon" sizes="200x200" href="/logo.png">
+	</head>
+	<body>
+	<h1>$to</h1>
+	<a href=/index.html>go back</a>
+	EOF
+
+	ls -ogdt --time-style long-iso "$HOME/mail/$to"/* | while read -r g x s d t f
+	do
+		f="$(basename "$f")"
+		qty="$(ls -1 "$HOME/mail/$to/$f" | wc -l)"
+		cat <<- EOF
+		<p>
+			<a href="$f/index.html">$f</a>
+			<small>$t $d</small><br>
+			<i>$qty emails</i>
+		</p>
+		EOF
+	done
+	cat <<- EOF
+	</body>
+	</html>
+	EOF
+}
+
+# update emails page
+emails() {
+	cat <<- EOF
+	<!DOCTYPE html>
+	<html>
+	<head>
+		<title>dovel</title>
+		<link rel=icon href=/assets/favicon.ico>
+		<meta name="viewport" content="width=device-width, initial-scale=1"/>
+		<meta name="color-scheme" content="light dark"/>
+		<style>body{max-width:600px;padding:0 15px;margin:40px auto;font-family:sans-serif}a{color:#888}small{float:right}</style>
+		<link rel="manifest" href="/assets/manifest.json">
+		<link rel="apple-touch-icon" sizes="200x200" href="/logo.png">
+	</head>
+	<body>
+	<h1>$subj</h1>
+	<a href="/$to/index.html">go back</a><br><br>
+	EOF
+
+	# print each email
+	# TODO: read text part
+	# TODO: decode quoted-pritable or base64
+	ls -1rt "$HOME/mail/$to/$subj"/*.mbox | while read -r f
+	do
+		{
+			# print headers
+			read -r foo from date
+			cat <<- EOF
+			<details>
+			<summary>
+				From: $from <i style="float:right">$date</i>
+			</summary>
+			<pre>
+			EOF
+
+			while read -r k v
+			do
+				printf "$k $v\n"
+				case "$k" in
+				"Content-Type:") ctype="${v%%;*}" ;;
+				"boundary="*) boundary="${k#*\"}" ;;
+				"Content-Disposition:")
+					cdisp="${v%%;*}"
+
+					if echo "$v" | grep -qv "filename="
+					then
+						read -r v
+						printf -- "$k $v\n"
+						fn="${v#*filename=}"
+					fi
+					fn="${v#*filename=}"
+					fn="$(echo "$fn" | tr -d '"')"
+					;;
+				"Content-Transfer-Encoding:") cenc="$v" ;;
+				"") break ;;
+				esac
+			done
+
+			cat <<- EOF
+			<br>
+			</pre>
+			</details>
+			<br>
+			EOF
+
+			case "$ctype" in
+			"multipart"*)
+				boundary="${boundary%\"}"
+				printf "<pre>\n"
+				while read -r line
+				do
+					case "$line" in
+					--"$boundary")
+						read -r key pctype char
+						read -r key pcenc
+						read -r blank
+						;;
+					--"$boundary"--) break ;;
+					*)
+						# now write only text/plain part
+						if [ "$pctype" = "text/plain;" ]
+						then
+							printf -- "$line\n"
+						fi
+						;;
+					esac
+				done
+				printf "</pre>\n"
+				;;
+			*)
+				# not multipart so body xor attachments
+				if [ "$cdisp" = "attachment" ]
+				then
+					cat <<- EOF
+					<a href="data:$ctype;base64,
+					EOF
+
+					if [ "$cenc" = "base64" ]
+					then
+						cat
+					else
+						base64
+					fi
+					printf -- "\" download=\"$fn\">$fn</a><br>"
+
+				else
+					printf "<pre>\n"
+					if [ "$cenc" = "base64" ]
+					then
+						base64 -d
+					else
+						cat
+					fi
+					printf "</pre>\n<br>\n"
+				fi
+				;;
+			esac
+		} < "$f"
+	done
+
+	# finish
+	cat <<- EOF
+	</body>
+	</html>
+	EOF
+}
+
+save() {
+	echo "parsing email"
+
+	# first line is From email date:
+	read -r foo from date
+
+	# read headers
+	while read -r k v
+	do
+		case "$k" in
+			"To:") to="$v" ;;
+			"Subject:") subj="$v" ;;
+			"Message-ID:") eid="$v" ;;
+			"") break ;;
+		esac
+	done
+
+	# adjust fields
+	to="$(printf "$to" | cut -d ' ' -f -1 | tr -d '<>')"
+	eid="${eid:-$(date -Iseconds)}"
+
+	# now the rest is a body
+	cat > /dev/null
+
+	# move temp file
+	mkdir -p "$HOME/mail/$to/$subj"
+	mv "$tmp" "$HOME/mail/$to/$subj/$eid.mbox"
+
+	# create html pages
+	echo "building index page"
+	mkdir -p "$out/$to/$subj"
+	index > "$out/index.html"
+
+	echo "building inbox page"
+	inbox > "$out/$to/index.html"
+
+	echo "building emails page"
+	emails > "$out/$to/$subj/index.html"
+}
+
+# copy to temp file
+echo "[INFO] receive-example.domain started"
+out="$HOME/www/mail"
+tmp="$(mktemp)"
+tee "$tmp" | save
+echo "[INFO] script finished"
+