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 708316493dee8c6675c118fa90c6e5b05be70e7c
parent 1e1b58293f76bfff469dd610be262304a62b2f4c
Author: Jaromil <jaromil@dyne.org>
Date:   Sat, 29 Nov 2014 00:14:11 +0100

new imap listfolder to fetch all remote folders, various fixes and documentation, folder excludes

Diffstat:
Mdoc/Accounts/default.txt | 13++++++++++---
Mdoc/Filters.txt | 33++++++++++++++++++++-------------
Msrc/jaro | 3++-
Msrc/zlibs/accounts | 6++++--
Msrc/zlibs/addressbook | 130++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/zlibs/email | 77+++++++++++++++++++++++++++++++++++++++++++++--------------------------------
6 files changed, 146 insertions(+), 116 deletions(-)

diff --git a/doc/Accounts/default.txt b/doc/Accounts/default.txt @@ -42,9 +42,16 @@ transport ssl # by default this is 'keep': don't delete mails from server options keep -# Imap folders -# uncomment to provide a list of folders to be fetched -# folders INBOX, known, priv, lists, ml.unsorted, unsorted +# Remote IMAP folders to be retreived +# fill to provide a list of folders to be fetched +# default is to detect and fetch all remote folders +## folders INBOX priv unsorted filters + +# list of folders to exclude from fetch +# comment or change to avoid leaving them on server +# please note we filters social networks by default +# (see Filters.txt and change it as you like) +exclude zz.spam zz.bounces zz.blacklist zz.social # diff --git a/doc/Filters.txt b/doc/Filters.txt @@ -1,4 +1,4 @@ -# Example filter configuration for Jaro Mail +# Default filter configuration for Jaro Mail # Mailinglist filters are in order of importance # syntax: to <list email> save <folder> @@ -6,24 +6,31 @@ # which makes it handy when browsing with file completion. # to crypto@lists.dyne save dyne.crypto -# to dynebolic save dyne.dynebolic -# to freej save dyne.freej +# to dynebolic save dyne.dynebolic +# to freej save dyne.freej # to frei0r-devel save dyne.frei0r -# to taccuino save ml.freaknet -# to deadpoets save ml.freaknet +# to taccuino save ml.freaknet +# to deadpoets save ml.freaknet # to linux-libre save gnu.linux-libre # to foundations@lists save gnu.foundations # to debian-mentors save debian.mentors # to debian-blends save debian.blends -# to freedombox-discuss save debian.freedombox # Other filters for web 2.0 using folder names with a prefix: # they can facilitate folder maintainance. +# These are on by default, comment out if not desired. -# from Twitter save web.twitter -# from linkedin save web.linkedin -# from googlealerts save web.google -# from plus.google.com save web.google -# from facebook save web.facebook -# from FriendFeed save web.friendfeed -# from academia.edu save web.academia +from github.com save zz.social +from launchpad save zz.social +from identi.ca save zz.social +from twitter.com save zz.social +from linkedin.com save zz.social +from googlealerts save zz.social +from plus.google.com save zz.social +from youtube.com save zz.social +from wmt-noreply@google save zz.social +from facebook save zz.social +from FriendFeed save zz.social +from academia-mail.com save zz.social +from statusnet save zz.social +from basecamp save zz.social diff --git a/src/jaro b/src/jaro @@ -60,7 +60,8 @@ typeset -h list list=whitelist # global variables for accounts -typeset -h name login imap imap_port smtp smtp_port protocol password auth folders accountopt +typeset -h name login imap imap_port smtp smtp_port protocol password auth accountopt +typeset -ah folders exclude typeset -h host port type # global variables for addressbook diff --git a/src/zlibs/accounts b/src/zlibs/accounts @@ -28,7 +28,7 @@ read_account() { typeset -al all unset name email imap imap_port smtp smtp_port \ - host login transport auth cert options folders + host login transport auth cert options folders exclude # parse arguments { test "$account" = "" } && { account="default" } @@ -62,7 +62,8 @@ read_account() { /^auth/ { printf "auth=\"%s\";", $2 } /^cert/ { printf "cert=\"%s\";", $2 } /^options/ { printf "accountopt=\""; for(i=2;i<=NF;i++) printf "%s ", $i; printf "\";" } - /^folders/ { printf "folders=\""; for(i=2;i<=NF;i++) printf "%s ", $i; printf "\";" } + /^folders/ { printf "folders=("; for(i=2;i<=NF;i++) printf "%s ", $i; printf ");" } + /^exclude/ { printf "exclude=("; for(i=2;i<=NF;i++) printf "%s ", $i; printf ");" } ' "$acct"` { test $? = 0 } || { error "Error parsing account: $acct" @@ -108,6 +109,7 @@ read_account() { func "auth: $auth" func "options: $accountopt" func "folders: $folders" + func "exclude: $exclude" return 0 } diff --git a/src/zlibs/addressbook b/src/zlibs/addressbook @@ -176,75 +176,75 @@ learn() { what=sender [[ "${PARAM[1]}" != "" ]] && { what=${PARAM[1]} } - + func "learning from $what" buffer=`cat` - case ${PARAM[1]} in - - sender) # simple: one address only on From: - head="`print $buffer | ${WORKDIR}/bin/fetchaddr -x From -a`" - # (Q) eliminates quotes, then word split - email="${(Q)head[(ws:,:)1]}" - name="${(Q)head[(ws:,:)2]}" - print "$name" "<$email>" - [[ $DRYRUN == 1 ]] || { - insert_address "$email" "$name" - { test $? = 0 } && { act "new: $_name <${_email}>" } - } - return 0 - ;; - - all) - head="`print $buffer | ${WORKDIR}/bin/fetchaddr -a`" - for h in ${(f)head}; do - # (Q) eliminates quotes, then word split - email="${(Q)h[(ws:,:)1]}" - name="${(Q)h[(ws:,:)2]}" - - print "$name" "<$email>" - - [[ $DRYRUN == 1 ]] || { - insert_address "$email" "$name" - { test $? = 0 } && { act "new: $_name <${_email}>" } - } - done - return 0 - ;; - - recipient) # complex: more addresses in To: and Cc: - head="`print $buffer | ${WORKDIR}/bin/fetchaddr -x To -a`" - for h in ${(f)head}; do - # (Q) eliminates quotes, then word split - email="${(Q)h[(ws:,:)1]}" - name="${(Q)h[(ws:,:)2]}" - print "$name" "<$email>" - - [[ $DRYRUN == 1 ]] || { - insert_address "$email" "$name" - { test $? = 0 } && { act "new: $_name <${_email}>" } - } - done - - head="`print $buffer | ${WORKDIR}/bin/fetchaddr -x Cc -a`" - for h in ${(f)head}; do - # (Q) eliminates quotes, then word split - email="${(Q)h[(ws:,:)1]}" - name="${(Q)h[(ws:,:)2]}" - print "$name" "<$email>" - - [[ $DRYRUN == 1 ]] || { - insert_address "$email" "$name" - { test $? = 0 } && { act "new: $_name <${_email}>" } - } - done - return 0 - ;; - - *) - error "Unknown learning function: $what" ;; + case ${what} in + + sender) # simple: one address only on From: + head="`print $buffer | ${WORKDIR}/bin/fetchaddr -x From -a`" + # (Q) eliminates quotes, then word split + email="${(Q)head[(ws:,:)1]}" + name="${(Q)head[(ws:,:)2]}" + print "$name" "<$email>" + [[ $DRYRUN == 1 ]] || { + insert_address "$email" "$name" + { test $? = 0 } && { act "new: $_name <${_email}>" } + } + return 0 + ;; + + all) + head="`print $buffer | ${WORKDIR}/bin/fetchaddr -a`" + for h in ${(f)head}; do + # (Q) eliminates quotes, then word split + email="${(Q)h[(ws:,:)1]}" + name="${(Q)h[(ws:,:)2]}" + + print "$name" "<$email>" + + [[ $DRYRUN == 1 ]] || { + insert_address "$email" "$name" + { test $? = 0 } && { act "new: $_name <${_email}>" } + } + done + return 0 + ;; + + recipient) # complex: more addresses in To: and Cc: + head="`print $buffer | ${WORKDIR}/bin/fetchaddr -x To -a`" + for h in ${(f)head}; do + # (Q) eliminates quotes, then word split + email="${(Q)h[(ws:,:)1]}" + name="${(Q)h[(ws:,:)2]}" + print "$name" "<$email>" + + [[ $DRYRUN == 1 ]] || { + insert_address "$email" "$name" + { test $? = 0 } && { act "new: $_name <${_email}>" } + } + done + + head="`print $buffer | ${WORKDIR}/bin/fetchaddr -x Cc -a`" + for h in ${(f)head}; do + # (Q) eliminates quotes, then word split + email="${(Q)h[(ws:,:)1]}" + name="${(Q)h[(ws:,:)2]}" + print "$name" "<$email>" + + [[ $DRYRUN == 1 ]] || { + insert_address "$email" "$name" + { test $? = 0 } && { act "new: $_name <${_email}>" } + } + done + return 0 + ;; + + *) + error "Unknown learning function: $what" ;; esac return 1 - + } forget() { diff --git a/src/zlibs/email b/src/zlibs/email @@ -202,71 +202,84 @@ fetch() { # notice "Total occupation is `human_size ${imap_info[${#imap_info}]}`" - { test $DRYRUN != 1 } && { - fmconf=("poll $imap with proto IMAP user \"$login\" there with password \"$password\"") - + if ! [ -z $accountopt ]; then # add option configuration fmconf+=(" ${accountopt} "); fi - + # if no folders specified, use all [[ "$folders" == "" ]] && { folders=(`imap_list_folders`) } act "${#folders} folders found" - + + # unset here because listing folders still needs a pass unset password - [[ ${#folders} == "0" ]] && { return 1 } + # nothing to download, bail out with error + [[ ${#folders} == "0" ]] && return 1 + # remove excludes + [[ ${#exclude} == "0" ]] || { + func "exclude folders: $exclude" + for e in ${exclude}; do + folders=(${folders:#$e}) + done + } + func "fetch folders: $folders" + # add folder configuration fmconf+=(" folder ${=folders} "); - + fmconf+=(" ${transport} warnings 3600 and wants mda \"jaro -q deliver\" ") - + if [ "$cert" = "check" ]; then # we now use system-wide certs fmconf+=(" sslcertck ") # sslcertpath '$WORKDIR/certs' fi - - + + fmconf+=(" antispam 571 550 501 554 ") - + print $accountopt | grep 'keep' > /dev/null { test $? = 0 } || { - error "planning to delete mails from server, account option: $accountopt" } - + error "planning to delete mails from server, account option: $accountopt" } + # try login without doing anything print "$fmconf" | fetchmail -c -f - res=$? # examine result case $ret in 1) - notice "No mails for $name" - unset $fmconf - return 1 - ;; + notice "No mails for $name" + unset $fmconf + return 1 + ;; 2) - error "Invalid or unknown certificate for $imap" - unset $fmconf - return 1 - ;; + error "Invalid or unknown certificate for $imap" + unset $fmconf + return 1 + ;; 3) - error "Invalid password for user $login at $imap" - unset $fmconf - return 1 - ;; + error "Invalid password for user $login at $imap" + unset $fmconf + return 1 + ;; *) - func "fetchmail returns $ret" ;; + func "fetchmail returns $ret" ;; esac - act "please wait while downloading mails to incoming..." - - print " $fmconf " | fetchmail -f - + if [[ $DRYRUN = 0 ]]; then + + act "please wait while downloading mails to incoming..." + + print " $fmconf " | fetchmail -f - + + else + act "dryrun: nothing will be fetched really." + fi unset $fmconf - - } # DRYRUN - + return 0 }