Hooks to be used to receive/send emails.
Author: brian (git@myr.sh)
Date: Tue Dec 26 19:50:58 2023 -0300
Added example receive script
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/&/\&/g' -e 's/</\</g' -e 's/>/\>/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>  + <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" +