#!/bin/bash # Sun Jan 18 16:48:55 EST 2004 # NAME: pop3ck # Copyright 2004, Chris F.A. Johnson # Released under the terms of the GNU General Public License version() { echo " $progname, version $version Copyright $copyright, $author $email This is free software, released under the terms of the GNU General Public License. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " } usage() { echo " $progname - USAGE: $progname [OPTIONS] OPTIONS: -c FILE - use FILE for server information (will prompt for details if file does not exist) -s - Print number of messages and exit -h - help: print this message -H - help: print more detailed message -v - verbose: -V - print version information Copyright 2004, Chris F.A. Johnson " } set_chars() { #== create string of all 255 chars q='0 1 2 3 4 5 6 7 8 9 a b c d e f' chars=`for a in $q do for b in $q do case $a$b in 00) ;; 7f) printf "\x11" ;; *) printf "\x$a$b" ;; esac done done` } get_key() { #== store keypress from list of permissible characters local OKchars=${1:-"$allkeys"} local k local error=0 local gk_tmo=${getkey_time:-${DFLT_TIME_OUT:-600}} local ESC_END=[a-zA-NP-Z~^$] type read_mouse >/dev/null 2>&1 || read_mouse() { :; } mouse_x=0 mouse_y=0 mouse_b=0 mouse_line=0 printf "$mouse_on" stty -echo while :; do IFS= read -r -d '' -sn1 -t$gk_tmo _GET_KEY &1 || break index "$OKchars" "$_GET_KEY" if [ "$_INDEX" -gt 0 ] then case $_GET_KEY in ${ESC}) while :; do IFS= read -rst1 -d '' -n1 k : " l echo case $l in 1) getline pop " Enter pop3 mail server" ;; 2) getline user " Enter user name" ;; 3) getline pass " Enter password" ;; 4) getline config_file " Enter config file" ;; *) break ;; esac done echo { echo "pop=$pop" echo "user=$user" echo "pass=$pass" } > "${config_file:-$HOME/.pop3ckrc}" stty $stty printf "${CINV}\n" } connect() { ## open connection to POP server and log in exec 3<> /dev/tcp/$pop/${port:=110} read -rt${timeout:-2} ok num x <&3 || return 5 _CONNECT=1 popcmd user $user popcmd pass $pass || return 5 } popcmd() { cmd=$* echo $cmd >&3 read -rt${timeout:-2} ok num x <&3 || return 5 [ "$ok" = "+OK" ] } set_pl() { local num=${1:-0} [ $num -eq 1 ] && pl= || pl=s } pop3stat() { [ -f "$config_file" ] && . "$config_file" || return 5 connect popcmd stat || return 3 set_pl $num num_messages=$num _POP3STAT="$num message$pl" } popread() { local header=1 while IFS= read -r line do line=${line%$CR} case $line in "") header=0; printf "\n\n" ;; .) break ;; *) if [ $header -eq 1 ] then case $line in $wsp*) printf "%s " "$line" ;; *) printf "%s\n" "$line" ;; esac fi esac echo "$line" done } hnum() { case ${#1} in 1|2|3|4) _HNUM=$1 ;; 5|6) _HNUM=$(( ($1 + 500) / 1000 ))K ;; 7|8|9) _HNUM=$(( ($1 + 500000) / 1000000 ))M ;; 10|11|12) _HNUM=$(( ($1 + 500000000) / 1000000000 ))G ;; *) _HNUM="HUGE" ;; esac } popheader() { local ph_num=$1 local sw=$(( $COLUMNS - 44 - ${#num_messages} )) f1= #$scroll_down${HB_RESET}${colour}${cle} f2="${f1}%2.1s %${#num_messages}d %6.6s %-25.25s %6.6s %-${sw}.${sw}s${HB_RESET}\r" notify reading header $ph_num popcmd top $ph_num ${msg_lines:-10} || return 1 size[$ph_num]=$num _POPREAD=`popread x <&3` header=1 local IFS=$NL _POPHEADER=( ${_POPREAD%%$NL$NL} ) msg_top[$ph_num]=${_POPREAD#*$NL$NL} msg_read[$ph_num]=1 local num=0 while [ $num -lt ${#_POPHEADER[@]} ] do line=${_POPHEADER[$num]} case $line in "") header=0; break ;; [\ \ ]*) ;; [Ss][Uu][Bb][Jj][Ee][Cc][Tt]:* ) msg_subject[$ph_num]=${line#*: } ;; [Ff][Rr][Oo][Mm]:*) msg_from[$ph_num]=${line#*: } msg_xfrom[$ph_num]=${msg_from[$ph_num]%%\<*};; [Tt][Oo]:*) msg_to[$ph_num]=${line#*: } ;; [Cc][Cc]:*) msg_cc[$ph_num]=${line#*: } ;; [Dd][Aa][Tt][Ee]:*) msg_date[$ph_num]=${line#*: } ;; [Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:*) msg_id[$ph_num]=${line#*: } ;; [Rr][Ee][Pp][Ll][Yy]-[Tt][Oo]:*) msg_reply_to[$ph_num]=${line#*: } ;; [Ss][Ee][Nn][Dd][Ee][Rr]:*) msg_sender[$ph_num]=${line#*: } ;; *:*) last_type=${line#*: } ;; esac num=$(( $num + 1 )) done hnum "${size[$ph_num]}" msg_hnum[$ph_num]=$_HNUM msg_status[$ph_num]=' ' summaries[$ph_num]=`printf "$f2" "${msg_status[$ph_num]}" \ "$ph_num" \ "${msg_date[$ph_num]:5:6}" \ "${msg_xfrom[$ph_num]//\"/}" \ "($_HNUM)" "${msg_subject[$ph_num]}"` printf "\n%s\n" "${summaries[$ph_num]}" } notify() { local msg=" $* " printat 1 $(( $COLUMNS - ${#msg} - 1 )) "$msg" } show_cmd() { local n=-1 local num=${#cmds[@]} local cmd=${cmds[*]} local cmd_line=$(( $LINES - 1 )) justify=$(( ($COLUMNS - ${#cmd}) / (${num} + 1) )) commands= printat $cmd_line 1 "${BR}" printf "%${COLUMNS}s" ' ' printat $cmd_line 1 while [ $(( n += 1 )) -lt $num ] do initial="${cmds[n]:0:1}" the_rest="${cmds[n]:1}" commands=$commands$initial printf " %${justify:-0}.${justify}s${NA}${B}%s${R}%s${BR}" ' ' $initial "${the_rest}" done printf "${NA}" } show_msg() { local num=${1:-1} local w=$(( $COLUMNS - 10 )) cls echo "$CINV" printat 1 1; printf "$BR%${COLUMNS}.${COLUMNS}s" " " printat 1 1; echo "$BR Message $num of $num_messages$NA" printat 2 1; printf "$date_lattr Date: $date_attr %-${w}.${w}s${NA}" "${msg_date[num]}" printat 3 1; printf "$from_lattr From: $from_attr %-${w}.${w}s${NA}" "${msg_from[num]}" printat 4 1; printf "$to_lattr To: $to_attr %-${w}.${w}s${NA}" "${msg_to[num]}" printat 5 1; printf "$subj_lattr Subject: $subj_attr %-${w}.${w}s${NA}" "${msg_subject[num]}" printat 7 1 local IFS=$NL # printf "%s\n" "${msg_top[$num]}" | cut -c1-$(( $COLUMNS - 1 )) | head -$(( $LINES - 10 )) printf "%s\n" "${msg_top[$num]}" | fold -w $(( $COLUMNS - 1 )) | head -$(( $LINES - 10 )) } show_summaries() { local msg_num=-1 cls while [ $(( msg_num += 1 )) -lt $num_messages ] do [ ${msg_read[$msg_num]:=0} -ne 1 ] && popheader $msg_num done cls printat 3 1 printf "%s\n" "${summaries[@]}" | if [ $num_messages -gt $(( $LINES - 10 )) ] then less else cat fi echo read -sn1 -p " ${B}Press any key to continue${NA} " } set_attr() { case $1 in -var) var=$2; shift 2 ;; -var=*) var=${1#-var=}; shift ;; -var*) var=${1#-var}; shift ;; *) var= ;; esac _SET_ATTR= for attr do case $attr in *,*) eval "_SET_ATTR=$_SET_ATTR\${fg_${attr%,*}}\${bg_${attr#*,}}" ;; *) eval "_SET_ATTR=$_SET_ATTR\${fg_${attr}}" ;; esac done [ -n "$var" ] && eval "$var=\"$_SET_ATTR\"" } cleanup() { msg_num=-1 while [ $(( msg_num += 1 )) -lt $num_messages ] do [ "${msg_status[$msg_num]}" = D ] && { popcmd dele $msg_num printf "\r${cle}%s\n" "$ok $num $x" } # || printf "\r${cle}%s\r" " $num" done [ ${_CONNECT:-0} -eq 1 ] && popcmd quit stty $stty stty sane echo printf "$NA\r$cles$CVIS" } wsp="[ ]" bra='[' ket=']' ESC=$'\e' NL=$'\n' CR=$'\r' TAB=$'\t' CSI=${ESC}${bra} cle=${CSI}K cles=${CSI}J clbs=${CSI}1J CVIS="${CSI}?25h" CINV="${CSI}0;8m" MSI=${CSI}M NA=${CSI}0m B=${CSI}1m R=${CSI}7m BR=$B$R U=${CSI}4m UP=${CSI}A DN=${CSI}B RT=${CSI}C LF=${CSI}D mouse_type[0]=${CSI}?9h ## report mouse button press mouse_type[1]=${CSI}?1000h ## report mouse button press and release mouse_on=${mouse_type[0]} mouse_off=${CSI}?9l${CSI}?1000l upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz numeric=0123456789 alphanumeric=$upper$lower$numeric CVIS=${CSI}?25h CINV=${CSI}?25l allkeys=$chars verbose=0 longusage=0 version="1.0" copyright=2004 author="Chris F.A. Johnson" progname=${0##*/} config_file=$HOME/.pop3ckrc while getopts vVhH-:c:s var do case $var in c) config_file=$OPTARG ;; s) pop3stat || return 5 printf "\r$_POP3STAT for $user on $pop $cle\n" popcmd quit || exit 4 exit ;; -) case $OPTARG in help) usage; exit ;; help_long) longusage=1; usage; exit ;; version) version; exit ;; esac ;; h) usage; exit ;; H) longusage=1; usage; exit ;; v) verbose=$(( $verbose + 1 )) ;; V) version; exit ;; *);; esac done shift $(( $OPTIND - 1 )) cls stty=`stty -g` stty -icanon -echo delete_will_advance=1 [ -f "$config_file" ] || { create_config || exit 5; } . "$config_file" setsize() { set `stty size || { tput lines; tput cols; }` LINES=${1:-24} COLUMNS=${2:-80} [ -n "$1" ] || show_msg $msg_num } trap setsize SIGWINCH trap cleanup EXIT echo "Making connection to $pop as $user" pop3stat || { echo "$OK $num $x (conection failed)" ; exit 5; } echo "$_POP3STAT" [ ${num:-0} -gt 0 ] || { popcmd quit; exit; } cmds=( forward next back previous goto summary delete undelete quit ) msg_lines=$(( ${LINES} - 6 )) msg_num=1 while : do setsize [ ${msg_read[$msg_num]:=0} -ne 1 ] && popheader $msg_num [ ${last_msg:-0} -ne $msg_num ] && show_msg $msg_num show_cmd last_msg=$msg_num get_key "$commands$ESC" case $_GET_KEY in n|f|$UP|$RT) msg_num=$(( $msg_num + 1 )) ;; b|p|$DN|$LF) msg_num=$(( $msg_num - 1 )) ;; d) msg_top[$msg_num]=" ${BR} DELETED ${NA}" msg_status[$msg_num]=D summaries[$msg_num]=`printf "$f2" "${msg_status[$msg_num]}" $msg_num "${msg_date[$msg_num]}" "${msg_from[$msg_num]//\"/}" "(${msg_hnum[$msg_num]})" "${msg_subject[$msg_num]}"` show_msg $msg_num sleep .2 msg_num=$(( $msg_num + ${delete_will_advance:=0} )) ;; g) stty echo printat $(( $LINES - 1 )) 1 "$cle" read -ep "$BR Enter number of message:$NA " num stty -echo case $num in *[!0-9]*) printf "\aInvalid entry" sleep 2 ;; *) msg_num=$num ;; esac ;; q) break ;; u) msg_status[$msg_num]=U popheader $msg_num show_msg $msg_num ;; s) show_summaries show_msg $msg_num ;; esac if [ $msg_num -lt 1 ] then msg_num=1 elif [ $msg_num -ge $num_messages ] then msg_num=$num_messages fi done cleanup