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 7e9e5143b6d13d01ddb7b34d97526fc2f1ff4573
parent 1419876b085267fea58021d8007c9f452d4e7d28
Author: Jaromil <jaromil@dyne.org>
Date:   Thu, 28 Jun 2012 18:43:15 +0200

new native imap folder examination using openssl

Diffstat:
Msrc/jaro | 9+++++++--
Msrc/zlibs/accounts | 7+++----
Msrc/zlibs/email | 46+++++++++++++++++++++++++++++++++++-----------
Msrc/zlibs/helpers | 16++++++++++++++++
Asrc/zlibs/imap | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 149 insertions(+), 17 deletions(-)

diff --git a/src/jaro b/src/jaro @@ -67,6 +67,12 @@ typeset -al maildirs typeset exitcode exitcode=0 +# global variable for infos on imap folder +# format: name;num_of_messages;size_in_bytes +# last entry is grand_total_in_bytes ${imap_info[${#imap_info}]} +typeset -alU imap_info + + autoload colors; colors # standard output message routines @@ -145,8 +151,7 @@ case $OS in touch /dev/shm/jaromail.test.tmp > /dev/null { test $? = 0 } && { # we can use volatile ram - rm -f /dev/shm/jaromail.test.tmp - TMPDIR=/dev/shm/jaromail.$USER + TMPDIR=/dev/shm/tmp.jaromail.$USER TMPRAM=1 } ;; diff --git a/src/zlibs/accounts b/src/zlibs/accounts @@ -53,7 +53,8 @@ list_accounts() { # -a defines which account name other than 'default' read_account() { typeset -al all - + unset name email host login transport \ + port auth cert options folders # parse arguments { test "$1" != "" } && { account=$1 } @@ -67,8 +68,7 @@ read_account() { error "No account type specified" act "Available accounts (excluding symbolic links, omit final .txt):" list_accounts - return 1 - } + return 1 } { test "$account" = "" } && { account=default } # find the file @@ -107,7 +107,6 @@ read_account() { /^login/ { printf "login=\"%s\";", $2 } /^transport/ { printf "transport=\"%s\";", $2 } /^port/ { printf "port=\"%s\";", $2 } - /^password/ { printf "password=\"%s\";", $2 } /^auth/ { printf "auth=\"%s\";", $2 } /^cert/ { printf "cert=\"%s\";", $2 } /^options/ { printf "accountopt=\""; for(i=2;i<=NF;i++) printf "%s ", $i; printf "\";" } diff --git a/src/zlibs/email b/src/zlibs/email @@ -98,8 +98,32 @@ fetch() { { test $DRYRUN != 1 } && { update } fi - notice "Fetching mails for $name" + notice "Examining mailbox for $name <$email> on $host" + + # check if its online + timeout 2 netcat -z ${host} ${port} > /dev/null + { test $? = 0 } || { + error "server is off-line or unreachable, skipped" + return 1 } + + ask_password $login $host + + + # skip getting size if Gmail + # (imap there lacks support for RFC822.SIZE) +# { test "$host" != "imap.gmail.com" } && { + get_imap_info + { test ${imap_info[${#imap_info}]} = 0 } && { + # imap account is empty + return 0 } + notice "Total occupation is `human_size ${imap_info[${#imap_info}]}`" +# } + # this puts total size in $imap_info + { test $DRYRUN != 1 } && { + + { test ${imap_info[${#imap_info}]} -eq 0 } && { return 0 } + ask_password $login $host { test $? != 0 } && { error "Error retrieving password for $login on $host" @@ -112,13 +136,13 @@ fetch() { 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 ssl warnings 3600 and wants mda "procmail -m $PROCMAILDIR/rc" EOF @@ -130,7 +154,7 @@ EOF cat <<EOF >> $tmp antispam 571 550 501 554 EOF - + # try login without doing anything fetchmail -c -f $tmp # examine result @@ -152,7 +176,7 @@ EOF ;; *) ;; esac - + # archive old procmail log if [ -r $WORKDIR/log/procmail.log ]; then newlock $WORKDIR/log/procmail-${datestamp}.log @@ -162,13 +186,13 @@ EOF 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" @@ -213,7 +237,7 @@ send() { error "Error retrieving password for $login on $host" unset password all; return 1 } - + tmp=$TMPDIR/$host.send.$RANDOM newlock $tmp cat <<EOF > $tmp @@ -230,7 +254,7 @@ 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} diff --git a/src/zlibs/helpers b/src/zlibs/helpers @@ -146,6 +146,22 @@ ramdisk() { esac } +human_size() { + { test $1 -gt 0 } || { + error "human_size() called with zero argument" + return 1 } + # megabytes + { test $1 -gt 1048576 } && { + print -n "$(( $1 / 1024 / 1024 )) MB" + return 0} + # kilobytes + { test $1 -gt 1024 } && { + print -n "$(( $1 / 1024 )) KB" + return 0} + # bytes + print -n "$1 Bytes" + return 0 +} ###### # CERT diff --git a/src/zlibs/imap b/src/zlibs/imap @@ -0,0 +1,87 @@ +#!/usr/bin/env zsh +# +# Jaro Mail, your humble and faithful electronic postman +# +# a tool to easily and privately handle your e-mail communication +# +# Copyleft (C) 2010-2012 Denis Roio <jaromil@dyne.org> +# +# This source code is free software; you can redistribute it and/or +# modify it under the terms of the GNU Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This source code is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# Please refer to the GNU Public License for more details. +# +# You should have received a copy of the GNU Public License along with +# this source code; if not, write to: +# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +get_imap_info() { + { test $name } || { + error "get_imap_info() called with no account loaded" + return 1 } + { test "$type" != "imap" } && { + error "get_imap_info() called on a non-imap account: $type.$host" + return 1 } + { test "$host" = "imap.gmail.com" } && { + act "skipping IMAP examination on GMail account" + return 1 } + func "Querying size on $type.$host" + + c=1 + tot=0 + grandtot=0 + imap_info=() + typeset -alU ff + id=$RANDOM + query=$TMPDIR/imap.size.query.$id + newlock $query + if [ "$folders" = "" ]; then + ff+=(INBOX) + else # imap folders are explicit in conf + for f in ${(s: :)folders}; do + # no composite works, one word each folder + ff+=($f); done + fi + + for f in ${ff}; do + rm -f $query; touch $query + cat <<EOF >> $query +B00000 CAPABILITY +B00001 LOGIN "${login}" "${password}" +EOF + + c=$(( $c + 1 )) + echo "B0000$c SELECT \"${f}\"" >> $query + c=$(( $c + 1 )) + echo "B0000$c FETCH 1:* (FLAGS RFC822.SIZE)" >> $query + echo >> $query + + typeset -al res + for i in `timeout 5 openssl s_client -starttls imap -quiet \ + -connect ${host}:${port} < $query 2>&1 \ + | grep RFC822.SIZE | awk '{ print $NF }' \ + | tr -d '\r' | sed 's/)//'`; do + res+=($i); done + + { test $? != 0 } && { + error "Error connecting to $host:$port" + continue } + { test "$res" = "" } && { + act "Empty folder $f" + continue } + + for rr in ${res}; do + tot=$(( ($rr) + $tot )) + done + act "Folder $f has ${#res} messages (`human_size $tot`)" + imap_info+=("$f;${#res};$tot") + grandtot=$(( $grandtot + $tot )) + done + unlink $query + imap_info+=($grandtot) +}+ \ No newline at end of file