rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | LICENSE

commit 9c46de0faaa605f288be000519a7a2a35556e523
parent ae52f8373b902cb8098bb8c7c54c88ff8f9805f9
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sun, 23 Dec 2012 09:35:49 +0100

Adding the example templates and some missing commands.

Diffstat:
bin/rpdecrypt | 16++++++++++++++++
bin/rpprint | 4++++
tmpl/compose.sh | 20++++++++++++++++++++
tmpl/flag.sh | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmpl/fwd.sh | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
tmpl/inc.sh | 37+++++++++++++++++++++++++++++++++++++
tmpl/news.sh | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmpl/print.sh | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmpl/repl.sh | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmpl/scan.sh | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tmpl/view.sh | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 674 insertions(+), 0 deletions(-)

diff --git a/bin/rpdecrypt b/bin/rpdecrypt @@ -0,0 +1,16 @@ +#!/bin/sh + +msgids="$*" + +parts=$(rppart -l -- "$msgids" | tail -n +2) + +if [ -n "$(echo -n "$parts" | grep "multipart/encrypted")" ]; +then + # + # Bad heuristics. Works for me. + # + rppart -sc application/octet-stream -- "$msgids" | gpg -d +else + rppart -sc text/plain -- "$msgids" | gpg -d +fi + diff --git a/bin/rpprint b/bin/rpprint @@ -0,0 +1,4 @@ +#!/bin/sh + +rpview "$@" | $(rpcfg -b)/tmpl/print.sh + diff --git a/tmpl/compose.sh b/tmpl/compose.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +echo "Date: `LANG=C date "+%a, %d %b %Y %T %z"` +From: `rpcfg -v defaultfrom` +Subject: Subject +To: +Cc: +Bcc: +User-Agent: rohrpost +MIME-Version: 1.0 +Content-Type: text/plain; charset=\"utf-8\" +Content-Transfer-Encoding: 8bit + +Text" + +if [ -e $HOME/.signature ]; +then + cat $HOME/.signature +fi + diff --git a/tmpl/flag.sh b/tmpl/flag.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +reset="$(tput sgr0)" +titleformat="$(tput bold)" +idformat="$(tput bold)" +flagformat="$(tput setaf 3)" + +flen=10 +cols=$(tput cols) +scols=$(($cols - $flen)) + +first=1 + +while read -r line; +do + id=$(echo -n "$line" | cut -f 1 | head -c 8) + flags=$(echo -n "$line" | cut -f 2) + + if [ $first -eq 1 ]; + then + printf "${titleformat}%8s %s\n" "$id" "$flags" + first=0 + else + printf "${idformat}%8s${reset} " "$id" + slen=$(utf8expr length "$flags") + if [ $scols -lt 1 ] || [ $scols -gt $slen ]; + then + printf "${flagformat}%s${reset}\n" "$flags" + else + pos=1 + while [ $slen -gt 0 ]; + do + if [ $slen -gt $scols ]; + then + sslen=$scols + else + sslen=$slen + fi + + sstr=$(utf8expr substr "$flags" $pos \ + $sslen | sed 's,^[[:space:]]*,,g') + if [ $pos -gt 1 ]; + then + printf "%${flen}s" " " + fi + printf "${flagformat}%s${reset}\n" "$sstr" + + pos=$(($pos + $sslen)) + slen=$(($slen - $sslen)) + done + fi + fi +done + diff --git a/tmpl/fwd.sh b/tmpl/fwd.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +usage() { + echo "usage: `basename $1` [-h] mailid" +} + +while getopts "hal" opt; +do + case $opt in + *) + usage $0 + exit 1 + ;; + esac +done +shift `expr $OPTIND - 1` +if [ "$1" = "--" ]; +then + shift 1 +fi + +if [ $# -lt 1 ]; +then + usage $0 + exit 1 +fi + +ids="$@" +if [ -z "$ids" ]; +then + usage $0 + exit 1 +fi + +nsubject="Fwd: `rpview -ve Subject -- "$ids"`" + +echo "Date: `LANG=C date "+%a, %d %b %Y %T %z"` +From: `rpcfg -v defaultfrom` +Subject: ${nsubject} +To: +Cc: +Bcc: +User-Agent: rohrpost +MIME-Version: 1.0 +Content-Type: text/plain; charset=\"utf-8\" +Content-Transfer-Encoding: 8bit +" + +# Consider checking for multiple messages and add them as eml or inline. +rpview -nb -- "$ids" | sed 's/^/> /' +echo + diff --git a/tmpl/inc.sh b/tmpl/inc.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +reset="$(tput sgr0)" +titleformat="$(tput bold)" +folderformat="$(tput setaf 7)" +msgsformat="$(tput setaf 3)" +unseen0format="" +unseenformat="$(tput setaf 7)" +recentformat="" + +first=1 + +while read line; +do + folder=$(echo -n "$line" | cut -f 1 | head -c 25) + msgs=$(echo -n "$line" | cut -f 2 | head -c 16) + unseen=$(echo -n "$line" | cut -f 3 | head -c 16) + recent=$(echo -n "$line" | cut -f 4 | head -c 16) + + if [ $first -eq 1 ]; + then + printf "${titleformat}%25s %16s %16s %16s${reset}\n" \ + "$folder" "$msgs" "$unseen" "$recent" + first=0 + else + printf "${folderformat}%25s${reset} " "$folder" + printf "${msgsformat}%16s${reset} " "$msgs" + if [ $unseen -eq 0 ]; + then + printf "${unseen0format}%16s${reset} " "$unseen" + else + printf "${unseenformat}%16s${reset} " "$unseen" + fi + printf "${recentformat}%16s${reset}\n" "$recent" + fi +done + diff --git a/tmpl/news.sh b/tmpl/news.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +reset="$(tput sgr0)" +titleformat="$(tput bold)" +idformat="$(tput bold)" +dateformat="$(tput setaf 3)" +subjectformat="$reset" + +flen=22 +cols=$(tput cols) +scols=$(($cols - $flen)) + +first=1 + +while read -r line; +do + id=$(echo -n "$line" | cut -f 1 | head -c 8) + date=$(echo -n "$line" | cut -f 2 | head -c 10) + subject=$(echo -n "$line" | cut -f 4) + + if [ $first -eq 1 ]; + then + printf "${titleformat}%8s %10s %s\n" "$id" "$date" \ + "$subject" + first=0 + else + printf "${idformat}%8s${reset} " "$id" + printf "${dateformat}%10s${reset} " "$date" + slen=$(utf8expr length "$subject") + if [ $scols -lt 1 ] || [ $scols -gt $slen ]; + then + printf "${subjectformat}%s${reset}\n" "$subject" + else + pos=1 + while [ $slen -gt 0 ]; + do + if [ $slen -gt $scols ]; + then + sslen=$scols + else + sslen=$slen + fi + + sstr=$(utf8expr substr "$subject" $pos \ + $sslen | sed 's,^[[:space:]]*,,g') + if [ $pos -gt 1 ]; + then + printf "%${flen}s" " " + fi + printf "${subjectformat}%s${reset}\n" \ + "$sstr" + + pos=$(($pos + $sslen)) + slen=$(($slen - $sslen)) + done + fi + fi +done + diff --git a/tmpl/print.sh b/tmpl/print.sh @@ -0,0 +1,107 @@ +#!/bin/sh + +# structure +reset="$(tput sgr0)" +idformat="$(tput bold)" +keyformat="$(tput setaf 3)" +valueformat="$(tput setaf 7)" +partformat="$(tput setaf 3)" +alertformat="$(tput setaf 1; tput bold; tput blink;)" + +# body text +textformat="$reset" +quoteformat="$(tput setaf 6)" +headerformat="$(tput setaf 8)" + +italicformat="$(tput sitm)" +italicreset="$(tput ritm)" +boldformat="$(tput bold)" +boldreset="$(echo -ne "\033[22m")" +underlineformat="$(tput smul)" +underlinereset="$(tput rmul)" +reverseformat="$(tput rev)" +reversereset="$(echo -ne "\033[27m")" + +state="id" + +function formatheader { + line="$1" + if [ "$line" = " " ] || [ -z "$line" ]; + then + printf "\n" + state="body" + return + fi + + # GNU sed sucks at UTF-8 + key=$(echo "$line" | perl -pe 's/: .*//') + value=$(echo "$line" | perl -pe 's/[A-Za-z0-9-]*: //') + + uvformat="${valueformat}" + if [ "$key" = "X-Mailer" ]; + then + case "$value" in + "Apple Mail"*|"iPhone Mail"*) + uvformat="${alertformat}" + ;; + esac + fi + + printf "${keyformat}%s: ${reset}${uvformat}%s${reset}\n" \ + "$key" "$value" +} + +IFS="\\" +while read -r line; +do + if [ "$line" = " " ]; + then + printf " \n" + state="id" + continue + fi + + case $state in + id) + te=$(echo -n "$line" | grep "^--") + if [ -n "$te" ]; + then + printf "${idformat}%s${reset}\n" "$line" + else + formatheader "$line" + fi + state="header" + ;; + header) + formatheader "$line" + ;; + body) + line=$(printf "%s" "$line" | sed 's/ //g') + case $line in + --MIME-Part*) + printf "${partformat}%s${reset}\n" "$line" + ;; + --*) + printf "${headerformat}%s${reset}\n" "$line" + ;; + ++*) + printf "${headerformat}%s${reset}\n" "$line" + ;; + \>*|\ \>*) + printf "${quoteformat}%s${reset}\n" "$line" + ;; + *) + line=$(printf "%s" "$line" \ + | sed "s,\(\*[^ \t\v\r\f]*\*\),${boldformat}\1${boldreset},g" \ + | sed "s,\(\/[^ \t\v\r\f]*\/\),${italicformat}\1${italicreset},g" \ + | sed "s,\(_[^ \t\v\r\f]*_\),${underlineformat}\1${underlinereset},g") + printf "${textformat}%s${reset}\n" "$line" + ;; + esac + ;; + *) + echo "unknown state" + ;; + esac +done + diff --git a/tmpl/repl.sh b/tmpl/repl.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +usage() { + printf "usage: $(basename $1) [-hal] mailid\n" >&2 +} + +doall=0 +dolist=0 + +while getopts "hal" opt; +do + case $opt in + a) + doall=1 + ;; + l) + dolist=1 + ;; + *) + usage $0 + exit 1 + ;; + esac +done +shift $(expr $OPTIND - 1) + +if [ "$1" = "--" ]; +then + shift 1 +fi + +if [ $# -lt 1 ]; +then + usage $0 + exit 1 +fi + +ids="$@" +if [ -z "$ids" ]; +then + usage $0 + exit 1 +fi + +nsubject=$(rpview -ve Subject -- "$ids") +if [ -z "$nsubject" ]; +then + nsubject="Subject" +else + case "$nsubject" in + Re:*) + ;; + *) + nsubject="Re: ${nsubject}" + ;; + esac +fi + +from=$(rpview -ve ^From -- "$ids" | sed 's/\n//') +cc=$(rpview -ve ^Cc -- "$ids" | sed 's/\n//') +references=$(rpview -ve ^References -- "$ids" | sed 's/\n//') +msgid=$(rpview -ve ^Message-ID -- "$ids" | sed 's/\n//') +inreplyto=$(rpview -ve ^In-Reply-To -- "$ids" | sed 's/\n//') +listpost=$(rpview -ve ^List-Post -- "$ids" \ + | sed -e 's/.*mailto:\([^> ]*\).*/\1/') + +replytohdrs=$(rpview -ve ^Reply-To -- "$ids" | sed 's/\n//') +replyto="" +IFS=' +' +for rt in $replytohdrs; +do + if [ -z "$replyto" ]; + then + replyto="$rt" + else + replyto="$replyto, $rt" + fi +done + +if [ -n "$references" ] && [ -n "$msgid" ]; +then + references="$references $msgid" +fi +if [ -z "$references" ] && [ -n "$msgid" ]; +then + if [ -n "$inreplyto" ]; + then + references="$inreplyto $msgid" + else + references="$msgid" + fi +fi + +nto="" +ncc="" +if [ $dolist -eq 1 ] && [ -n "$listpost" ]; +then + nto="$listpost" +fi +if [ $doall -eq 1 ]; +then + if [ -z "$replyto" ]; + if [ -z "$nto" ]; + then + nto="$from" + ncc="$cc" + else + ncc="$from, $cc" + fi + then + if [ -z "$nto" ]; + then + nto="$replyto" + ncc="$from, $cc" + else + ncc="$replyto, $from, $cc" + fi + fi +fi +if [ -z "$nto" ]; +then + if [ -z "$replyto" ]; + then + nto="$from" + else + nto="$replyto" + fi +fi + +printf "Date: $(LANG=C date "+%a, %d %b %Y %T %z")\n" + +if [ -n "$msgid" ]; +then + printf "In-Reply-To: ${msgid}\n" +fi +if [ -n "$references" ]; +then + printf "References: ${references}\n" +fi + +printf "User-Agent: rohrpost\n" +printf "MIME-Version: 1.0\n" +printf "Content-Type: text/plain; charset=\"utf-8\"\n" +printf "Content-Transfer-Encoding: 8bit\n" +printf "From: $(rpcfg -v defaultfrom)\n" +printf "To: ${nto}\n" +printf "Cc: ${ncc}\n" +printf "Bcc:\n" +printf "Subject: ${nsubject}\n" +printf "\n" + +printf "On $(LANG=C date "+%a, %d %b %Y %T %z") ${from} wrote:\n" +rpview -nb -- "$ids" | sed 's/^/> /' +printf "\n" + diff --git a/tmpl/scan.sh b/tmpl/scan.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +reset="$(tput sgr0)" +titleformat="$(tput bold)" +idformat="$(tput bold)" +dateformat="$(tput setaf 3)" +fromformat="$(tput setaf 7)" +subjectformat="$reset" + +flen=40 +cols=$(tput cols) +scols=$(($cols - $flen)) + +first=1 + +while read -r line; +do + id=$(echo -n "$line" | cut -f 1 | head -c 8) + date=$(echo -n "$line" | cut -f 2 | head -c 16) + from=$(utf8expr substr "$(echo -n "$line" | cut -f 3)" 1 10) + subject=$(echo -n "$line" | cut -f 4) + + if [ $first -eq 1 ]; + then + printf "${titleformat}%8s %16s %10s %s\n" "$id" "$date" \ + "$from" "$subject" + first=0 + else + printf "${idformat}%8s${reset} " "$id" + printf "${dateformat}%16s${reset} " "$date" + printf "${fromfromat}%10s${reset} " "$from" + slen=$(utf8expr length "$subject") + if [ $scols -lt 1 ] || [ $scols -gt $slen ]; + then + printf "${subjectformat}%s${reset}\n" "$subject" + else + pos=1 + while [ $slen -gt 0 ]; + do + if [ $slen -gt $scols ]; + then + sslen=$scols + else + sslen=$slen + fi + + sstr=$(utf8expr substr "$subject" $pos \ + $sslen | sed 's,^[[:space:]]*,,g') + if [ $pos -gt 1 ]; + then + printf "%${flen}s" " " + fi + printf "${subjectformat}%s${reset}\n" \ + "$sstr" + + pos=$(($pos + $sslen)) + slen=$(($slen - $sslen)) + done + fi + fi +done + diff --git a/tmpl/view.sh b/tmpl/view.sh @@ -0,0 +1,107 @@ +#!/bin/sh + +# structure +reset="$(tput sgr0)" +idformat="$(tput bold)" +keyformat="$(tput setaf 3)" +valueformat="$(tput setaf 7)" +partformat="$(tput setaf 3)" +alertformat="$(tput setaf 1; tput bold; tput blink;)" + +# body text +textformat="$reset" +quoteformat="$(tput setaf 6)" +headerformat="$(tput setaf 8)" + +italicformat="$(tput sitm)" +italicreset="$(tput ritm)" +boldformat="$(tput bold)" +boldreset="$(echo -ne "\033[22m")" +underlineformat="$(tput smul)" +underlinereset="$(tput rmul)" +reverseformat="$(tput rev)" +reversereset="$(echo -ne "\033[27m")" + +state="id" + +function formatheader { + line="$1" + if [ "$line" = " " ] || [ -z "$line" ]; + then + printf "\n" + state="body" + return + fi + + # GNU sed sucks at UTF-8 + key=$(echo "$line" | perl -pe 's/: .*//') + value=$(echo "$line" | perl -pe 's/[A-Za-z0-9-]*: //') + + uvformat="${valueformat}" + if [ "$key" = "X-Mailer" ]; + then + case "$value" in + "Apple Mail"*|"iPhone Mail"*) + uvformat="${alertformat}" + ;; + esac + fi + + printf "${keyformat}%s: ${reset}${uvformat}%s${reset}\n" \ + "$key" "$value" +} + +IFS="\\" +while read -r line; +do + if [ "$line" = " " ]; + then + printf " \n" + state="id" + continue + fi + + case $state in + id) + te=$(echo -n "$line" | grep "^--") + if [ -n "$te" ]; + then + printf "${idformat}%s${reset}\n" "$line" + else + formatheader "$line" + fi + state="header" + ;; + header) + formatheader "$line" + ;; + body) + line=$(printf "%s" "$line" | sed 's/ //g') + case $line in + --MIME-Part*) + printf "${partformat}%s${reset}\n" "$line" + ;; + --*) + printf "${headerformat}%s${reset}\n" "$line" + ;; + ++*) + printf "${headerformat}%s${reset}\n" "$line" + ;; + \>*|\ \>*) + printf "${quoteformat}%s${reset}\n" "$line" + ;; + *) + line=$(printf "%s" "$line" \ + | sed "s,\(\*[^ \t\v\r\f]*\*\),${boldformat}\1${boldreset},g" \ + | sed "s,\(\/[^ \t\v\r\f]*\/\),${italicformat}\1${italicreset},g" \ + | sed "s,\(_[^ \t\v\r\f]*_\),${underlineformat}\1${underlinereset},g") + printf "${textformat}%s${reset}\n" "$line" + ;; + esac + ;; + *) + echo "unknown state" + ;; + esac +done +