commit 0e1e1e9cb2ff662780c3ab3a9131cf253844812e
parent 0857fed85fe514e1da491d3756b8e2df18d06a03
Author: Jaromil <jaromil@dyne.org>
Date: Thu, 15 Jan 2015 13:59:47 +0100
filter delivery cleanup and optimizations, fixes to exitcodes and more code cleanups
Diffstat:
5 files changed, 207 insertions(+), 150 deletions(-)
diff --git a/src/jaro b/src/jaro
@@ -34,6 +34,9 @@ DEBUG=0
DRYRUN=0
CALLMUTT=1
+# use gnome-keyring for passwords on GNU systems
+GNOMEKEY=0
+
# default permission on files
umask 066
@@ -86,7 +89,7 @@ typeset -al maildirs
typeset -h mutt pgpewrap dotlock
# global variable for exit code
-typeset exitcode
+typeset -h exitcode
# exitcode=0
# global variable for infos on imap folder
@@ -255,10 +258,10 @@ KEYRING="$MAILDIRS/Keyring"
# Cleanup anything sensitive before exiting.
-_endgame() {
+endgame() {
func "endgame() $1"
- [[ "$1" = "EXIT" ]] || {
- error "QUIT signal sent to processes, waiting 2 seconds..."
+ [[ "$1" = "NOERRORS" ]] || {
+ error "$1 signal sent to processes, waiting to quit..."
global_quit=1
sleep 2
}
@@ -274,17 +277,18 @@ _endgame() {
unlock "$MAILDIRS"/cache/notmuch
}
func "endgame() exit code: $exitcode"
+ return $exitcode
}
# Trap functions for the _endgame event
-TRAPINT() { _endgame INT; return $exitcode }
-# TRAPEXIT() { _endgame EXIT; return $exitcode }
-TRAPHUP() { _endgame HUP; return $exitcode }
-TRAPQUIT() { _endgame QUIT; return $exitcode }
-TRAPABRT() { _endgame ABORT; return $exitcode }
-TRAPKILL() { _endgame KILL; return $exitcode }
-TRAPPIPE() { _endgame PIPE; return $exitcode }
-TRAPTERM() { _endgame TERM; return $exitcode }
-TRAPSTOP() { _endgame STOP; return $exitcode }
+TRAPINT() { _endgame INT; return $? }
+# TRAPEXIT() { _endgame EXIT; return $? }
+TRAPHUP() { _endgame HUP; return $? }
+TRAPQUIT() { _endgame QUIT; return $? }
+TRAPABRT() { _endgame ABORT; return $? }
+TRAPKILL() { _endgame KILL; return $? }
+TRAPPIPE() { _endgame PIPE; return $? }
+TRAPTERM() { _endgame TERM; return $? }
+TRAPSTOP() { _endgame STOP; return $? }
# TRAPZERR() { func "function returns non-zero." }
case $OS in
@@ -334,11 +338,6 @@ MUTTDIR="$MAILDIRS/.mutt"
cp "$WORKDIR/Mutt.txt" "$MAILDIRS/Mutt.txt"
notice "Default Mutt configuration template created" }
-# use gnome-keyring for passwords on GNU systems
-GNOMEKEY=0
-pidof gnome-keyring-daemon > /dev/null && {
- act "using gnome-keyring to store secrets"
- GNOMEKEY=1 }
# binary programs recognition
check_bin() {
@@ -354,47 +353,53 @@ check_bin() {
# make sure a gnupg dir exists
{ test -r $HOME/.gnupg/pubring.gpg } || {
- ${=mkdir} $HOME/.gnupg
- touch $HOME/.gnupg/pubring.gpg
- touch $HOME/.gnupg/secring.gpg
+ ${=mkdir} $HOME/.gnupg
+ touch $HOME/.gnupg/pubring.gpg
+ touch $HOME/.gnupg/secring.gpg
}
# which find command to use
case $OS in
- GNU) find="find -O3" ;;
- MAC) find="gfind -O3" ;;
- *) find="find"
+ GNU) find="find -O3" ;;
+ MAC) find="gfind -O3" ;;
+ *) find="find"
esac
# which wipe command to use
if command -v wipe > /dev/null; then
- rm="wipe -f -s -q -R /dev/urandom"
+ rm="wipe -f -s -q -R /dev/urandom"
elif command -v srm > /dev/null; then
- rm="srm -m"
+ rm="srm -m"
else
- rm="rm -f"
+ rm="rm -f"
fi
func "Rm binary: $rm"
# which mutt binary to use
if command -v mutt > /dev/null; then
- # system-wite
- mutt="mutt"
- # TODO: check if this is also the location on Fedora
- pgpewrap="/usr/lib/mutt/pgpewrap"
- dotlock="mutt_dotlock"
+ # system-wite
+ mutt="mutt"
+ # TODO: check if this is also the location on Fedora
+ pgpewrap="/usr/lib/mutt/pgpewrap"
+ dotlock="mutt_dotlock"
elif command -v mutt-jaro > /dev/null; then
- # in-house compiled
- mutt=mutt-jaro
- pgpewrap=pgpewrap
- dotlock=dotlock
+ # in-house compiled
+ mutt=mutt-jaro
+ pgpewrap=pgpewrap
+ dotlock=dotlock
else
- error "Cannot find Mutt. Please install it."
- exit 1
+ error "Cannot find Mutt. Please install it."
+ exit 1
fi
func "Mutt binary: $mutt"
# make sure there is always a muttpass file even if empty
touch $MAILDIR/tmp/muttpass
+
+
+ pidof gnome-keyring-daemon > /dev/null && {
+ act "using gnome-keyring to store secrets"
+ GNOMEKEY=1 }
+
return 0
}
@@ -513,17 +518,16 @@ EOF
typeset -A subcommands_opts
-main()
- {
+main() {
### Options configuration
#Hi, dear developer! Are you trying to add a new subcommand, or to add some options?
#Well, keep in mind that:
# 1. An option CAN'T have differente meanings/behaviour in different subcommands.
# For example, "-s" means "size" and accept an argument. If you are tempted to add
# an option "-s" (that means, for example "silent", and doesn't accept an argument)
- # DON'T DO IT!
- # There are two reasons for that:
- # I. usability; user expect that "-s" is "size
+# DON'T DO IT!
+ # There are two reasons for that:
+ # I. usability; user expect that "-s" is "size
# II. Option parsing WILL EXPLODE if you do this kind of bad things
# (it will say "option defined more than once, and he's right)
main_opts=(a: -account=a l: -list=l q -quiet=q D -debug=D h -help=h v -version=v n -dry-run=n f -force=f)
@@ -592,9 +596,9 @@ main()
### Detect subcommand
local -aU every_opts #every_opts behave like a set; that is, an array with unique elements
for optspec in $subcommands_opts$main_opts; do
- for opt in ${=optspec}; do
- every_opts+=${opt}
- done
+ for opt in ${=optspec}; do
+ every_opts+=${opt}
+ done
done
local -a oldstar
oldstar=($argv)
@@ -602,9 +606,9 @@ main()
unset discardme
subcommand=$1
if [[ -z $subcommand ]]; then
- subcommand="__default"
+ subcommand="__default"
fi
-
+
if [[ -z ${(k)subcommands_opts[$subcommand]} ]]; then
# unknown command, pass it to autostart
func "unknown command, autostart: $@"
@@ -619,7 +623,7 @@ main()
argv=(${oldstar})
unset oldstar
-
+
### Parsing global + command-specific options
# zsh magic: ${=string} will split to multiple arguments when spaces occur
set -A cmd_opts ${main_opts} ${=subcommands_opts[$subcommand]}
@@ -685,8 +689,15 @@ main()
PARAM=(${PARAM// -? /})
case "$subcommand" in
- compose) compose ${PARAM} ;;
- queue) queue ${PARAM} ;;
+
+ compose) compose ${PARAM}
+ exitcode=$?
+ ;;
+
+ queue) queue ${PARAM}
+ exitcode=$?
+ ;;
+
fetch)
if [[ "$account" = "" ]]; then
fetchall
@@ -695,10 +706,19 @@ main()
fi
filter_maildir incoming
;;
- send) send ${PARAM} ;; # was checking is_online
- peek) peek ${PARAM} ;; # was checking is_online
- later|remember) cat | deliver remember ;;
+ send) send ${PARAM}
+ exitcode=$?
+ ;;
+
+ peek) peek ${PARAM}
+ exitcode=$?
+ ;;
+
+ later|remember)
+ cat | deliver remember
+ exitcode=$?
+ ;;
update|init)
init_inbox
@@ -709,21 +729,37 @@ main()
help) usage ;;
- index) nm_index ;;
+ index) nm_index
+ exitcode=$?
+ ;;
+
search) search ${PARAM} ;;
+
notmuch)
notice "Command: notmuch ${PARAM}"
nm ${PARAM}
+ exitcode=$?
;;
stat) stats ${PARAM} ;;
- complete) complete ${PARAM} ;;
- isknown) sender_isknown ${PARAM} ;;
- learn) learn ${PARAM} ;;
- forget) forget ${PARAM} ;;
- import) import ${PARAM} ;;
+ complete) complete ${PARAM}
+ exitcode=$?
+ ;;
+
+ isknown) sender_isknown ${PARAM}
+ exitcode=$?
+ ;;
+
+ learn) learn ${PARAM}
+ exitcode=$?
+ ;;
+
+ import) import ${PARAM}
+ exitcode=$?
+ ;;
+
"export")
case "$PARAM" in
abook)
@@ -736,22 +772,35 @@ main()
esac
;;
- abook) edit_abook ${PARAM} ;;
+ abook) edit_abook ${PARAM}
+ exitcode=$?
+ ;;
edit|vim) edit_file ${PARAM} ;;
open) open_folder ${PARAM} ;;
preview) preview_file ${PARAM} ;;
- backup) backup ${PARAM} ;;
+ backup) backup ${PARAM}
+ exitcode=$?
+ ;;
+
rmdupes) rmdupes ${PARAM} ;;
merge) merge ${PARAM} ;;
filter)
update_filters ${PARAM}
+ [[ $? = 0 ]] || {
+ error "error updating filters, operation aborted."
+ break
+ }
filter_maildir ${PARAM}
+ exitcode=$?
;;
- deliver) deliver ${PARAM} ;;
+ deliver)
+ deliver ${PARAM}
+ exitcode=$?
+ ;;
passwd) new_password ;;
@@ -781,21 +830,19 @@ main()
read_account $account
ask_password
bytes_total=`imap_get_size "$2"`
+ exitcode=$?
notice "Size of account $login on $imap"
act "$bytes_total bytes"
mib_total=$(( $bytes_total / 1048576 ))
act "$mib_total MB (MiB)"
- exitcode=$?
;;
listfolders)
read_account $account
ask_password
folders=(`imap_list_folders`)
- notice "List of folders for $login on $imap"
- for f in $folders; do
- print "$f"
- done
exitcode=$?
+ notice "List of folders for $login on $imap"
+ for f in $folders; do print "$f"; done
;;
# interactive)
# read_account
@@ -821,7 +868,7 @@ main()
smtp)
smtp_send ${PARAM}
- exitcode=$res
+ exitcode=$?
;;
*) # unknown command, pass it to autostart
@@ -834,10 +881,12 @@ main()
}
;;
esac
+
+ return $exitcode
}
check_bin
main $@
-_endgame EXIT
+endgame NOERRORS
return $exitcode
diff --git a/src/zlibs/addressbook b/src/zlibs/addressbook
@@ -198,16 +198,6 @@ learn() {
}
-forget() {
- error "forget() TODO in abook branch"
- return 0
-
- # func "forget sender from mail in stdin"
- # act "Expecting mail from stdin pipe"
- # head="`${WORKDIR}/bin/fetchaddr -x From -a`"
- # # forget the email part of the parsed head
- # remove_address "${head[(ws:,:)1]}"
-}
# extract all addresses found in a list of email files from stdin
extract_mails() {
diff --git a/src/zlibs/email b/src/zlibs/email
@@ -138,8 +138,8 @@ fetch() {
}
# updates the notmuch configuration
- # setup the unread default tag
nm_setup unread
+ # setup :unread: as default tag
notice "Fetching email for account ${account}"
diff --git a/src/zlibs/filters b/src/zlibs/filters
@@ -190,7 +190,8 @@ filter_maildir() {
ownfilters=1
}
- [[ "$1" = "" ]] && { mdinput=incoming }
+ # default maildir to filter is incoming
+ mdinput=${1:-incoming}
maildircheck "$MAILDIRS/$mdinput"
[[ $? = 0 ]] || {
@@ -220,6 +221,19 @@ filter_maildir() {
match=0
c=$(($c + 1))
+ # check if its an empty file
+ _fsize=`stat -c '%s' "$m"`
+ [[ $_fsize = 0 ]] && {
+ act "$c\t/ $numm\t(empty)"
+ rm "$m"
+ continue
+ }
+
+ # parse if its a mailinglist
+ _md=0
+ hdr "$m" | ismailinglist
+ [[ $? = 0 ]] && _md=1
+
list="blacklist"
hdr "$m" | sender_isknown
[[ $? = 0 ]] && {
@@ -248,28 +262,42 @@ filter_maildir() {
[[ "$ownfilters" = "1" ]] && {
func "processing through own filters"
- ffrom=`hdr "$m" | ${WORKDIR}/bin/fetchaddr -x From -a`
# run all filter regexps on the from: field
- [[ "$ffrom" = "" ]] || {
- femail="${ffrom[(ws:,:)1]:l}"
+ _dest=""
+ e_addr=()
+ hdr "$m" | e_parse From
+ [[ $? = 0 ]] && {
+ femail="${(k)e_addr}" # e_parse From hit is always one
for exp in ${(k)filter_from}; do
-
+
+ # fuzzy match on a string (PCRE)
if [[ "$femail" =~ "$exp" ]]; then
+
+ # retrieve the filter destination maildir
+ _dest="${filter_from[$exp]}"
+
# if destination maildir is same as input, skip
- [[ "${filter_from[$exp]}" = "$mdinput" ]] && {
+ [[ "$_dest" = "$mdinput" ]] && {
act "$c\t/ $numm"
match=1
break
}
- cat "$m" | deliver ${filter_from[$exp]}
+
+ # tag mailinglists
+ if [[ $_md = 1 ]]; then
+ cat "$m" | deliver "$_dest" "+filtered +mailinglist"
+ else
+ cat "$m" | deliver "$_dest" "+filtered"
+ fi
+
if [[ $? = 0 ]]; then
- act "$c\t/ $numm\t-> ${filter_from[$exp]}"
+ act "$c\t/ $numm\t-> $_dest\t(from $femail)"
match=1
rm "$m"
break
else
- error "Error filtering to maildir ${filter_from[$exp]}"
+ error "Error filtering to maildir $_dest"
error "File: $m"
continue
fi
@@ -281,31 +309,43 @@ filter_maildir() {
}
}
- typeset -alU ftos
+ _dest=""
# recompile the array of destination addresses
- ftos=(`hdr "$m" | ${WORKDIR}/bin/fetchaddr -x cc -e`)
- ftos+=(`hdr "$m" | ${WORKDIR}/bin/fetchaddr -x to -e`)
-
+ e_addr=()
+ hdr "$m" | e_parse To
+ hdr "$m" | e_parse Cc
# run all filter regexps on the to: and cc: fields
- { test "$ftos" = "" } || {
- for ft in ${(f)ftos}; do
+ [[ $? = 0 ]] && {
+ for ft in ${(k)e_addr}; do
for exp in ${(k)filter_to}; do
- # special zsh parsing in PCRE (=~)
+
+ # fuzzy match on a string (PCRE)
if [[ "$ft" =~ "$exp" ]]; then
+
+ # retrieve the filter destination maildir
+ _dest="${filter_to[$exp]}"
+
# if destination maildir is same as input, skip
- [[ "${filter_to[$exp]}" = "$mdinput" ]] && {
+ [[ "$_dest" = "$mdinput" ]] && {
act "$c\t/ $numm"
match=1
break
}
- cat "$m" | deliver ${filter_to[$exp]}
+
+ # tag mailinglists
+ if [[ $_md = 1 ]]; then
+ cat "$m" | deliver "$_dest" "+filtered +mailinglist"
+ else
+ cat "$m" | deliver "$_dest" "+filtered"
+ fi
+
if [[ $? = 0 ]]; then
- act "$c\t/ $numm\t-> ${filter_to[$exp]}"
+ act "$c\t/ $numm\t-> $_dest\t(to $ft)"
match=1
rm "$m"
break
else
- error "Error filtering to maildir ${filter_to[$exp]}"
+ error "Error filtering to maildir $_dest"
error "File: $m"
continue
fi
@@ -329,7 +369,7 @@ filter_maildir() {
act "$c\t/ $numm"
continue
}
- cat "$m" | deliver known
+ cat "$m" | deliver known "+inbox +priv"
[[ $? = 0 ]] && { rm "$m" }
act "$c\t/ $numm\t-> known"
continue
@@ -357,7 +397,7 @@ filter_maildir() {
match=1
break
}
- cat "$m" | deliver priv
+ cat "$m" | deliver priv "+priv"
[[ $? = 0 ]] && {
rm "$m";
act "$c\t/ $numm\t-> priv"
@@ -368,14 +408,13 @@ filter_maildir() {
done
[[ $match = 1 ]] && continue
- # parse if its an unknown mailinglist
- hdr "$m" | ismailinglist
- [[ $? = 0 ]] && {
+ # its an unkown mailinglist
+ [[ $_ml = 1 ]] && {
[[ "$mdinput" = "unsorted.ml" ]] && {
act "$c\t/ $numm"
continue
}
- cat "$m" | deliver unsorted.ml
+ cat "$m" | deliver unsorted.ml "+unsorted +mailinglist"
[[ $? = 0 ]] && { rm "$m" }
continue
}
@@ -385,7 +424,7 @@ filter_maildir() {
act "$c\t/ $numm"
else
act "$c\t/ $numm\t-> unsorted"
- cat "$m" | deliver unsorted
+ cat "$m" | deliver unsorted "+unsorted"
[[ $? = 0 ]] && { rm "$m" }
fi
diff --git a/src/zlibs/maildirs b/src/zlibs/maildirs
@@ -196,11 +196,9 @@ merge() {
# important to return 1 on all errors
# so that fetchmail does not deletes mail from server
deliver() {
- if [ "$1" = "" ]; then
- dest="incoming"
- else
- dest="$1"
- fi
+
+ # default destination is incoming
+ dest=${1:-incoming}
# create destination maildir if not existing
[[ -r "$MAILDIRS/$dest" ]] || {
@@ -217,52 +215,33 @@ deliver() {
func "deliver to $dest"
- # destinations excluded from notmuch indexing
- [[ "$dest" = "outbox" ]] \
- || [[ "$dest" =~ "^zz." ]] \
- || [[ "$dest" = "incoming" ]] && {
-
- base="`hostname`_jaro_`date +%Y-%m-%d_%H-%M-%S`_$RANDOM"
-
+ [[ "$2" = "" ]] && {
+ # no tag specified, plain delivery without indexing
+ ## destinations excluded from notmuch indexing
+ # for indexing rules see filter_maildir()
+ # [[ "$dest" = "outbox" ]] \
+ # || [[ "$dest" =~ "^zz." ]] \
+ # || [[ "$dest" = "incoming" ]] && {
+ base="`hostname`_jaro_`date +%Y-%m-%d_%H-%M-%S`_$RANDOM"
cat > "$MAILDIRS/$dest/new/$base"
[[ $? = 0 ]] || {
- error "Could not write email file into maildir $dest."
+ error "Could not deliver email file into maildir $dest"
func "Returning error to caller."
return 1
}
return 0
}
-
+
#########
# notmuch indexing from here
+ tags="$2"
+ func "indexing tags: $tags"
- # tag +inbox
- [[ "$dest" = "known" ]] \
- || [[ "$dest" = "sent" ]] && {
- cat | nm insert --folder="$dest" +inbox +priv
- return $?
- }
-
- [[ "$dest" = "priv" ]] && {
- cat | nm insert --folder="$dest" +priv
- return $?
- }
+ cat | nm insert --folder="$dest" ${=tags}
+ res=$?
+ [[ $res = 0 ]] || \
+ error "Could not deliver email file into maildir $dest with tags $tags"
+
+ return $res
- # tag +unsorted
- [[ "$dest" = "unsorted" ]] \
- || [[ "$dest" =~ "^lists." ]] && {
- cat | nm insert --folder="$dest" +unsorted
- return $?
- }
-
- _email=`cat`
- print - "$_email" | ismailinglist
- [[ $? = 0 ]] && {
- print - "$_email" | nm insert --folder="$dest" +filters +mailinglist
- return $?
- }
-
- # anything else +filters
- print - "$_email" | nm insert --folder="$dest" +filters
- return $?
}