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 4821db66cae3338bb0ad9999f01c29649bfbbb69
parent b6c59d34bbe86cb8178592d722a60762d97eb143
Author: Jaromil <jaromil@dyne.org>
Date:   Fri, 18 May 2012 00:32:50 +0200

added options and folders to accounts

Diffstat:
Msrc/jaro | 72++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Dsrc/postino-queue | 412-------------------------------------------------------------------------------
Dsrc/postino-sendmail | 2--
3 files changed, 52 insertions(+), 434 deletions(-)

diff --git a/src/jaro b/src/jaro @@ -46,7 +46,8 @@ PARAM=() typeset -A global_opts typeset -A opts -typeset -h name login host protocol port password auth cert +# global variables for accounts +typeset -h name login host protocol port password auth folders accountopt autoload colors; colors @@ -102,13 +103,16 @@ ${=mkdir} "$WORKDIR/certs" PROCMAILDIR=$WORKDIR/.procmail MUTTDIR=$WORKDIR/.mutt +cleanexit() { + for f in `ls $WORKDIR/tmp/`; do + ${=rm} $WORKDIR/tmp/$f + done + unset typeset -h name login host protocol port password auth folders accountopt +} # make sure tmp is wiped from sensitive data in case of sigINT TRAPINT() { error "Caught signal, aborting operations." - for f in `ls $WORKDIR/tmp/`; do - ${=rm} $f - done - + cleanexit if [ "$DEBUG" = "1" ]; then return 1 else @@ -256,21 +260,24 @@ read_account() { /^login/ { printf "login=\"%s\";", $2 } /^transport/ { printf "transport=\"%s\";", $2 } /^port/ { printf "port=\"%s\";", $2 } - /^password/ {printf "password=\"%s\";", $2 } + /^password/ { printf "password=\"%s\";", $2 } /^auth/ { printf "auth=\"%s\";", $2 } - /^cert/ { printf "cert=\"%s\";", $2 } + /^options/ { printf "accountopt=\"%s\";", $2 } + /^folders/ { printf "folders=\"%s\";", $2 } '` eval "$ttmp" # check required fields - { test -z $name } && { error "Field missing in account $acct: name"; return 1 } - { test -z $host } && { error "Field missing in account $acct: host"; return 1 } + { test -z $host } && { error "Field missing in account $acct: host"; return 1 } { test -z $login } && { error "Field missing in account $acct: login"; return 1 } # fill in defaults - { test -z $transport } && { transport=ssl } - { test -z $port } && { port=993 } - { test -z $auth } && { auth=plain } + { test -z $name } && { name="$type" } + { test -z $transport } && { transport=ssl } + { test -z $port } && { port=993 } + { test -z $auth } && { auth=plain } + { test -z $accountopt } && { accountopt=keep } # cert and password can be missing + func "type: $type" func "name: $name" func "host: $host" func "login: $login" @@ -278,6 +285,8 @@ read_account() { func "port: $port" func "cert: $cert" func "auth: $auth" + func "options: $accountopt" + func "folders: $folder" ;; *) error "Account type \"$type\" not recognized." @@ -460,19 +469,40 @@ fetch() { cat <<EOF > $WORKDIR/tmp/$host.fetch poll $host with proto IMAP user "$login" there with password "$password" -keep and ssl warnings 3600 and wants mda "procmail -m $PROCMAILDIR/rc" +EOF + if ! [ -z $accountopt ]; then # add option configuration + echo "${accountopt}" >> $WORKDIR/tmp/$host.fetch; fi + if ! [ -z $folders ]; then # add folder configuration + echo "folder ${folders}" >> $WORKDIR/tmp/$host.fetch; fi + cat <<EOF >> $WORKDIR/tmp/$host.fetch +ssl warnings 3600 and wants mda "procmail -m $PROCMAILDIR/rc" sslcertck sslcertpath '$WORKDIR/certs' antispam 571 550 501 554 EOF unset password - # this function generates a fetchmail configuration and downloads emails + + # try login without doing anything fetchmail -c -f $WORKDIR/tmp/$host.fetch - # no mails found - if [ $? = 1 ]; then - notice "No mails for $name" - ${=rm} $WORKDIR/tmp/$host.fetch - return 1 - fi + # examine result + case $? in + 1) + notice "No mails for $name" + ${=rm} $WORKDIR/tmp/$host.fetch + return 1 + ;; + 2) + error "Invalid or unknown certificate for $host" + ${=rm} $WORKDIR/tmp/$host.fetch + return 1 + ;; + 3) + error "Invalid password for user $login at $host" + ${=rm} $WORKDIR/tmp/$host.fetch + return 1 + ;; + *) ;; + esac + # archive old procmail log if [ -r $WORKDIR/log/procmail.log ]; then touch $WORKDIR/log/procmail-${datestamp}.log @@ -900,3 +930,4 @@ main() check_bin main $@ +cleanexit+ \ No newline at end of file diff --git a/src/postino-queue b/src/postino-queue @@ -1,412 +0,0 @@ -#!/usr/bin/env bash - -#-------------------------------------------------------------- -# -# msmtpq : queue funtions to both use & manage the msmtp queue, -# as it was defined by Martin Lambers -# Copyright (C) 2008, 2009, 2010 Chris Gianniotis -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or, at -# your option, any later version. -# -#-------------------------------------------------------------- - -# msmtpq is meant to be used both by an email client - -# in 'sendmail' mode -# for this purpose, it is evoked by the symlink 'msmtpQ' -# ( created as ln -s msmtpq msmtpQ ) -# it is also meant to be used to maintain the msmtp queue -# as 'msmtpq' - -# there is a queue log file, distinct from the msmtp log, -# for all events & operations on the msmtp queue -# that is defined below - -# (mutt users, using msmtpQ in 'sendmail' mode, -# should make at least the following two settings in their .muttrc -# set sendmail = /path/to/msmtpQ -# set sendmail_wait = -1 -# -# please see the msmtp man page and docs for further mutt settings -# ) - - -#-------------------------------------------------------------- -# the msmtp queue contains unique filenames of the following form : -# two files for each mail in the queue -# -# creates new unique filenames of the form : -# MLF: ccyy-mm-dd-hh.mm.ss[-x].mail -- mail file -# MSF: ccyy-mm-dd-hh.mm.ss[-x].msmtp -- msmtp command line file -# where x is a consecutive number only appended for uniqueness -# if more than one mail per second is sent -#-------------------------------------------------------------- - - -dsp() { local L ; for L ; do [ -n "$L" ] && echo " $L" || echo ; done ; } -err() { dsp '' "$@" '' ; exit 1 ; } - -if [ -r $HOME/.postinorc ]; then - . $HOME/.postinorc -elif [ -r $HOME/.postino/main.conf ]; then - . $HOME/.postino/main.conf -else - echo "Postino not in use on this machine, operation aborted." - return 1 -fi - - -## ====================================================================================== -## !!! please define or confirm the following three vars !!! -## !!! before using the msmtpq/msmtpQ routine !!! -## ====================================================================================== -## -## only if necessary (in unusual circumstances - e.g. embedded systems), -## enter the location of the msmtp executable (no quotes !!) -## e.g. ( MSMTP=/path/to/msmtp ) -MSMTP=msmtp -#[ -x "$MSMTP" ] || \ -# log -e 1 "msmtpq : can't find the msmtp executable [ $MSMTP ]" # if not found - complain ; quit -## -## set the queue var to the location of the msmtp queue directory -## if the queue dir doesn't yet exist, better to create it (0700) -## before using this routine -## e.g. ( mkdir msmtp.queue ) -## ( chmod 0700 msmtp.queue ) -## -## the queue dir - modify this to reflect where you'd like it to be (no quotes !!) -Q=$MAILDIRS/queue -[ -d "$Q" ] || \ - err '' "msmtpq : can't find msmtp queue directory [ $Q ]" '' # if not present - complain ; quit -## -## set the queue log file var to the location of the msmtp queue log file -## where it is or where you'd like it to be -## ( note that the LOG setting could be the same as the ) -## ( 'logfile' setting in .msmtprc - but there may be ) -## ( some advantage in keeping the two logs separate ) -## if you don't want the log at all unset (comment out) this var -## LOG=~/log/msmtp.queue.log --> #LOG=~/log/msmtp.queue.log -## (doing so would be inadvisable under most conditions, however) -## -## the queue log file - modify (or comment out) to taste (but no quotes !!) -LOG=$WORKDIR/queue.log -## ====================================================================================== - -umask 077 # set secure permissions on created directories and files - -declare -i CNT # a count of mail(s) currently in the queue - -trap on_exit EXIT # run 'on_exit' on exit -on_exit() { - [ -n "$LKD" ] && lock_queue -u 2>/dev/null # unlock the queue on exit -} # if the lock was set here - -# -## ----------------------------------- common functions -# - -## make an entry to the queue log file, possibly an error -## (log queue changes only ; not interactive chatter) -## usage : log [ -e errcode ] msg [ msg ... ] -## opts : -e <exit code> an error ; log msg & terminate w/prejudice -## display msg to user, as well -log() { - local ARG RC PFX="$('date' +'%Y %d %b %H:%M:%S')" - # time stamp prefix - "2008 13 Mar 03:59:45 " - if [ "$1" = '-e' ] ; then # there's an error exit code - RC="$2" # take it - shift 2 # shift opt & its arg off - fi - - dsp "$@" # display msg to user, as well as logging it - - if [ -n "$LOG" ] ; then # log is defined and in use - for ARG ; do # each msg line out - [ -n "$ARG" ] && \ - echo "$PFX : $ARG" >> "$LOG" # line has content ; send it to log - done - fi - - if [ -n "$RC" ] ; then # an error ; leave w/error return - [ -n "$LOG" ] && \ - echo " exit code = $RC" >> "$LOG" # logging ok ; send exit code to log - exit $RC # exit w/return code - fi -} - -## write/remove queue lockfile for a queue op -lock_queue() { # <-- '-u' to remove lockfile - local LOK="${Q}/.lock" # lock file name - local -i MAX=240 SEC=0 # max seconds to gain a lock ; seconds waiting - - if [ -z "$1" ] ; then # lock queue - while [ -e "$LOK" ] && (( SEC < MAX )) ; do # lock file present - sleep 1 # wait a second - (( ++SEC )) # accumulate seconds - done # try again while locked for MAX secs - [ -e "$LOK" ] && \ - err '' "cannot use queue $Q : waited $MAX seconds for"\ - " lockfile [ $LOK ] to vanish ; giving up"\ - 'if you are certain that no other instance of this script'\ - ' is running, then delete the lock file manually' '' # lock file still there, give up - - touch "$LOK" && \ - LKD='t' || \ - log -e "$?" "couldn't create queue lock file [ $LOK ]" # lock queue - - elif [ "$1" = '-u' ] ; then # unlock queue - 'rm' -f "$LOK" # remove the lock - fi -} - -# -## ----------------------------------- functions for queue management -## ----------------------------------- queue maintenance mode - (msmtpq) -# - -## show queue maintenance functions -usage() { # <-- error msg - dsp ''\ - 'usage : msmtpq functions' ''\ - ' msmtpq <op>'\ - ' ops : -r run (flush) mail queue - all mail in queue'\ - ' -R send selected individual mail(s) in queue'\ - ' -d display (list) queue contents (<-- default)'\ - ' -p purge individual mail(s) from queue'\ - ' -a purge all mail in queue'\ - ' -h this helpful blurt' ''\ - ' ( one op only ; any others ignored )' '' - [ -z "$1" ] && exit 0 || { dsp "$@" '' ; exit 1 ; } -} - -## get user [y/n] acknowledgement -ok() { - local R YN='Yn' # default to yes - - [ "$1" = '-n' ] && \ - { YN='yN' ; shift ; } # default to no ; change prompt ; shift off spec - - dsp "$@" - while true ; do - echo -n " ok [${YN}] ..: " ; read R - case $R in - y|Y) return 0 ;; - n|N) return 1 ;; - '') [ "$YN" = 'Yn' ] && return 0 || return 1 ;; - *) echo 'yYnN<cr> only please' ;; - esac - done -} - -## is anything in the queue ? -## sets CNT global var or -## exits w/passed msg -cnt_queue() { # <-- op label { 'purge' | 'send' } - CNT=$('ls' -1 ${Q}/*.mail 2>/dev/null | 'wc' -l) # take num mails in queue - - if (( CNT == 0 )) ; then # no mail in Q - dsp '' "mail queue is empty (nothing to $1)" '' # inform user - exit 0 # depart - fi -} - -## send a queued mail out via msmtp -send_queued_mail() { # <-- mail id - local FQP="${Q}/${1}" # fully qualified path name - local -i RC=0 # for msmtp exit code - - if [ -f "${FQP}.msmtp" ] ; then # corresponding .msmtp file found - # verify net connection - ping ip address of debian.org - if ping -qnc1 -w2 debian.org > /dev/null 2>&1 ; then # connected - if $MSMTP $(< "${FQP}.msmtp") < "${FQP}.mail" ; then # this mail goes out the door - 'rm' -f ${FQP}.* # nuke both queue mail files - log "mail [ $1 ] from queue ; send was successful ; purged from queue" # good news to user - ALT='t' # set queue changed flag - else # send was unsuccessful - RC=$? # take msmtp exit code - log "mail [ $1 ] from queue ; send failed ; msmtp rc = $RC" # bad news ... - fi - return $RC # func returns exit code - else # not connected - dsp "mail [ $1 ] from queue ; couldn't be sent - host not connected" - return 1 - fi - else # corresponding MSF file not found - log "preparing to send .mail file [ ${FQP}.mail ] but"\ - " corresponding .msmtp file [ ${FQP}.msmtp ] was not found in queue"\ - ' skipping this mail ; this is worth looking into' # give user the bad news - fi # (but allow continuation) -} - -## run (flush) queue -run_queue() { # run queue - local M LST="$('ls' $Q/*.mail 2>/dev/null)" # list of mails in queue - - if [ -n "$LST" ] ; then # something in queue - for M in $LST ; do # process all mails - send_queued_mail "$(basename $M .mail)" # send mail - pass {id} only - done - else # queue is empty - dsp '' 'mail queue is empty (nothing to send)' '' # inform user - fi -} - -## display queue contents -display_queue() { - local M LST="$('ls' $Q/*.mail 2>/dev/null)" # list of mails in queue - - if [ -n "$LST" ] ; then # list has contents (any mails in queue) - for M in $LST ; do # cycle through each - dsp '' "mail id = [ $(basename $M .mail) ]" # show mail id - 'egrep' -s --colour -h '(^From:|^To:|^Subject:)' "$M" # show mail info - done - echo - else # no mails ; no contents - dsp '' 'no mail in queue' '' # inform user - fi -} - -## delete all mail in queue, after confirmation -purge_queue() { - local YN # confirmation response - - cnt_queue 'purge' - display_queue # show queue contents - if ok -n 'remove (purge) all mail from the queue' ; then - 'rm' -f "$Q"/*.* - log 'msmtp queue purged (all mail)' - else - dsp '' 'nothing done ; queue is untouched' '' - fi -} - -## select a single mail from queue ; delete it or send it -select_mail() { # <-- '-purge' or '-send' - local ONE ID # mail id - - while true ; do # purge an individual mail from queue - cnt_queue "${1:1}" # count queue entries - display_queue # show queue contents - - if (( CNT == 1 )) ; then # only one mail in queue ; take its id - ID="$(basename $('ls' $Q/*.mail 2>/dev/null) .mail)" - ONE='t' # mark single mail - else # more than one mail ; select its id - while true ; do # get mail id - dsp '' "enter mail id to ${1:1}" # <-- file name (only, no suff) - echo -n ' ( <cr> alone to exit ) ..: ' ; read ID - [ -n "$ID" ] || return # entry made - or say good bye - 'ls' "$Q"/"$ID".* >/dev/null 2>&1 && \ - break || \ - dsp '' "mail [ $ID ] not found ; bad id" # id valid or complain & ask again - done - fi - - if ok "${1:1} mail - id = [ $ID ]" ; then # confirm mail op - if [ "$1" = '-purge' ] ; then # purging - 'rm' -f "$Q"/"$ID".* # msmtp - nukes single mail (both files) in queue - log "mail [ $ID ] purged from queue" # log op - ALT='t' # mark that a queue alteration has taken place - else # sending - send_queued_mail "$ID" # send out the mail - fi - else # user opts out - dsp '' 'nothing done to this queued email' # soothe user - [ -n "$ONE" ] && break # single mail ; user opted out - fi - dsp '' "--------------------------------------------------" - done - - if [ -n "$ALT" ] ; then # queue was changed - dsp '' 'done' '' - else # queue is untouched - dsp '' 'nothing done ; queue is untouched' '' - fi -} - -# -## ----------------------------------- functions for directly sending mail -## ----------------------------------- 'sendmail' mode - (msmtpQ) -# - -## ('sendmail' mode only) -## make base filename id for queue -make_id() { - local -i INC # increment counter for (possible) base fqp name collision - - ID="$(date +%Y-%m-%d-%H.%M.%S)" # make filename id for queue - FQP="${Q}/$ID" # make fully qualified pathname - if [ -f "${FQP}.*" ] ; then # ensure fqp name is unique - INC=1 # initial increment - while [ -f "${FQP}-${INC}.*" ] ; do # fqp name w/incr exists - (( ++INC )) # bump increment - done - ID="${ID}-${INC}" # unique ; set id - FQP="${FQP}-${INC}" # unique ; set fqp name - fi -} - -## ('sendmail' mode only) -## enqueue a mail -enqueue_mail() { # <-- all mail args ; mail text via TMP - if echo "$@" > "${FQP}.msmtp" ; then # write msmtp command line to queue .msmtp file - log "enqueued mail as : [ $ID ] ( $* ) : successful" # (queue .mail file is already there) - else # write failed ; bomb - log -e "$?" "queueing - writing msmtp cmd line { $* }"\ - " to [ ${ID}.msmtp ] : failed" - fi -} - -## ('sendmail' mode only) -## send a mail (if possible, otherwise enqueue it) -## if send is successful, msmtp will also log it (if enabled in ~/.msmtprc) -send_mail() { # <-- all mail args ; mail text via TMP - # verify net connection - ping ip address of debian.org - if ping -qnc1 -w4 debian.org > /dev/null 2>&1 ; then # we're online, connected - if $MSMTP "$@" < "${FQP}.mail" > /dev/null ; then # send mail using queue .mail fil - log "mail for [ $* ] : send was successful" # log it - 'rm' -f "${FQP}.mail" # remove queue .mail file - run_queue # run/flush any other mails in queue - else # send failed - log "mail for [ $* ] : send was unsuccessful ; msmtp exit code was $?" - enqueue_mail "$@" # enqueue the mail - fi - else # not connected to net ; log msg - log "mail for [ $* ] : couldn't be sent - host not connected" - enqueue_mail "$@" # enqueue the mail - fi -} - -# -## -- entry point -# - -case "$(basename $0)" in # get name script called as - postino-sendmail) # called as 'msmtpQ' - sendmail mode - lock_queue # lock here - make_id # make base queue filename id for this mail - cat > "${FQP}.mail" || \ - log -e "$?" "creating mail body file [ ${FQP}.mail ] : failed" # test for error - send_mail "$@" # send the mail if possible, queue it if not - ;; - postino-queue) # called as 'msmtpq' - queue management mode - OP=${1:1} # trim off first char of OP - case "$OP" in # sort ops ; run according to spec - r) lock_queue ; run_queue ;; # run (flush) the queue - R) lock_queue ; select_mail -send ;; # send individual mail(s) in queue - d|'') display_queue ;; # display (list) all mail in queue (defaykt) - p) lock_queue ; select_mail -purge ;; # purge individual mail(s) from queue - a) lock_queue ; purge_queue ;; # purge all mail in queue - h) usage ;; # show help - *) usage "[ $OP ] is an unknown msmtpq option" ;; - esac - ;; - *) # invalid name - err "msmtpq can only be called as 'msmtpq' or 'msmtpQ'"\ - "{ $(basename $0) } doesn't work" - ;; -esac - -exit 0 diff --git a/src/postino-sendmail b/src/postino-sendmail @@ -1 +0,0 @@ -postino-queue- \ No newline at end of file