jaromail

a commandline tool to easily and privately handle your e-mail
git clone git://parazyd.org/jaromail.git
Log | Files | Refs | Submodules | README

commit 44f170367b78805767ecdad3cdbb3ceeec6a6079
parent a8437a171152c017e50dac4d46f8ba8403fafd34
Author: Jaromil <jaromil@dyne.org>
Date:   Tue, 26 Jun 2012 19:40:51 +0200

fix to account selection and dryrun

Diffstat:
Msrc/jaro | 27+++++++++++++++------------
Msrc/zlibs/accounts | 53+++++++++++++++++++++++++++++++++++++++++------------
Msrc/zlibs/email | 264++++++++++++++++++++++++++++++++++++++++---------------------------------------
3 files changed, 190 insertions(+), 154 deletions(-)

diff --git a/src/jaro b/src/jaro @@ -53,7 +53,7 @@ typeset -A opts # global variable for account selection typeset -h account -account=default +# account=default typeset -h list list=whitelist @@ -429,14 +429,18 @@ main() cat $JAROMAILEXEC | awk '/^#/ {print $0 } !/^#/ {exit}' echo fi - if option_is_set -a; then account=`option_value -a`; fi - if option_is_set -l; then list=`option_value -l`; fi - { option_is_set -h } && { CLEANEXIT=0; usage; return 0 } - { option_is_set -v } && { CLEANEXIT=0; - cat $JAROMAILEXEC | awk 'BEGIN { v=1 } !/^#/ { exit }'; return 0 } - if option_is_set -q; then QUIET=1; fi - if option_is_set -D; then func "Debug messages ON"; DEBUG=1; fi - if option_is_set -n; then act "Dry run, show operations without executing them."; DRYRUN=1; fi + { option_is_set -a } && { account=`option_value -a` } + { option_is_set -l } && { list=`option_value -l` } + { option_is_set -h } && { CLEANEXIT=0 + usage; return 0 } + { option_is_set -v } && { CLEANEXIT=0 + cat $JAROMAILEXEC | awk 'BEGIN { v=1 } !/^#/ { exit }' + return 0 } + { option_is_set -q } && { QUIET=1 } + { option_is_set -D } && { DEBUG=1 + func "Debug messages ON" } + { option_is_set -n } && { DRYRUN=1 + act "Dry run, show operations without executing them." } case "$subcommand" in queue) queue ${PARAM} ;; @@ -464,9 +468,8 @@ main() merge) merge ${PARAM} ;; filter) filter ${PARAM} ;; - passwd) read_account; - { test $? = 0 } && { new_password ${PARAM} } - ;; + passwd) change_password ${PARAM} ;; + cert) cert ${PARAM} ;; ramdisk) ramdisk ${PARAM} ;; diff --git a/src/zlibs/accounts b/src/zlibs/accounts @@ -37,15 +37,42 @@ EOF fi } - +list_accounts() { + for a in `find $WORKDIR/Accounts -type f | grep -v README | sed 's/.txt//'`; do + act -n "`basename $a`\t :: " + awk ' +/^name/ { for(i=2;i<=NF;i++) printf "%s ", $i } +/^email/ { printf "<%s>", $2 } +/^host/ { printf " on %s", $2 } +{next}' $a.txt + echo " (`basename $a | cut -d. -f1`)" + done +} # arg 1 : account type, es: imap or smtp # -a defines which account name other than 'default' read_account() { typeset -al all - type=$1 + + # parse arguments + { test "$1" != "" } && { account=$1 } + + account=".${account}" + type=`echo ${account} | cut -d. -f2` + account=`echo ${account} | cut -d. -f3` + + { test "$2" != "" } && { account=$2 } + + { test "$type" = "default" } && { + error "No account type specified" + act "Available accounts (excluding symbolic links, omit final .txt):" + list_accounts + return 1 + } + { test "$account" = "" } && { account=default } + # find the file - func "read_account looking for \"$account\"" + func "read_account looking for ${type} ${account}" for a in `find $WORKDIR/Accounts -name "$type.$account*"`; do func "found account: $a" all+=($a) @@ -55,15 +82,7 @@ read_account() { act "Refine your argument using '-a type.account'" act "For instance adding to the commandline: -a imap.default" act "Available accounts (excluding symbolic links, omit final .txt):" - for a in `find $WORKDIR/Accounts -type f | grep -v README | sed 's/.txt//'`; do - act -n "`basename $a`\t :: " - awk ' -/^name/ { for(i=2;i<=NF;i++) printf "%s ", $i } -/^email/ { printf "<%s>", $2 } -/^host/ { printf " on %s", $2 } -{next}' $a.txt - echo " (`basename $a | cut -d. -f1`)" - done + list_accounts return 1 elif [ ${#all} != 1 ]; then error "Too many $type accounts named $account" @@ -274,3 +293,12 @@ EOF return 1 esac } + +change_password() { + + read_account ${=PARAM} + + { test $? = 0 } && { test $DRYRUN != 1 } && { + new_password } + +}+ \ No newline at end of file diff --git a/src/zlibs/email b/src/zlibs/email @@ -66,116 +66,115 @@ fetchall() { for i in `find $WORKDIR/Accounts -type f | grep -v README`; do account=`basename $i` type=`echo $account | cut -d. -f1` - func "fetchall: $account type $type" - fetch $account.$type + account=`echo $account | cut -d. -f2` + fetch $type $account if [ $? != 0 ]; then res=1; fi # returns an error if just one of the accounts did done return $res } fetch() { + + func "Fetch account ${@}" + # recursion here + { test ${#@} = 0 } && { fetchall; return $? } + adir=$WORKDIR/Accounts typeset -al all - # argument is account type.name - { test $1 } && { - type=`echo $1 | cut -d. -f1` - account=`echo $1 | cut -d. -f2` - func "fetch type $type account $account" - } - # recursion here - { test $account = default } && { fetchall; return $? } - - read_account $type + read_account ${=@} - if [ $? != 0 ]; then + { test $? != 0 } && { error "Account configuration not found, or broken. Aborting operation." return 1 - fi + } - if [ "$type" = "smtp" ]; then # we skip smtp in fetch - return 0; fi + # fetch works with imap and pop, skip smtp + { test "$type" = "smtp" } && { return 0 } if ! [ -r $PROCMAILDIR/rc ]; then act "updating procmail configuration" - update + { test $DRYRUN != 1 } && { update } fi notice "Fetching mails for $name" - ask_password $login $host - { test $? != 0 } && { - error "Error retrieving password for $login on $host" - unset password all; return 1 - } - - tmp=$TMPDIR/$host.fetch.$RANDOM - newlock $tmp - cat <<EOF > $tmp + { test $DRYRUN != 1 } && { + ask_password $login $host + { test $? != 0 } && { + error "Error retrieving password for $login on $host" + unset password all; return 1 + } + + tmp=$TMPDIR/$host.fetch.$RANDOM + newlock $tmp + cat <<EOF > $tmp poll $host with proto IMAP user "$login" there with password "$password" EOF - unset password - - if ! [ -z $accountopt ]; then # add option configuration - echo "${accountopt}" >> $tmp; fi - - if ! [ -z $folders ]; then # add folder configuration - echo "folder ${folders}" >> $tmp; fi - - cat <<EOF >> $tmp + unset password + + if ! [ -z $accountopt ]; then # add option configuration + echo "${accountopt}" >> $tmp; fi + + if ! [ -z $folders ]; then # add folder configuration + echo "folder ${folders}" >> $tmp; fi + + cat <<EOF >> $tmp ssl warnings 3600 and wants mda "procmail -m $PROCMAILDIR/rc" EOF - if [ "$cert" = "check" ]; then - cat <<EOF >> $tmp + if [ "$cert" = "check" ]; then + cat <<EOF >> $tmp sslcertck sslcertpath '$WORKDIR/certs' EOF - fi - cat <<EOF >> $tmp + fi + cat <<EOF >> $tmp antispam 571 550 501 554 EOF - + # try login without doing anything - fetchmail -c -f $tmp + fetchmail -c -f $tmp # examine result - case $? in - 1) - notice "No mails for $name" - unlink $tmp - return 1 + case $? in + 1) + notice "No mails for $name" + unlink $tmp + return 1 ;; - 2) - error "Invalid or unknown certificate for $host" - unlink $tmp - return 1 - ;; - 3) - error "Invalid password for user $login at $host" - unlink $tmp - return 1 - ;; - *) ;; - esac - + 2) + error "Invalid or unknown certificate for $host" + unlink $tmp + return 1 + ;; + 3) + error "Invalid password for user $login at $host" + unlink $tmp + return 1 + ;; + *) ;; + esac + # archive old procmail log - if [ -r $WORKDIR/log/procmail.log ]; then - newlock $WORKDIR/log/procmail-${datestamp}.log - cat $WORKDIR/log/procmail.log \ - >> $WORKDIR/log/procmail-${datestamp}.log - rm -f $WORKDIR/log/procmail.log - unlock $WORKDIR/log/procmail-${datestamp}.log - fi - act "please wait while downloading mails..." - - cat $tmp | fetchmail -f $tmp + if [ -r $WORKDIR/log/procmail.log ]; then + newlock $WORKDIR/log/procmail-${datestamp}.log + cat $WORKDIR/log/procmail.log \ + >> $WORKDIR/log/procmail-${datestamp}.log + rm -f $WORKDIR/log/procmail.log + unlock $WORKDIR/log/procmail-${datestamp}.log + fi + act "please wait while downloading mails..." + + cat $tmp | fetchmail -f $tmp # TODO: substitute this with cat conf | fetchmail -f - # to avoid writing the password in clear on filesystem + + unlink $tmp + + total=`mailstat -k $WORKDIR/log/procmail.log | tail -n1 | awk '{print $2}'` + briefing=`mailstat -kt $WORKDIR/log/procmail.log |awk '!/procmail/ { print " " $2 "\t" $3 }'|sort -nr` + notice "$total emails fetched" + echo "${briefing}" - unlink $tmp - - total=`mailstat -k $WORKDIR/log/procmail.log | tail -n1 | awk '{print $2}'` - briefing=`mailstat -kt $WORKDIR/log/procmail.log |awk '!/procmail/ { print " " $2 "\t" $3 }'|sort -nr` - notice "$total emails fetched" - echo "${briefing}" + } # DRYRUN return 0 } @@ -196,28 +195,28 @@ send() { return 0 fi - read_account smtp - if [ $? != 0 ]; then + read_account smtp ${=@} + { test $? != 0 } && { error "Account configuration not found, or broken. Aborting operation." return 1 - fi + } - notice "Sending out ${mailnum} mails via $name" + notice "Sending out ${mailnum} mails via ${type}.${account}" # defaults - [ -z $auth ] && auth=plain - [ -z $port ] && port=25 - - - ask_password $login $host - { test $? != 0 } && { - error "Error retrieving password for $login on $host" - unset password all; return 1 - } - - tmp=$TMPDIR/$host.send.$RANDOM - newlock $tmp - cat <<EOF > $tmp + { test -z $auth } && { auth=plain } + { test -z $port } && { port=25 } + + { test $DRYRUN != 1 } && { + ask_password $login $host + { test $? != 0 } && { + error "Error retrieving password for $login on $host" + unset password all; return 1 + } + + tmp=$TMPDIR/$host.send.$RANDOM + newlock $tmp + cat <<EOF > $tmp account default from ${email} user ${login} @@ -230,26 +229,27 @@ logfile ${WORKDIR}/log/msmtp.log auth ${auth} password ${password} EOF - unset password - - for mail in `find $MAILDIRS/outbox -name "*.mail"`; do - smtp=`echo ${mail} | sed -e 's/mail/msmtp/'` - lock ${smtp} - recipients="`cat ${smtp}`" - act "To: ${recipients}" - msmtp -C $tmp -- ${=recipients} < "${mail}" - if [ $? != 0 ]; then - error "Error sending mail, skipped" - unlock ${smtp} - else - act "Mail sent succesfully" + unset password + + for mail in `find $MAILDIRS/outbox -name "*.mail"`; do + smtp=`echo ${mail} | sed -e 's/mail/msmtp/'` + lock ${smtp} + recipients="`cat ${smtp}`" + act "To: ${recipients}" + msmtp -C $tmp -- ${=recipients} < "${mail}" + if [ $? != 0 ]; then + error "Error sending mail, skipped" + unlock ${smtp} + else + act "Mail sent succesfully" # whitelist those to whom we send mails - cat ${mail} | $WORKDIR/bin/jaro -l whitelist -q learn to: - ${=rm} ${mail} & - unlink ${smtp} & - fi - done - unlink $tmp + cat ${mail} | $WORKDIR/bin/jaro -l whitelist -q learn to: + ${=rm} ${mail} & + unlink ${smtp} & + fi + done + unlink $tmp + } # DRYRUN return 0 } @@ -257,11 +257,11 @@ EOF # PEEK # this function will open the MTA to the imap server without fetching mails locally peek() { - read_account imap - if [ $? != 0 ]; then + read_account imap ${account} + { test $? != 0 } && { error "Account configuration not found, or broken. Aborting operation." return 1 - fi + } notice "Peek into remote imap account $name" @@ -281,24 +281,28 @@ peek() { # escape at sign in login ilogin=`echo $login | sed 's/@/\\@/'` - ask_password $login $host - { test $? != 0 } && { - error "Error retrieving password for $login on $host" - unset password all; return 1 - } - tmp=$TMPDIR/$host.peek.$RANDOM - newlock $tmp - cat <<EOF >> $tmp + { test $DRYRUN != 1 } && { + + ask_password $login $host + { test $? != 0 } && { + error "Error retrieving password for $login on $host" + unset password all; return 1 + } + tmp=$TMPDIR/$host.peek.$RANDOM + newlock $tmp + cat <<EOF >> $tmp set imap_pass = "${password}" # set imap_peek = yes EOF - unset password - echo "source $tmp" >> $MUTTDIR/password - (sleep 1; - cp /dev/null $MUTTDIR/password - cp /dev/null $tmp - unlink $tmp - ) & - mutt -F $MUTTDIR/rc -f ${iproto}://${ilogin}@${host}${folder} + unset password + echo "source $tmp" >> $MUTTDIR/password + (sleep 1; + cp /dev/null $MUTTDIR/password + cp /dev/null $tmp + unlink $tmp + ) & + mutt -F $MUTTDIR/rc -f ${iproto}://${ilogin}@${host}${folder} + + } # DRYRUN return $? }