#! /usr/bin/ksh
##########################################################################
# Shellscript:	popc.ksh - example of an POP3 e-mail client
# Author     :	Heiner Steven <heiner.steven@odn.de>
# Date       :	2002-02-12
# Category   :	Mail, Internet
# SCCS-Id.   :	@(#) popc.ksh	1.1 02/02/26
##########################################################################
# Description
# This example implements the "LIST" command to list all messages,
# "RETR" to retrieve a message text by number, and "DELE" to delete
# a message by number.
#
# Refer to RFC 1939 (http://www.ietf.org/rfc/rfc1939.txt) for a full
# description of the POP3 protocol.
#
# Needs the non-standard program "netcat" (aka "nc") to establish a
# TCP connection. You could use "socket(1)" instead, if installed.
##########################################################################

PN=${0##*/}			# Program name
VER='1.1'

: ${NETCAT:=netcat}
: ${NETCATFLAGS:=}

DEF_HOST=localhost
DEF_PORT=110
: ${DEF_USER:=${USER:-$LOGNAME}}
: ${DEF_PASSWD:=$POP3_PASSWORD}

function Usage {
    print -u2 "$PN - example of an POP3 e-mail client, $VER
usage: $PN [-h host] [-p port] [-U user] [-P password]
    -h:	mail server (POP3) host name (default is \"$DEF_HOST\")
    -p:	mail server port number (default is $DEF_PORT)
    -U: mail account user name (default is $DEF_USER)
    -P: mail account password (no default)"
    exit 1
}

function Msg {
    print -u2 "$PN:" "$@"
}

function Fatal { Msg "$@"; exit 1; }

while getopts :h:p:U:P: opt
do
    case "$opt" in
    	# your flags here
	#f)	argument=$OPTARG;;
	h)	host=$OPTARG;;
	p)	port=$OPTARG;;
	U)	user=$OPTARG;;
	P)	pass=$OPTARG;;
	?)	Usage;;
    esac
done
shift OPTIND-1

: ${host:=$DEF_HOST}		# Name or address of POP3 server
: ${port:=$DEF_PORT}		# POP3 port (standard is 110)
: ${user:=$DEF_USER}
: ${pass:=$DEF_PASSWD}

typeset -u pop_status		# Global last status { "+OK" | "-ERR" }
typeset pop_msg			# Global last server status message

function Fatal { print -u2 "$@"; exit 1; }

# sendline - send one line to co-process

function sendline { print -p -- "$@"; }

# getack - get positive or negative acknowledgement from server
#
# The server will answer with either "+OK ..." or "-ERR ...". We
# evaluate the first word read from the server, and set the
# return value accordingly

function getack {
    read -p -r pop_status pop_msg; print -u2 "DEBUG: $pop_status $pop_msg"
    [[ $pop_status == '+OK' ]] && return 0
    print -u2 -- "$pop_status $pop_msg"
    return 1
}

# getlist - get multi-line response from server
#
# Multi-line responses are terminated by a line consisting only of
#  a period '.'

function getlist {
    typeset line

    while read -p -r line
    do
	line=${line%+(?)}		# Remove trailing CR (ASCII 13)
    	[[ $line == '.' ]] && break	# End of list
	#print -- "<$line>"
	print -- "$line"
    done
}

function ListCmd {
    sendline "LIST"
    getack && getlist
}

function DeleteCmd {
    integer msgno

    read msgno?"DELETE message Number: "
    sendline "DELE $msgno" && getack
}

function RetrieveCmd {
    integer msgno

    read msgno?"Retrieve message Number: "
    sendline "RETR $msgno"
    getack && getlist
}

# Startup the server as a co-process. We will use "print -p"
# and "read -p" to write and read data.

"$NETCAT" $NETCATFLAGS "$host" "$port" |&	popdpid=$!

# Check if the server is ready
getack || Fatal "cannot start POP3 server $host:$port"

# Authentication

set -e		# First error terminates script
sendline "USER $user" && getack
sendline "PASS $pass" && getack
set +e

print -u2 "Authentication successful"
PS3="POP3 command (RETURN prints menu): "
select choice in List Retrieve Delete Quit
do
    case "$choice" in
    (List)	ListCmd ;;
    (Retrieve)	RetrieveCmd ;;
    (Delete)	DeleteCmd ;;
    (Quit)	break;;
    esac
done

# Shut down co-process
exec 3<&p 3>&p		# redirect co-process fd to fd 3
exec 3<&- 3>&-		# close fd 3
kill $popdpid >/dev/null 2>&1	# if the above does not work...

exit 0
