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