#!/bin/bash # Copyright (c) 2010 Switzernet by Emin Gabrielyan and Oussama Hammami # CleanIMAPunsync v100604.2 # This script is a complementary to imapsync # It deletes the folders that exist in the destination server # but do not exist in the source. The imapsync does not delete # folders in the destination server that are not in the source # If you periodically sync with cron, and frequently rename folders # on the source server, imapsync would copy each renamed instance # to the destination and you may endup with multiple copies of the # same folder on the destination server. This script solves this problem. # You must run this script periodically, before or after the imapsync. # # ver=100604.a26.sh prog=cleanimapunsync workroot=/var/tmp log=/var/log/$prog.log function usage { echo echo "Celans the IMAP folders on the destination backup server," echo "not existing anymore in the source IMAP server." echo echo Usage: echo echo " host1=mail2.switzernet.com user1=support@mail2.switzernet.com pass1=xxxx dir1=\"INBOX/Support/4 Reception/\" \\" echo " host2=backup.switzernet.com user2=admin@backup.switzernet.com pass2=yyyy dir2=\"support.INBOX.Support.4 Reception.\" $prog" echo exit } if [ -z "$host1" -o -z "$host2" ] then echo "Error: one or both hosts are unknown" usage fi if [ -z "$user1" -o -z "$user2" ] then echo "Error: one or both usernames are unknown" usage fi if [ -z "$pass1" -o -z "$pass2" ] then echo "Error: one or both passwords are unknown" usage fi if [ -z "$dir1" -o -z "$dir2" ] then echo "Error: one or both root directories are unknown" usage fi #echo "host1=$host1" #echo "user1=$user1" #echo "pass1=$pass1" #echo "dir1=$dir1" #echo "host2=$host2" #echo "user2=$user2" #echo "pass2=$pass2" #echo "dir2=$dir2" out1=a,out1.txt folders1=b,folders1.txt list1=c,list1.txt out2=a,out2.txt folders2=b,folders2.txt list2=c,list2.txt intersect=d,intersect.txt zombies=e,zombies.txt deleted=f,deleted.txt time=`date +%Y%m%d,%H%M%S` work=${workroot}/$time,$prog,$ver,$$,$RANDOM cd $workroot if [ $? -ne 0 ] then echo Error: cannot go into work root $workroot exit fi mkdir $work if [ $? -ne 0 ] then echo Error: cannot create work dir $work exit fi cd $work if [ $? -ne 0 ] then echo Error: cannot move into work $work exit fi function imap_list { tag=2000 (sleep 0.5; echo "1000 login $user $pass"; sleep 0.5; echo "$tag list \"$dir\" *"; sleep 0.5; echo "3000 logout"; sleep 1.5) | telnet $host imap > $out 2>&1 if [ ! -f $out ] then echo "`date +%Y-%m-%d\ %H:%M:%S` Error: connection problem, output file $out is not found" >> $log exit fi if grep -qi "^$tag OK LIST completed" $out then echo ok > /dev/null else echo "`date +%Y-%m-%d\ %H:%M:%S` Error: connection problem with $user@$host, IMAP list is not obtained or incomplete" >> $log exit fi cat $out | perl -ne 'if(/^\* +LIST +\([^)]*\) +\"[^"]+\" \"([^"]+)\"/){$s=$1; print $s."\n"}' > $folders cat $folders | perl -e '$d="'"$dir"'"; $d=~s/\//\\\//g; while(<>){s/^$d//; s/\//./g; s/[,;]/'\''/g; print}' > $list } host=$host1 user=$user1 pass=$pass1 dir=$dir1 out=$out1 folders=$folders1 list=$list1 imap_list host=$host2 user=$user2 pass=$pass2 dir=$dir2 out=$out2 folders=$folders2 list=$list2 imap_list cat $list1 $list2 | sort | uniq -c | perl -ne 'print $1."\n" if(/^ *2 +(.*)$/)' > $intersect cat $intersect $list2 | sort | uniq -c | perl -ne 'print $1."\n" if(/^ *1 +(.*)$/)' > $zombies ( sleep 0.5 echo "1000 login $user2 $pass2" i=1 cat $zombies | perl -ne 's/^//; print' | while read s #The middle pipe adding <> protects fro read's trim do sleep 0.5 #The next version of line is without regex side effects as perl eq is used for comparison line=`(echo "$s"; cat $list2) | perl -ne '$i++ if($s); s/[\n\r]//g; $s=$_ if(! $i); if("<$_>" eq $s) {print $i; last}'` rm="`head -$line $folders2 | tail -1`" imap="$((2000+i)) delete \"$rm\"" echo `date +%Y-%m-%d\ %H:%M:%S` IMAP: $imap >> $log echo $imap i=$((i+1)) done sleep 0.5 echo 3000 logout sleep 1.5 ) | telnet $host2 imap > $deleted 2>&1 n=`wc -l $zombies | cut -d\ -f1` err=0 for((i=1;i<=n;i++)) do grep -iq "^$((2000+i)) OK Delete completed" $deleted || err=$((err+1)) done if [ $err -gt 0 ] then echo "`date +%Y-%m-%d\ %H:%M:%S` Error: $err out of $n folders seems are not deleted" >> $log else echo "`date +%Y-%m-%d\ %H:%M:%S` OK: $n folders are deleted" >> $log fi rm $out1 rm $folders1 rm $list1 rm $out2 rm $folders2 rm $list2 rm $intersect rm $zombies rm $deleted cd .. rmdir $work