dmc

dynamic mail client
git clone git://git.suckless.org/dmc
Log | Files | Refs | README | LICENSE

dmc.sh (6950B)


      1 #!/bin/sh
      2 # dmc - dynamic mail client
      3 # See LICENSE file for copyright and license details.
      4 
      5 VERSION="0.1"
      6 HELP="Usage: dmc [-hv] [-e acc] [-a addr] [-m addr subj] [-A file] [-s msg] [action]"
      7 
      8 [ -z "${EDITOR}" ] && EDITOR=vim
      9 mkdir -p ~/.dmc/mail
     10 mkdir -p ~/.dmc/tmp
     11 mkdir -p ~/.dmc/acc
     12 [ -e ~/.dmc/acc.default ] && . ~/.dmc/acc.default
     13 
     14 chkcfg () {
     15 	if [ -z "${NAME}" ]; then
     16 		echo "No selected mail account. Use 'dmc -e'"
     17 		exit 1
     18 	fi
     19 }
     20 
     21 acc_daemon () {
     22 	chkcfg
     23 	LOCK=~/.dmc/tmp/${NAME}.lock
     24 	INPUT=~/.dmc/tmp/${NAME}.input
     25 	OUTPUT=~/.dmc/tmp/${NAME}.output
     26 
     27 	echo "Starting $NAME account $PROTOCOL daemon..."
     28 
     29 	rm -f "${LOCK}" "${INPUT}" "${OUTPUT}"
     30 	mkfifo "${LOCK}" "${INPUT}"
     31 
     32 	# wait 1 connect message and 1 login message
     33 	(head -n 2 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ; dmc_cmd "ls") &
     34 	(while : ; do cat ${INPUT} 2> /dev/null ; done) | \
     35 		dmc-${PROTOCOL} ${HOST} ${PORT} ${SSL} 2> ${OUTPUT} > ${LOCK}
     36 	rm -f "${LOCK}" "${INPUT}" "${OUTPUT}"
     37 }
     38 
     39 dmc_cmd () {
     40 	[ -z "$1" ] && return
     41 	echo "$@" > ~/.dmc/tmp/${NAME}.input
     42 	head -n 1 ~/.dmc/tmp/${NAME}.lock > /dev/stderr
     43 	cat ~/.dmc/tmp/${NAME}.output
     44 }
     45 
     46 start_account_daemons () {
     47 	chkcfg
     48 	i=0
     49 	for a in ~/.dmc/acc/* ; do
     50 		( . $a ; acc_daemon ) &
     51 		i=$(($i+1))
     52 		sleep 1
     53 	done
     54 	if [ $i = 0 ]; then
     55 		echo "No accounts defined in ~/.dmc/acc"
     56 		exit 1
     57 	fi
     58 }
     59 
     60 print_account_template () {
     61 	echo "NAME='test'"
     62 	echo "SSL=0"
     63 	echo "LIMIT=50 # get only 50 mails for each folder"
     64 	echo "PROTOCOL='pop3' # imap4"
     65 	echo "HOST=serverhost.com"
     66 	echo "PORT=110"
     67 	echo "#SEND=acc-name"
     68 	echo "SEND=!msmtp"
     69 	echo "ONLINE=0"
     70 	echo "MAIL=username@domain"
     71 	echo "USER='username'"
     72 	echo "PASS='password'"
     73 }
     74 
     75 edit_message () {
     76 	chkcfg
     77 	OUTDIR=~/.dmc/box/${NAME}/out
     78 	mkdir -p ${OUTDIR}
     79 	OUT="`mktemp ${OUTDIR}/mail.XXXXXX`"
     80 	echo "X-Mailer: dmc v${VERSION}" > $OUT
     81 	echo "From: ${MAIL}" >> $OUT
     82 	echo "To: ${TO}" >> $OUT
     83 	echo "Subject: ${SUBJECT}" >> $OUT
     84 	echo "" >> $OUT
     85 	echo "" >> $OUT
     86 	if [ -e ~/.dmc/box/${NAME}/signature ]; then
     87 		echo "---" >> $OUT
     88 		cat ~/.dmc/box/${NAME}/signature >> $OUT
     89 	else
     90 		if [ -e ~/.dmc/signature ]; then
     91 			echo "---" >> $OUT
     92 			cat ~/.dmc/signature >> $OUT
     93 		fi
     94 	fi
     95 	${EDITOR} ${OUT}
     96 	if [ -z "`cat ${OUT}`" ]; then
     97 		echo "Mail aborted"
     98 		rm -f "${OUT}"
     99 	else
    100 		ln -fs "${OUT}" ~/.dmc/mail.last
    101 	fi
    102 }
    103 
    104 add_attachment () {
    105 	chkcfg
    106 	OUT="`readlink ~/.dmc/mail.last`"
    107 	if [ -z "${OUT}" ]; then
    108 		echo "No ~/.dmc/mail.last found. 'dmc -m' or manual symlink required."
    109 	else
    110 		mkdir -p "${OUT}.d"
    111 		if [ -f "$1" ]; then
    112 			FILE="`basename \"$1\"`"
    113 			ln -fs "$1" "${OUT}.d/${FILE}"
    114 		else
    115 			echo "Cannot find \"$1\""
    116 		fi
    117 	fi
    118 }
    119 
    120 send_message () {
    121 	chkcfg
    122 	FILE=$1
    123 	if [ ! -e "${FILE}" ]; then
    124 		echo "Cannot find '${FILE}'"
    125 		exit 1
    126 	fi
    127 	# TODO: find better name for the auto mode
    128 	if [ -e "${FILE}.d" ]; then
    129 		TMP="`mktemp ~/.dmc/tmp/mail.XXXXXX`"
    130 		cat $FILE | dmc-pack `ls ${FILE}.d/*` > $TMP 
    131 	else
    132 		TMP=$FILE
    133 	fi
    134 	if [ "${SEND}" = "!msmtp" ]; then
    135 		TO="`dmc-filter -v To: < $FILE`"
    136 		SJ="`dmc-filter -v Subject: < $FILE`"
    137 		echo "Sending mail to $TO (${SJ})..."
    138 #		HOST=`dmc-smtp ${TO}`
    139 		msmtp "--user=${USER}" "--from=${MAIL}" $TO < ${TMP}
    140 		return $?
    141 	elif [ "`echo \"${SEND}\" | grep '|'`" ]; then
    142 		echo "=> cat $1 ${SEND}"
    143 		# TODO: setup environment for $TO $SUBJECT ...
    144 		eval cat ${TMP} ${SEND}
    145 	else
    146 		echo "SEND method '${SEND}' not supported"
    147 	fi
    148 	[ -e "${FILE}.d" ] && rm -f $TMP
    149 	return 0
    150 }
    151 
    152 pull_mails () {
    153 	chkcfg
    154 	echo "Pulling mails from account '${NAME}'"
    155 	# This is pop3-only
    156 	i=1
    157 	while [ ! "$LIMIT" = "$i" ] ; do
    158 		dmc -c cat $i > ~/.dmc/box/${NAME}/in/$i.eml 2> ~/.dmc/tmp/${NAME}.tmp
    159 		if [ -n "`cat ~/.dmc/tmp/${NAME}.tmp | grep 'cat 0'`" ]; then
    160 			rm -f ~/.dmc/box/${NAME}/in/$i.eml
    161 			echo "EOF $i"
    162 			cat ~/.dmc/tmp/${NAME}.tmp
    163 			break
    164 		else
    165 			size=`du -hs ~/.dmc/box/${NAME}/in/$i.eml | awk '{print \$1}'`
    166 			echo "got $i $size $(cat ~/.dmc/tmp/${NAME}.tmp)"
    167 		fi
    168 		i=$(($i+1))
    169 	done
    170 }
    171 
    172 ign () { : ; }
    173 
    174 case "$1" in
    175 "start")
    176 	start_account_daemons
    177 	;;
    178 "stop")
    179 	cd ~/.dmc/tmp
    180 	for a in *.input ; do
    181 		[ "$a" = "*.input" ] && break # XXX ugly hack
    182 		file=`echo $a|cut -d '.' -f 1`
    183 		echo Stopping $file daemon
    184 		echo exit > $a &
    185 		sleep 1
    186 		rm -f ~/.dmc/tmp/$a
    187 	done
    188 	rm -f ~/.dmc/tmp/* 2> /dev/null
    189 	pkill cat
    190 	trap ign TERM
    191 	pkill -TERM dmc
    192 	;;
    193 "push")
    194 	for a in ~/.dmc/acc/* ; do
    195 		. $a
    196 		[ ! -d ~/.dmc/box/${NAME}/out ] && continue
    197 		for b in ~/.dmc/box/${NAME}/out/* ; do
    198 			[ ! -f "$b" ] && continue
    199 			send_message "$b"
    200 			if [ $? = 0 ]; then
    201 				echo "Mail sent. local copy moved to ~/.dmc/box/${NAME}/sent"
    202 				mkdir -p ~/.dmc/box/${NAME}/sent
    203 				mv $b ~/.dmc/box/${NAME}/sent
    204 				[ -e "${b}.d" ] && mv ${b}.d ~/.dmc/box/${NAME}/sent
    205 			else
    206 				echo "There was an error sending the mail"
    207 			fi
    208 		done
    209 	done
    210 	;;
    211 "pull")
    212 	for a in ~/.dmc/acc/* ; do
    213 		. $a
    214 		mkdir -p ~/.dmc/box/${NAME}/in
    215 		pull_mails
    216 	done
    217 	;;
    218 "-e"|"--edit")
    219 	if [ -n "$2" ]; then
    220 		[ -z "`cat ~/.dmc/acc/$2`" ] && \
    221 			print_account_template "$2" > ~/.dmc/acc/$2
    222 		${EDITOR} ~/.dmc/acc/$2
    223 		if [ -z "`cat ~/.dmc/acc/$2`" ]; then
    224 			rm -f ~/.dmc/acc/$2
    225 		else
    226 			echo "The '$2' account is now the default"
    227 			ln -fs ~/.dmc/acc/$2 ~/.dmc/acc.default
    228 		fi
    229 	else
    230 		ls ~/.dmc/acc | cat
    231 	fi
    232 	;;
    233 "-c"|"--cmd")
    234 	chkcfg
    235 	if [ -z "$2" ]; then
    236 		while [ ! "$A" = "exit" ] ; do
    237 			printf "> "
    238 			read A
    239 			dmc_cmd "$A"
    240 		done
    241 	else
    242 		shift
    243 		dmc_cmd "$@"
    244 	fi
    245 	;;
    246 "-s"|"--send")
    247 	shift
    248 	chkcfg
    249 	if [ -z "$*" ]; then
    250 		echo "Usage: dmc -s mail1 mail2 ..."
    251 		exit 1
    252 	fi
    253 	for a in $* ; do
    254 		send_message $a
    255 	done
    256 	;;
    257 "-m"|"--mail")
    258 	TO="$2"
    259 	SUBJECT="$3"
    260 	edit_message
    261 	;;
    262 "-A"|"--add-attachment")
    263 	while [ -n "$2" ] ; do
    264 		add_attachment $2
    265 		shift
    266 	done
    267 	;;
    268 "-a"|"--addr")
    269 	if [ -n "$2" ]; then
    270 		while [ -n "$2" ] ; do
    271 			grep -e "$2" ~/.dmc/addrbook
    272 			shift
    273 		done
    274 	else
    275 		[ ! -f ~/.dmc/addrbook ] && touch ~/.dmc/addrbook
    276 		${EDITOR} ~/.dmc/addrbook
    277 	fi
    278 	;;
    279 "-l"|"--list")
    280 	cd ~/.dmc/box/${NAME}/in
    281 	if [ -n "$2" ]; then
    282 		if [ -f "$2.eml" ]; then
    283 			cat $2.eml
    284 			exit 0
    285 		fi
    286 		cd $2
    287 	fi
    288 	for a in `ls -rt *.eml` ; do
    289 		printf "$a:\t\x1b[32m"
    290 		dmc-filter Subject < $a | head -n 1
    291 		printf "\x1b[0m  \t- "
    292 		dmc-filter To < $a | head -n 1
    293 		printf "  \t- "
    294 		dmc-filter Date < $a | head -n 1
    295 	done
    296 	;;
    297 "-v"|"--version")
    298 	echo "dmc v${VERSION}"
    299 	;;
    300 "--help"|"-h")
    301 	echo ${HELP}
    302 	echo " -e account     edit account information"
    303 	echo " -a name        show addressbook email for contact"
    304 	echo " -A file        add attachment to mail"
    305 	echo " -c cmd         run command for \$DMC_ACCOUNT or acc.default daemon"
    306 	echo " -m addr subj   create mail with default account"
    307 	echo " -s file        send email"
    308 	echo " -l [mail/fold] list mails in folder or show mail"
    309 	echo " -v             show version"
    310 	echo " -h             show this help message"
    311 	echo " start          start mail daemons"
    312 	echo " stop           stop them all"
    313 	echo " push           send mails in box/*/out"
    314 	echo " pull           update box/*/in folders"
    315 	;;
    316 *)
    317 	echo "${HELP}"
    318 	;;
    319 esac
    320 
    321 exit 0