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:
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