This commit is contained in:
Nick Bebout 2012-11-27 16:32:36 -06:00
parent 1e03db551f
commit 0df034010b
18 changed files with 1673 additions and 183 deletions

View file

@ -1,5 +1,5 @@
#!/bin/cat
# $Id: CREDITS,v 1.170 2012/08/10 11:29:41 gilles Exp gilles $
# $Id: CREDITS,v 1.171 2012/10/01 08:58:58 gilles Exp gilles $
If you want to make a donation to the author, Gilles LAMIRAL,
use any of the following ways:
@ -30,6 +30,9 @@ I thank very much all of these people.
I thank also very much all people who bought imapsync from the homepage
but I don't cite them here.
Jeff Verheyen
Contributed by giving an 32GB microSDHC card and the book
29.69 "Design by Nature: Using Universal Forms and Principles in Design"
David Abrahams
Gave a patch for --authmech PREAUTH

View file

@ -1,17 +1,54 @@
RCS file: RCS/imapsync,v
Working file: imapsync
head: 1.508
head: 1.516
branch:
locks: strict
gilles: 1.508
gilles: 1.516
access list:
symbolic names:
keyword substitution: kv
total revisions: 508; selected revisions: 508
total revisions: 516; selected revisions: 516
description:
----------------------------
revision 1.508 locked by: gilles;
revision 1.516 locked by: gilles;
date: 2012/11/02 22:15:04; author: gilles; state: Exp; lines: +43 -38
Added current date at the beginning of the run, useful when imapsync doesn't end properly or hasn't finished yet.
Better output for diff statistics.
----------------------------
revision 1.515
date: 2012/10/31 12:56:02; author: gilles; state: Exp; lines: +12 -9
Added Initial difference to compare it with Final difference.
----------------------------
revision 1.514
date: 2012/10/31 01:39:38; author: gilles; state: Exp; lines: +32 -16
Added --foldersizesatend and --nofoldersizesatend, on by default.
Added statistic host2 minus host1: number of messages and bytes.
----------------------------
revision 1.513
date: 2012/10/30 22:31:49; author: gilles; state: Exp; lines: +40 -19
Add --fixslash2 to avoid 'Invalid mailbox name' when --sep2 is not / and sep1 is / and host1 folders contain --sep2 characters.
----------------------------
revision 1.512
date: 2012/10/30 01:44:26; author: gilles; state: Exp; lines: +22 -8
Added option --showpasswords
--showpasswords : shows passwords on output instead of "MASKED".
Off by default.
----------------------------
revision 1.511
date: 2012/10/27 22:37:57; author: gilles; state: Exp; lines: +44 -20
Added --delete2duplicates; Delete messages in host2 that are duplicates.
--delete2duplicates is on when --delete2 is on unless --nodelete2duplicates.
----------------------------
revision 1.510
date: 2012/10/27 15:18:44; author: gilles; state: Exp; lines: +36 -30
Added --pidfilelocking option to abort in case another imapsync may be running.
----------------------------
revision 1.509
date: 2012/10/24 14:57:56; author: gilles; state: Exp; lines: +41 -13
Added option --noabletosearch to allow listing messages without SEARCH command. Hack for imap server softalk 7.6.4. (8.6 is fine about search)
----------------------------
revision 1.508
date: 2012/09/10 21:10:13; author: gilles; state: Exp; lines: +81 -17
Added ETA after each copy. Estimated Time of Arrival.
----------------------------

17
FAQ
View file

@ -1,5 +1,5 @@
#!/bin/cat
# $Id: FAQ,v 1.116 2012/09/11 21:00:06 gilles Exp gilles $
# $Id: FAQ,v 1.117 2012/11/03 00:44:30 gilles Exp gilles $
+------------------+
| FAQ for imapsync |
@ -1203,10 +1203,15 @@ imapsync --host1 mail.oldhost.com \
--user2 my_email@gmail.com \
--password2 password \
--folder "INBOX.Sent" \
--regextrans2 "s/Sent/Sent Mail/"
--regextrans2 "s/Sent/Sent Mail/" \
--exitwhenover 500000000
The same goes for the "All Mail" archive pseudo-folder.
--exitwhenover option is here to avoid locking when transfers
exceed maximum limit.
See http://support.google.com/a/bin/answer.py?hl=en&answer=1071518
=======================================================================
Q. Synchronizing from Gmail to XXX
@ -1218,6 +1223,7 @@ R. Gmail needs SSL
--authmech1 LOGIN \
--user1 gilles.lamiral@gmail.com \
--password1 gmailsecret \
--exitwhenover 2500000000 \
--host2 localhost
--user2 tata \
--password2 tatasecret \
@ -1229,7 +1235,12 @@ option:
--regextrans2 's/\[Gmail\]/Gmail/'
You can select folders exported to imap within the gmail preferences,
unselect all "System labels"
unselect all "System labels".
--exitwhenover option is here to avoid locking when transfers
exceed maximum limit.
See http://support.google.com/a/bin/answer.py?hl=en&answer=1071518
=======================================================================
Q. migrate email from gmail to google apps

View file

@ -1,5 +1,5 @@
# $Id: Makefile,v 1.107 2012/09/11 21:00:06 gilles Exp gilles $
# $Id: Makefile,v 1.110 2012/11/03 01:38:12 gilles Exp gilles $
.PHONY: help usage all
@ -108,14 +108,16 @@ test_quick_229: imapsync tests.sh
test_quick_3xx: imapsync tests.sh
CMD_PERL='perl -I./$(IMAPClient_3xx)' /usr/bin/time sh -x tests.sh locallocal
testv2: .test_229
CMD_PERL='perl -I./$(IMAPClient_2xx) /usr/bin/time sh tests.sh
testv2:
CMD_PERL='perl -I./$(IMAPClient_2xx)' /usr/bin/time sh tests.sh
touch .test_229
testv3:.test_3xx
CMD_PERL='perl -I./$(IMAPClient_3xx)' sh -x tests.sh
testv3:
CMD_PERL='perl -I./$(IMAPClient_3xx)' /usr/bin/time sh tests.sh
touch .test_3xx
testv: testv2 testv3
test: .test_229 .test_3xx
tests: test
@ -210,7 +212,6 @@ imapsync_elf_x86.bin: imapsync
lfo: cidone niouze_lfo upload_lfo
dist: cidone test clean all INSTALL dist_prepa dist_prepa_exe
tarball: cidone all
echo making tarball $(DIST_FILE)
@ -232,6 +233,9 @@ DIST_PATH := ./dist/$(DIST_SECRET)
lalala:
echo $(DIST_SECRET)
dist: cidone test clean all INSTALL dist_prepa dist_prepa_exe
dist_prepa: tarball dist_dir
ln -f ../prepa_dist/$(DIST_FILE) $(DIST_PATH)/
rcsdiff imapsync
@ -261,10 +265,10 @@ ks:
. imapsync@ks.lamiral.info:public_html/imapsync/
ksa:
rsync -avHz --delete \
rsync -avHz --delete -P \
. imapsync@ks.lamiral.info:public_html/imapsync/
publish: upload_ks ks ml
publish: upload_ks ksa ml
PUBLIC_FILES = ./ChangeLog ./COPYING ./CREDITS ./FAQ \
./index.shtml ./INSTALL \
@ -283,7 +287,7 @@ ml:
mailq
upload_ks: ci
upload_ks: ci dist
rsync -lptvHzP $(PUBLIC_FILES) \
root@ks.lamiral.info:/var/www/imapsync/
rsync -lptvHzP $(PUBLIC_FILES_W) \
@ -307,10 +311,10 @@ upload_lfo:
/home/gilles/public_html/www.linux-france.org/html/prj/imapsync/.htaccess
sh ~/memo/lfo-rsync
upload_index: index.shtml FAQ
upload_index: index.shtml FAQ COPYING CREDITS
validate --verbose index.shtml
rcsdiff index.shtml FAQ COPYING
rsync -avH index.shtml FAQ COPYING root@ks.lamiral.info:/var/www/imapsync/
rcsdiff index.shtml FAQ COPYING CREDITS
rsync -avH index.shtml FAQ COPYING CREDITS root@ks.lamiral.info:/var/www/imapsync/
niouze_lfo :
echo "CORRECT ME: . ./memo && lfo_announce"

8
README
View file

@ -3,7 +3,7 @@ NAME
Synchronise mailboxes between two imap servers. Good at IMAP migration.
More than 44 different IMAP server softwares supported with success.
$Revision: 1.508 $
$Revision: 1.516 $
SYNOPSIS
To synchronise imap account "foo" on "imap.truc.org" to imap account
@ -85,7 +85,7 @@ USAGE
[--expunge] [--expunge1] [--expunge2] [--uidexpunge2]
[--delete2folders] [--delete2foldersonly] [--delete2foldersbutnot]
[--subscribed] [--subscribe] [--subscribe_all]
[--nofoldersizes]
[--nofoldersizes] [--nofoldersizesatend]
[--dry]
[--debug] [--debugimap][--debugimap1][--debugimap2]
[--timeout <int>] [--fast]
@ -354,7 +354,7 @@ IMAP SERVERS
- Qualcomm Worldmail (NT)
- Rockliffe Mailsite 5.3.11, 4.5.6
- Samsung Contact IMAP server 8.5.0
- Scalix v10.1, 10.0.1.3, 11.0.0.431
- Scalix v10.1, 10.0.1.3, 11.0.0.431, 11.4.6
- SmarterMail, Smarter Mail 5.0 Enterprise, Smarter Mail 5.5 [host1].
- SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System)
- Sun Java(tm) System Messaging Server 6.2-2.05, 6.2-7.05, 6.3
@ -440,5 +440,5 @@ SIMILAR SOFTWARES
Feedback (good or bad) will often be welcome.
$Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $
$Id: imapsync,v 1.516 2012/11/02 22:15:04 gilles Exp gilles $

6
TODO
View file

@ -1,5 +1,5 @@
#!/bin/cat
# $Id: TODO,v 1.113 2012/09/11 20:58:32 gilles Exp gilles $
# $Id: TODO,v 1.114 2012/11/02 22:19:14 gilles Exp gilles $
TODO file for imapsync
----------------------
@ -62,7 +62,6 @@ http://mail.google.com/support/bin/answer.py?answer=78892
Look at larch https://github.com/rgrove/larch/
http://wonko.com/
Add and option to sync to & from files.
Add an --aclregextrans2 flag.
@ -94,7 +93,6 @@ Fix bug "not possible to use space in the imap password"
Add kerberos authentification
Add stdin/stdout filter before transfer:
"Now i asked me, how to modify your perl program to work with
that - in example, to write each mail to stdout, pipe that to the
@ -142,6 +140,8 @@ http://asg.web.cmu.edu/cyrus/download/imapd/altnamespace.html
===========================================================================
DONE. Add current date at the beginning of the run, useful when imapsync
doesn't finish with statistics.
DONE. Not donse since useless now (--useuid)
Add a --skipheaderinfolder option

View file

@ -1 +1 @@
1.508
1.516

View file

@ -1 +1 @@
1.508
1.516

View file

@ -156,3 +156,7 @@
1347196697 END 1.507 : dimanche 9 septembre 2012, 15:18:17 (UTC+0200)
1347392501 BEGIN 1.508 : mardi 11 septembre 2012, 21:41:41 (UTC+0200)
1347393591 END 1.508 : mardi 11 septembre 2012, 21:59:51 (UTC+0200)
1351688288 BEGIN 1.515 : mercredi 31 octobre 2012, 13:58:08 (UTC+0100)
1351689817 END 1.515 : mercredi 31 octobre 2012, 14:23:37 (UTC+0100)
1351894814 BEGIN 1.516 : vendredi 2 novembre 2012, 23:20:14 (UTC+0100)
1351896296 END 1.516 : vendredi 2 novembre 2012, 23:44:56 (UTC+0100)

View file

@ -1,4 +1,4 @@
m4_dnl $Id: ml_announce.in,v 1.3 2012/09/11 21:01:53 gilles Exp gilles $
m4_dnl $Id: ml_announce.in,v 1.4 2012/11/03 01:38:45 gilles Exp gilles $
m4_dnl
m4_define(`M4_imapsync_VERSION',m4_esyscmd(cat VERSION|tr -d '\n'))m4_dnl
m4_define(`M4_SECRET_PATH',m4_esyscmd(cat dist/path_last.txt|tr -d '\n'))m4_dnl
@ -10,6 +10,8 @@ To: imapsync_update@lists.lamiral.info
Hello imapsync user,
Sorry for the previous link given, it was the one of release 1.508
You're subscribed to the newsletter announcing imapsync new releases
(very few traffic) and the way to get them. Send me a note if you
don't want to receive those announces anymore.

View file

@ -1,6 +1,6 @@
#!/bin/sh
# $Id: memo,v 1.11 2012/08/16 13:37:02 gilles Exp gilles $
# $Id: memo,v 1.12 2012/11/02 07:49:37 gilles Exp gilles $
echo paypal_bilan_todo
@ -28,12 +28,12 @@ Europe a un autre assujetti : Article 262 ter => Exoneration
EOF
}
echo paypal_bilan_exportbnc
paypal_bilan_exportbnc() {
# DID output no diff between paypal_bilan_1.58 and 1.59
echo paypal_bilan_Avant_commission
paypal_bilan_Avant_commission() {
# DID output diff between paypal_bilan_1.60 and 1.61
(
#set -x
/g/public_html/imapsync/W/paypal_reply/paypal_bilan_1.58 --bnc --debug --debug_invoice --first_in 147 \
/g/public_html/imapsync/W/paypal_reply/paypal_bilan_1.60 --bnc --debug --debug_invoice --first_in 147 \
--avoid_numbers '292 293 643 644 731 732 1093 1330 1331 1332 1333 1334 1652 1653' \
/g/paypal/paypal_201?_??_complet.csv \
> /g/var/paypal_bilan/tests/paypal_invoice.out1 2>&1

View file

@ -1,6 +1,6 @@
#!/usr/bin/perl
# $Id: paypal_bilan,v 1.58 2012/08/11 00:01:46 gilles Exp gilles $
# $Id: paypal_bilan,v 1.61 2012/11/02 01:31:58 gilles Exp gilles $
use strict;
use warnings;
@ -13,7 +13,7 @@ use Test::More 'no_plan' ;
die unless (utf8_supported_charset('ISO-8859-1'));
my $rcs = '$Id: paypal_bilan,v 1.58 2012/08/11 00:01:46 gilles Exp gilles $ ' ;
my $rcs = '$Id: paypal_bilan,v 1.61 2012/11/02 01:31:58 gilles Exp gilles $ ' ;
$rcs =~ m/,v (\d+\.\d+)/ ;
my $VERSION = ($1) ? $1: "UNKNOWN" ;
@ -111,7 +111,8 @@ foreach my $file ( @files ) {
'Devise', 'Montant', "Numéro d'avis de réception", 'Solde',
'Pays', 'Nom Option 1', 'Valeur Option 1', 'Hors taxe', "Titre de l'objet", 'Nom Option 2', 'Option 2 Valeur') } ;
#print "$Nom\n" ;
( $Etat ) = @action{ ( 'Etat', ) } || @action{ ( 'État' ) } ;
( $Etat ) = @action{ ( 'Etat' ) } || @action{ ( 'État' ) } ;
( $Hors_taxe ) = @action{ ( 'Hors taxe' ) } || @action{ ( 'Avant commission' ) } ;
my $invoice = 'NONE' ;
$Montant = $action->{ Net } if not defined $Montant;
compute_line($action, $invoice, $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat,
@ -200,6 +201,7 @@ print "Nb invoice sent $nb_invoice_sent\n" ;
print "Have to send invoices @invoice_not_sent\n" if ( @invoice_not_sent ) ;
my $total_eur2 = $total_HT_EUR_exo + $total_HT_EUR_ass + $total_TVA_EUR + $total_HT_EUR_sup + $total_TVA_EUR_sup ;
$total_eur2 = sprintf('%2.2f', $total_eur2) ;
print "$total_eur != $total_eur2 = $total_HT_EUR_exo + $total_HT_EUR_ass + $total_TVA_EUR + $total_HT_EUR_sup + $total_TVA_EUR_sup\n"
if ( $total_eur != $total_eur2 ) ;
@ -523,13 +525,10 @@ sub build_invoice {
'Etat/Province/Région/Comté/Territoire/Préfecture/République', 'Code postal', 'Pays', 'line_number', 'line_csv', 'file_csv',
'Nom Option 2', 'Option 2 Valeur' ) } ;
my( $Etat_Province1 ) = @action{ ( 'Etat/Province/Région/Comté/Territoire/Préfecture/République' ) } ;
my( $Etat_Province2 ) = @action{ ( 'État/Province/Région/Comté/Territoire/Préfecture/République' ) } ;
$Etat_Province = @action{ ( 'Etat/Province/Région/Comté/Territoire/Préfecture/République' ) }
|| @action{ ( 'État/Province/Région/Comté/Territoire/Préfecture/République' ) }
|| '' ;
( $Hors_taxe ) = @action{ ( 'Hors taxe' ) } || @action{ ( 'Avant commission' ) } ;
#print "$Hors_taxe $Devise\n" ;
my $Hors_taxe_num = $Hors_taxe ;
$Hors_taxe_num =~ s{,}{.} ;

1173
W/paypal_reply/paypal_bilan_1.60 Executable file

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,12 @@
#!/bin/sh
# $Id: paypal_build_invoices,v 1.36 2012/08/10 22:37:18 gilles Exp gilles $
# $Id: paypal_build_invoices,v 1.40 2012/10/03 14:29:07 gilles Exp gilles $
# usage: sh paypal_build_invoices /g/var/paypal_invoices/????
lyx -e latex /home/gilles/public_html/AGIL/factures/000/facture_imapsync-000.lyx
cp /home/gilles/public_html/AGIL/factures/000/facture_imapsync-000.tex /g/var/paypal_invoices/
set -x
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 147 /g/paypal/paypal_2010_11_complet.csv
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 214 /g/paypal/paypal_2010_12_complet.csv
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 294 /g/paypal/paypal_2011_01_complet.csv
@ -29,7 +28,10 @@ set -x
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 1654 /g/paypal/paypal_2012_05_complet.csv
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 1743 /g/paypal/paypal_2012_06_complet.csv
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 1824 /g/paypal/paypal_2012_07_complet.csv
/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 1891 /g/paypal/paypal_2012_08_complet.csv
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 1891 /g/paypal/paypal_2012_08_complet.csv
#/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 1963 /g/paypal/paypal_2012_09_complet.csv
/g/public_html/imapsync/W/paypal_reply/paypal_bilan --write_invoices --first_in 2047 /g/paypal/paypal_2012_10_complet.csv
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 147 /g/paypal/paypal_2010_11_complet.csv
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 214 /g/paypal/paypal_2010_12_complet.csv
@ -53,6 +55,9 @@ set -x
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 1743 /g/paypal/paypal_2012_06_complet.csv
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 1824 /g/paypal/paypal_2012_07_complet.csv
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 1891 /g/paypal/paypal_2012_08_complet.csv
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 1963 /g/paypal/paypal_2012_09_complet.csv
set -x
: /g/public_html/imapsync/W/paypal_reply/paypal_bilan --first_in 2047 /g/paypal/paypal_2012_10_complet.csv
set +x

View file

@ -1,5 +1,5 @@
REM $Id: test2.bat,v 1.10 2012/08/29 10:43:25 gilles Exp gilles $
REM $Id: test2.bat,v 1.11 2012/10/05 09:15:55 gilles Exp gilles $
cd C:\msys\1.0\home\Admin\imapsync
REM perl ./imapsync --host1 p --user1 tata --passfile1 secret.tata --host2 p --user2 titi --passfile2 secret.titi --delete2 --expunge2 --folder INBOX
@ -34,6 +34,10 @@ REM --host2 p --user2 titi --passfile2 secret.titi ^
REM --folder INBOX.useuid --useuid --debugcache --delete2
perl ./imapsync --host1 p --user1 tata --passfile1 secret.tata ^
--host2 imap.gmail.com --ssl2 --user2 gilles.lamiral@gmail.com --passfile2 secret.gilles_gmail ^
--usecache --nofoldersizes --folder INBOX --regextrans2 "s(INBOX)([Gmail]/te*st)"
REM perl ./imapsync --host1 p --user1 tata --passfile1 secret.tata ^
REM --host2 imap.gmail.com --ssl2 --user2 gilles.lamiral@gmail.com --passfile2 secret.gilles_gmail ^
REM --usecache --nofoldersizes --folder INBOX --regextrans2 "s(INBOX)([Gmail]/te*st)"
perl ./imapsync --host1 imap.gmail.com --port1 993 --ssl1 --host2 imap.bigs.dk --justconnect
imapsync.exe --host1 imap.gmail.com --port1 993 --ssl1 --host2 imap.bigs.dk --justconnect

319
imapsync
View file

@ -20,7 +20,7 @@ Synchronise mailboxes between two imap servers.
Good at IMAP migration. More than 44 different IMAP server softwares
supported with success.
$Revision: 1.508 $
$Revision: 1.516 $
=head1 SYNOPSIS
@ -106,7 +106,7 @@ The option list:
[--expunge] [--expunge1] [--expunge2] [--uidexpunge2]
[--delete2folders] [--delete2foldersonly] [--delete2foldersbutnot]
[--subscribed] [--subscribe] [--subscribe_all]
[--nofoldersizes]
[--nofoldersizes] [--nofoldersizesatend]
[--dry]
[--debug] [--debugimap][--debugimap1][--debugimap2]
[--timeout <int>] [--fast]
@ -403,7 +403,7 @@ Success stories reported with the following 44 imap servers
- Qualcomm Worldmail (NT)
- Rockliffe Mailsite 5.3.11, 4.5.6
- Samsung Contact IMAP server 8.5.0
- Scalix v10.1, 10.0.1.3, 11.0.0.431
- Scalix v10.1, 10.0.1.3, 11.0.0.431, 11.4.6
- SmarterMail, Smarter Mail 5.0 Enterprise, Smarter Mail 5.5 [host1].
- SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System)
- Sun Java(tm) System Messaging Server 6.2-2.05, 6.2-7.05, 6.3
@ -515,7 +515,7 @@ Entries for imapsync:
Feedback (good or bad) will often be welcome.
$Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $
$Id: imapsync,v 1.516 2012/11/02 22:15:04 gilles Exp gilles $
=cut
@ -559,9 +559,9 @@ use constant {
# global variables
my(
$rcs, $pidfile,
$rcs, $pidfile, $pidfilelocking,
$debug, $debugimap, $debugimap1, $debugimap2, $debugcontent, $debugflags,
$debugLIST, $debugsleep,
$debugLIST, $debugsleep, $debugdev,
$nb_errors,
$host1, $host2, $port1, $port2,
$user1, $user2, $domain1, $domain2,
@ -580,8 +580,8 @@ my(
$exitwhenover,
$search,
$skipheader, @useheader,
$skipsize, $allowsizemismatch, $foldersizes, $buffersize,
$delete, $delete2,
$skipsize, $allowsizemismatch, $foldersizes, $foldersizesatend, $buffersize,
$delete, $delete2, $delete2duplicates,
$expunge, $expunge1, $expunge2, $uidexpunge2, $dry,
$justfoldersizes,
$authmd5, $authmd51, $authmd52,
@ -609,6 +609,8 @@ my(
$h1_nb_msg_processed,
$h1_nb_msg_start, $h1_bytes_start,
$h2_nb_msg_start, $h2_bytes_start,
$h1_nb_msg_end, $h1_bytes_end,
$h2_nb_msg_end, $h2_bytes_end,
$timeout,
$timestart, $timestart_int, $timeend, $timediff,
@ -635,13 +637,16 @@ my(
%h1, %h2,
$checkselectable, $checkmessageexists,
$expungeaftereach,
$abletosearch,
$showpasswords,
$fixslash2,
);
# main program
# global variables initialisation
$rcs = '$Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $ ';
$rcs = '$Id: imapsync,v 1.516 2012/11/02 22:15:04 gilles Exp gilles $ ';
$total_bytes_transferred = 0;
$total_bytes_skipped = 0;
@ -658,6 +663,9 @@ $h1_nb_msg_start = $h1_bytes_start = 0 ;
$h2_nb_msg_start = $h2_bytes_start = 0 ;
$h1_nb_msg_processed = $h1_bytes_processed = 0 ;
$h1_nb_msg_end = $h1_bytes_end = 0 ;
$h2_nb_msg_end = $h2_bytes_end = 0 ;
$nb_errors = 0;
$max_msg_size_in_bytes = 0;
@ -682,26 +690,34 @@ unless(defined(&_SYSEXITS_H)) {
}
# @ARGV will be eat by get_options()
my @argv_copy = @ARGV;
get_options();
# $SIG{ INT } = \&catch_continue ;
$SIG{ INT } = \&catch_exit ;
$timestart = time( );
$timestart_int = int( $timestart ) ;
$timebefore = $timestart;
my $timestart_str = localtime( $timestart ) ;
print "Transfer started at $timestart_str\n";
$modules_version = defined($modules_version) ? $modules_version : 1;
# $SIG{ INT } = \&catch_continue ;
$releasecheck = defined($releasecheck) ? $releasecheck : 1;
my $warn_release = ($releasecheck) ? check_last_release() : '';
$SIG{ INT } = \&catch_exit ;
# default values
$tmpdir ||= File::Spec->tmpdir();
$pidfile ||= $tmpdir . '/imapsync.pid';
$pidfilelocking = defined( $pidfilelocking ) ? $pidfilelocking : 0 ;
# allow Mail::IMAPClient 3.0.xx by default
$allow3xx = defined($allow3xx) ? $allow3xx : 1;
@ -719,7 +735,8 @@ $relogin2 = defined( $relogin2 ) ? $relogin2 : 5 ;
if ( $fast ) {
# $useuid = 1 ;
$foldersizes = 0 ;
$foldersizes = 0 ;
$foldersizesatend = 0 ;
}
# Activate --usecache if --useuid is set and no --nousecache
@ -729,6 +746,11 @@ $cacheaftercopy = 1 if ( $usecache and ( ! defined( $cacheaftercopy ) ) ) ;
$checkselectable = defined( $checkselectable ) ? $checkselectable : 1 ;
$checkmessageexists = defined( $checkmessageexists ) ? $checkmessageexists : 1 ;
$expungeaftereach = defined( $expungeaftereach ) ? $expungeaftereach : 1 ;
$abletosearch = defined( $abletosearch ) ? $abletosearch : 1 ;
$showpasswords = defined( $showpasswords ) ? $showpasswords : 0 ;
$fixslash2 = defined( $fixslash2 ) ? $fixslash2 : 1 ;
$delete2duplicates = 1 if ( $delete2 and ( ! defined( $delete2duplicates ) ) ) ;
print banner_imapsync(@argv_copy);
@ -808,7 +830,7 @@ if ( $delete2 and ! defined( $uidexpunge2 ) ) {
}
if ( $delete and $delete2 ) {
print "Warning: using --delete and --delete2 is almost always a bad idea, exiting imapsync\n" ;
print "Warning: using --delete and --delete2 together is almost always a bad idea, exiting imapsync\n" ;
exit_clean( 4 ) ;
}
@ -863,6 +885,7 @@ print "Info: will try to use $authmech2 authentication on host2\n";
$syncacls = (defined($syncacls)) ? $syncacls : 0;
$foldersizes = (defined($foldersizes)) ? $foldersizes : 1;
$foldersizesatend = (defined($foldersizesatend)) ? $foldersizesatend : 1;
$fastio1 = (defined($fastio1)) ? $fastio1 : 0;
$fastio2 = (defined($fastio2)) ? $fastio2 : 0;
@ -904,9 +927,7 @@ $dry_message = "\t(not really since --dry mode)" if $dry ;
my $imap1 = ();
my $imap2 = ();
$timestart = time( );
$timestart_int = int( $timestart ) ;
$timebefore = $timestart;
$debugimap1 and print "Host1 connection\n";
$imap1 = login_imap($host1, $port1, $user1, $domain1, $password1,
@ -1041,6 +1062,13 @@ $h2_prefix = get_prefix($imap2, $prefix2, "--prefix2");
print "Host1 separator and prefix: [$h1_sep][$h1_prefix]\n";
print "Host2 separator and prefix: [$h2_sep][$h2_prefix]\n";
#my $h1_xlist_folders = $imap1->xlist_folders( ) ;
#my $h2_xlist_folders = $imap2->xlist_folders( ) ;
#require Data::Dumper ;
#print "Host1 xlist:\n", Data::Dumper->Dump([$h1_xlist_folders]) ;
#print "Host2 xlist:\n", Data::Dumper->Dump([$h2_xlist_folders]) ;
#exit ;
foreach my $h1_fold (@h1_folders_wanted) {
my $h2_fold;
@ -1215,8 +1243,13 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
@$h1_fir_ref{@h1_msgs} = (undef);
$debug and print "Host1 getting flags idate and sizes of folder [$h1_fold]\n" ;
$h1_fir_ref = $imap1->fetch_hash("FLAGS", "INTERNALDATE", "RFC822.SIZE", $h1_fir_ref)
if (@h1_msgs);
if ( $abletosearch ) {
$h1_fir_ref = $imap1->fetch_hash( "FLAGS", "INTERNALDATE", "RFC822.SIZE", $h1_fir_ref )
if ( @h1_msgs ) ;
}else{
$h1_fir_ref = $imap1->fetch_hash( '1:999999', "FLAGS", "INTERNALDATE", "RFC822.SIZE", $h1_fir_ref )
if ( @h1_msgs ) ;
}
$debug and print "Host1 getting flags idate and sizes of folder [$h1_fold] took ", timenext(), " s\n";
unless ($h1_fir_ref) {
print
@ -1282,7 +1315,8 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
my $h2_msgs_duplicate_nb = scalar( @h2_msgs_duplicate ) ;
$h2{ $h2_fold }{ 'duplicates_nb' } = $h2_msgs_duplicate_nb ;
$debug and print "Host2 selected: $h2_msgs_nb duplicates: $h2_msgs_duplicate_nb\n" ;
print "Host2 selected: $h2_msgs_nb, duplicates: $h2_msgs_duplicate_nb\n"
if ( $debug or $delete2duplicates or $h2_msgs_duplicate_nb ) ;
$debug and print "Host2 whole time parsing headers took ", timenext(), " s\n";
$debug and print "++++ Verifying [$h1_fold] -> [$h2_fold]\n";
@ -1310,6 +1344,29 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
}
#next FOLDER ;
if( $delete2duplicates ) {
my @h2_expunge ;
foreach my $h2_msg ( @h2_msgs_duplicate ) {
print "msg $h2_fold/$h2_msg marked \\Deleted [duplicate] on host2 $dry_message\n" ;
push( @h2_expunge, $h2_msg ) if $uidexpunge2 ;
unless ( $dry ) {
$imap2->delete_message( $h2_msg ) ;
$h2_nb_msg_deleted += 1 ;
}
}
my $cnt = scalar @h2_expunge ;
if( @h2_expunge ) {
print "uidexpunge $cnt message(s) $dry_message\n" ;
$imap2->uidexpunge( \@h2_expunge ) if ! $dry ;
}
if ( $expunge2 ){
print "Expunging host2 folder $h2_fold $dry_message\n" ;
$imap2->expunge( ) if ! $dry ;
}
}
if($delete2) {
my @h2_expunge;
foreach my $m_id (@h2_hash_keys_sorted_by_uid) {
@ -1318,7 +1375,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
my $h2_msg = $h2_hash{$m_id}{'m'};
my $h2_flags = $h2_hash{$m_id}{'F'} || "";
my $isdel = $h2_flags =~ /\B\\Deleted\b/ ? 1 : 0;
print "msg $h2_fold/$h2_msg marked \\Deleted on host2 [$m_id]\n"
print "msg $h2_fold/$h2_msg marked \\Deleted on host2 [$m_id] $dry_message\n"
if ! $isdel;
push(@h2_expunge, $h2_msg) if $uidexpunge2;
unless ($dry or $isdel) {
@ -1327,16 +1384,8 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
}
}
}
foreach my $h2_msg (@h2_msgs_duplicate) {
print "msg $h2_fold/$h2_msg marked \\Deleted [duplicate] on host2\n";
push(@h2_expunge, $h2_msg) if $uidexpunge2;
unless ($dry) {
$imap2->delete_message($h2_msg);
$h2_nb_msg_deleted += 1;
}
}
foreach my $h2_msg ( @h2_msgs_delete2_not_in_cache ) {
print "msg $h2_fold/$h2_msg marked \\Deleted [not in cache] on host2\n";
print "msg $h2_fold/$h2_msg marked \\Deleted [not in cache] on host2 $dry_message\n";
push(@h2_expunge, $h2_msg) if $uidexpunge2;
unless ($dry) {
$imap2->delete_message($h2_msg);
@ -1345,7 +1394,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
}
my $cnt = scalar @h2_expunge ;
if( @h2_expunge ) {
print "uidexpunge $cnt message(s)\n" ;
print "uidexpunge $cnt message(s) $dry_message\n" ;
$imap2->uidexpunge( \@h2_expunge ) if ! $dry ;
}
if ($expunge2){
@ -1508,14 +1557,17 @@ sub sync_flags {
print "++++ End looping on each folder\n";
#print memory_consumption();
if ( $foldersizesatend ) {
( $h1_nb_msg_end, $h1_bytes_end ) = foldersizes( "Host1", $imap1, @h1_folders_wanted ) ;
( $h2_nb_msg_end, $h2_bytes_end ) = foldersizes( "Host2", $imap2, @h2_folders_from_1_wanted ) ;
}
$imap1->logout();
$imap2->logout();
$imap1->logout( ) ;
$imap2->logout( ) ;
stats();
exit_clean(1) if( $nb_errors );
exit_clean(0);
stats( ) ;
exit_clean( 1 ) if ( $nb_errors ) ;
exit_clean( 0 ) ;
# END of main program
@ -1596,6 +1648,8 @@ Authen::NTLM))
sub command_line_nopassword {
my @argv_copy = @_;
my @argv_nopassword;
return("@argv_copy") if $showpasswords ;
while (@argv_copy) {
my $arg = shift(@argv_copy); # option name or value
if ($arg =~ m/-password[12]/) {
@ -1616,7 +1670,13 @@ sub tests_command_line_nopassword {
ok('--password1 MASKED' eq command_line_nopassword(qw{ --password1 secret1}), 'command_line_nopassword --password1');
ok('--blabla --password1 MASKED --blibli'
eq command_line_nopassword(qw{ --blabla --password1 secret1 --blibli }), 'command_line_nopassword --password1 --blibli');
$showpasswords = 1 ;
ok('' eq command_line_nopassword(), 'command_line_nopassword void');
ok('--blabla' eq command_line_nopassword('--blabla'), 'command_line_nopassword --blabla');
#print command_line_nopassword((qw{ --password1 secret1 })), "\n";
ok('--password1 secret1' eq command_line_nopassword(qw{ --password1 secret1}), 'command_line_nopassword --password1');
ok('--blabla --password1 secret1 --blibli'
eq command_line_nopassword(qw{ --blabla --password1 secret1 --blibli }), 'command_line_nopassword --password1 --blibli');
}
@ -1635,7 +1695,7 @@ sub catch_exit {
my $signame = shift ;
print "\nGot a SIG$signame!\n" ;
stats( ) ;
exit_clean( ) ;
exit_clean( 6 ) ;
}
sub catch_continue {
@ -1877,7 +1937,7 @@ sub login_imap {
$imap->Authuser($authuser);
$imap->Password($password);
}
unless ( $authmech eq 'PREAUTH' or $imap->login( ) ) {
my $info = "Failure: error login on [$host] with user [$user] auth" ;
my $einfo = $imap->LastError || @{$imap->History}[-1] ;
@ -1923,8 +1983,8 @@ sub banner_imapsync {
my @argv_copy = @_;
my $banner_imapsync = join("",
'$RCSfile: imapsync,v $ ',
'$Revision: 1.508 $ ',
'$Date: 2012/09/10 21:10:13 $ ',
'$Revision: 1.516 $ ',
'$Date: 2012/11/02 22:15:04 $ ',
"\n",localhost_info(), "\n",
"Command line used:\n",
"$0 ", command_line_nopassword(@argv_copy), "\n",
@ -1941,35 +2001,38 @@ sub is_valid_directory {
}
sub write_pidfile {
my $pidfile = shift;
sub write_pidfile {
my $pidfile = shift ;
print "PID file is $pidfile\n";
if (-e $pidfile) {
print "$pidfile already exists, overwriting it\n";
}
open(PIDFILE, ">$pidfile") or do {
print "Could not open $pidfile for writing";
return undef;
};
print "PID file is $pidfile\n" ;
if ( -e $pidfile and $pidfilelocking ) {
print "$pidfile already exists, another imapsync may be curently running. Aborting imapsync.\n" ;
exit( 8 ) ;
}
if ( -e $pidfile ) {
print "$pidfile already exists, overwriting it\n" ;
}
open( PIDFILE, ">$pidfile" ) or do {
print "Could not open $pidfile for writing" ;
return undef ;
} ;
print PIDFILE $PROCESS_ID;
close PIDFILE;
return($PROCESS_ID);
}
print PIDFILE $PROCESS_ID ;
close PIDFILE ;
return( $PROCESS_ID ) ;
}
sub exit_clean {
my $status = shift;
my $status = shift ;
$status = defined( $status ) ? $status : 1 ;
unlink($pidfile);
exit($status);
unlink( $pidfile ) ;
exit( $status ) ;
}
sub die_clean {
unlink($pidfile);
die @_;
}
sub die_clean {
unlink( $pidfile ) ;
die @_ ;
}
sub missing_option {
my ($option) = @_;
@ -2251,18 +2314,19 @@ sub folders_list_to_help {
}
sub separator_invert {
# The separator we hope we'll never encounter: 00000000
my $o_sep="\000";
sub separator_invert {
# The separator we hope we'll never encounter: 00000000
my $o_sep="\000" ;
my($h1_fold, $h1_sep, $h2_sep) = @_;
my($h1_fold, $h1_sep, $h2_sep) = @_ ;
my $h2_fold = $h1_fold;
$h2_fold =~ s@\Q$h2_sep@$o_sep@g;
$h2_fold =~ s@\Q$h1_sep@$h2_sep@g;
$h2_fold =~ s@\Q$o_sep@$h1_sep@g;
return($h2_fold);
}
my $h2_fold = $h1_fold ;
$h2_fold =~ s@\Q$h2_sep@$o_sep@g ;
$h2_fold =~ s@\Q$h1_sep@$h2_sep@g ;
$h2_fold =~ s@\Q$o_sep@$h1_sep@g ;
$h2_fold =~ s,/,_,g if( $fixslash2 and '/' ne $h2_sep and '/' eq $h1_sep ) ;
return( $h2_fold ) ;
}
sub tests_imap2_folder_name {
@ -2278,6 +2342,7 @@ sep1:[$h1_sep]
sep2:[$h2_sep]
";
$fixslash2 = 0 ;
ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string');
ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla');
ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam');
@ -2297,6 +2362,22 @@ ok('bla_bla' eq imap2_folder_name('bla bla'), 'imap2_folder_name: blabla [s, ,_,
@regextrans2 = ('s,(.*),\U$1,');
ok('BLABLA' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s,\U(.*)\E,$1,]');
$fixslash2 = 1 ;
@regextrans2 = ( ) ;
ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string');
ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla');
ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam -> spam.spam');
ok('spam_spam' eq imap2_folder_name('spam.spam'), 'imap2_folder_name: spam.spam -> spam_spam');
ok('spam.spam_spam' eq imap2_folder_name('spam/spam.spam'), 'imap2_folder_name: spam/spam.spam -> spam.spam_spam');
$h1_sep = '.';
$h2_sep = '/';
ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string');
ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla');
ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam -> spam.spam');
ok('spam/spam' eq imap2_folder_name('spam.spam'), 'imap2_folder_name: spam.spam -> spam/spam');
ok('spam.spam/spam' eq imap2_folder_name('spam/spam.spam'), 'imap2_folder_name: spam/spam.spam -> spam.spam/spam');
}
@ -2359,7 +2440,11 @@ sub foldersizes {
my $smax = 0 ;
@$hash_ref{ @msgs } = ( undef ) if @msgs ;
if ( $nb_msgs > 0 and @msgs ) {
$imap->fetch_hash("RFC822.SIZE",$hash_ref) or die_clean("$@") ;
if ( $abletosearch ) {
$imap->fetch_hash( "RFC822.SIZE", $hash_ref) or die_clean("$@" ) ;
}else{
$imap->fetch_hash( '1:999999', "RFC822.SIZE", $hash_ref ) or die_clean( "$@" ) ;
}
#print map {$hash_ref->{$_}->{"RFC822.SIZE"}, " "} keys %$hash_ref ;
map { $stot += $hash_ref->{ $_ }->{ "RFC822.SIZE" } } keys %$hash_ref ;
$smax = max( map { $hash_ref->{ $_ }->{ "RFC822.SIZE" } } keys %$hash_ref ) ;
@ -2647,7 +2732,15 @@ sub select_msgs {
if ( defined( $msgs_all_hash_ref )
or ( ! defined( $maxage ) and ! defined( $minage ) and ! defined( $search ) )
) {
@msgs = $imap->messages() ;
if ( $abletosearch ) {
$debugdev and print "Calling messages()\n" ;
@msgs = $imap->messages() ;
}else{
$debugdev and print "Calling fetch_hash()\n" ;
@msgs = sort { $a <=> $b } keys( %{$imap->fetch_hash( '1:999999', "RFC822.SIZE")} ) ;
}
$debugdev and print "Done fetch_hash()\n" ;
if ( defined( $msgs_all_hash_ref ) ) {
@msgs_all = @msgs ;
@{ $msgs_all_hash_ref }{ @msgs_all } = () ;
@ -3474,38 +3567,37 @@ sub regexmess {
return($string);
}
sub bytes_display_string {
my ($bytes) = @_;
sub bytes_display_string {
my ( $bytes ) = @_ ;
if ($bytes < (1024 * 1024)) {
return sprintf("%.2f KiB", $bytes / 1024);
} elsif ($bytes < (1024 * 1024 * 1024)) {
return sprintf("%.2f MiB", $bytes / (1024 * 1024));
} elsif ($bytes < (1024 * 1024 * 1024 * 1024)) {
return sprintf("%.2f GiB", $bytes / (1024 * 1024 * 1024));
} elsif ($bytes < (1024 * 1024 * 1024 * 1024 * 1024)) {
return sprintf("%.2f TiB", $bytes / (1024 * 1024 * 1024 * 1024));
} else {
return sprintf("%.2f PiB", $bytes / (1024 * 1024 * 1024 * 1024 * 1024));
}
if ( abs( $bytes ) < ( 1024 * 1024 ) ) {
return sprintf( "%.2f KiB", $bytes / 1024) ;
} elsif ( abs( $bytes ) < ( 1024 * 1024 * 1024 ) ) {
return sprintf( "%.2f MiB", $bytes / (1024 * 1024) ) ;
} elsif ( abs( $bytes ) < ( 1024 * 1024 * 1024 * 1024) ) {
return sprintf("%.2f GiB", $bytes / (1024 * 1024 * 1024) ) ;
} elsif ( abs( $bytes ) < ( 1024 * 1024 * 1024 * 1024 * 1024) ) {
return sprintf( "%.2f TiB", $bytes / (1024 * 1024 * 1024 * 1024) ) ;
} else {
return sprintf( "%.2f PiB", $bytes / (1024 * 1024 * 1024 * 1024 * 1024) ) ;
}
# if you have exabytes (EiB) of email to transfer, you have too much email
}
sub stats {
$timeend = time();
$timediff = $timeend - $timestart;
$timeend = time( );
$timediff = $timeend - $timestart ;
my $timestart_str = localtime( $timestart ) ;
my $timeend_str = localtime( $timeend ) ;
my $memory_consumption = memory_consumption( ) || 0 ;
my $memory_ratio = ($max_msg_size_in_bytes) ?
sprintf('%.1f', $memory_consumption / $max_msg_size_in_bytes) : "NA";
sprintf('%.1f', $memory_consumption / $max_msg_size_in_bytes) : "NA" ;
my $host1_reconnect_count = $imap1->Reconnect_counter() || 0;
my $host2_reconnect_count = $imap2->Reconnect_counter() || 0;
my $host1_reconnect_count = $imap1->Reconnect_counter() || 0 ;
my $host2_reconnect_count = $imap2->Reconnect_counter() || 0 ;
print "++++ Statistics\n";
print "++++ Statistics\n" ;
print "Transfer started on : $timestart_str\n";
print "Transfer ended on : $timeend_str\n";
printf( "Transfer time : %.1f sec\n", $timediff ) ;
@ -3542,9 +3634,17 @@ sub stats {
printf ("Memory consumption : %.1f MiB\n", $memory_consumption / 1024 / 1024);
print "Biggest message : $max_msg_size_in_bytes bytes\n";
# print "Memory/biggest message ratio : $memory_ratio\n";
print "Detected $nb_errors errors\n\n";
if ( $foldersizesatend and $foldersizes ) {
printf("Initial difference host2 - host1 : %s messages, %s bytes (%s)\n", $h2_nb_msg_start - $h1_nb_msg_start,
$h2_bytes_start - $h1_bytes_start,
bytes_display_string( $h2_bytes_start - $h1_bytes_start ) ) ;
printf("Final difference host2 - host1 : %s messages, %s bytes (%s)\n", $h2_nb_msg_end - $h1_nb_msg_end,
$h2_bytes_end - $h1_bytes_end,
bytes_display_string( $h2_bytes_end - $h1_bytes_end ) ) ;
}
print "Detected $nb_errors errors\n\n" ;
print $warn_release, "\n";
print $warn_release, "\n" ;
print thank_author();
}
@ -3579,6 +3679,7 @@ sub get_options {
"debugimap!" => \$debugimap,
"debugimap1!" => \$debugimap1,
"debugimap2!" => \$debugimap2,
"debugdev!" => \$debugdev,
"host1=s" => \$host1,
"host2=s" => \$host2,
"port1=i" => \$port1,
@ -3602,6 +3703,7 @@ sub get_options {
"exclude=s" => \@exclude,
"prefix1=s" => \$prefix1,
"prefix2=s" => \$prefix2,
"fixslash2!" => \$fixslash2,
"regextrans2=s" => \@regextrans2,
"regexmess=s" => \@regexmess,
"regexflag=s" => \@regexflag,
@ -3609,6 +3711,7 @@ sub get_options {
"flagsCase!" => \$flagsCase,
"delete!" => \$delete,
"delete2!" => \$delete2,
"delete2duplicates!" => \$delete2duplicates,
"delete2folders!" => \$delete2folders,
"delete2foldersonly=s" => \$delete2foldersonly,
"delete2foldersbutnot=s" => \$delete2foldersbutnot,
@ -3621,6 +3724,7 @@ sub get_options {
"minage=i" => \$minage,
"search=s" => \$search,
"foldersizes!" => \$foldersizes,
"foldersizesatend!" => \$foldersizesatend,
"dry!" => \$dry,
"expunge!" => \$expunge,
"expunge1!" => \$expunge1,
@ -3669,6 +3773,7 @@ sub get_options {
"justlogin!" => \$justlogin,
"tmpdir=s" => \$tmpdir,
"pidfile=s" => \$pidfile,
"pidfilelocking!" => \$pidfilelocking,
"releasecheck!" => \$releasecheck,
"modules_version!" => \$modules_version,
"usecache!" => \$usecache,
@ -3680,6 +3785,8 @@ sub get_options {
"checkselectable!" => \$checkselectable,
"checkmessageexists!" => \$checkmessageexists,
"expungeaftereach!" => \$expungeaftereach,
"abletosearch!" => \$abletosearch,
"showpasswords!" => \$showpasswords,
);
$debug and print "get options: [$opt_ret]\n";
@ -3869,7 +3976,7 @@ sub check_last_release {
}
sub imapsync_version {
my $rcs = '$Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $ ';
my $rcs = '$Id: imapsync,v 1.516 2012/11/02 22:15:04 gilles Exp gilles $ ';
$rcs =~ m/,v (\d+\.\d+)/;
my $VERSION = ($1) ? $1: "UNKNOWN";
return($VERSION);
@ -3993,6 +4100,8 @@ Several options are mandatory.
Required by Sun/iPlanet/Netscape IMAP servers to
be able to use an administrative user
--password1 <string> : password for the user1. Dangerous, use --passfile1
--showpasswords : shows passwords on output instead of "MASKED".
Useful to restart a complete run by just reading a log.
--passfile1 <string> : password file for the user1. Contains the password.
--host2 <string> : "destination" imap server. Mandatory.
--port2 <int> : port to connect on host2. Default is 143.
@ -4029,6 +4138,8 @@ Several options are mandatory.
Will be created if it doesn't exist.
Default is system specific and should be ok.
--pidfile <string> : the file where imapsync pid is written.
--pidfilelocking : Abort if pidfile already exists. Usefull to avoid
concurrent transfers on the same mailbox.
--prefix1 <string> : remove prefix to all destination folders
(usually INBOX. for cyrus imap servers)
you can use --prefix1 if your source imap server
@ -4058,6 +4169,9 @@ Several options are mandatory.
they are really deleted unless --noexpunge is used.
--delete2 : delete messages in host2 that are not in
host1 server. Useful for backup or pre-sync.
--delete2duplicates : delete messages in host2 that are duplicates.
Works only without --useuid since duplicates are
detected with header part of each message.
--delete2folders : Delete folders in host2 that are not in host1 server.
For safety, first try it like this (it is safe):
--delete2folders --dry --justfolders --nofoldersizes
@ -4105,6 +4219,8 @@ Several options are mandatory.
host2 even if they are not subscribed on host1.
--nofoldersizes : Do not calculate the size of each folder in bytes
and message counts. Default is to calculate them.
--nofoldersizesatend : Do not calculate the size of each folder in bytes
and message counts at the end. Default is on.
--justfoldersizes : exit after printed the folder sizes.
--syncacls : synchronises acls (Access Control Lists).
--nosyncacls : does not synchronise acls. This is the default.
@ -4668,7 +4784,7 @@ sub tests_debug {
SKIP: {
skip "No test in normal run" if ( not $tests_debug );
tests_time_remaining( ) ;
tests_imap2_folder_name( ) ;
}
}
@ -4708,6 +4824,7 @@ sub tests {
tests_cache_dir_fix( ) ;
tests_filter_forbidden_characters( ) ;
tests_cache_folder( ) ;
tests_time_remaining( ) ;
}
}

View file

@ -5,7 +5,7 @@
<title>Imapsync: an IMAP migration tool ( release <!--#exec cmd="cat ./VERSION"--> )</title>
<meta name="generator" content="Bluefish 1.0.7"/>
<meta name="author" content="Gilles LAMIRAL"/>
<meta name="date" content="2012-09-12T00:06:47+0200"/>
<meta name="date" content="2012-11-02T19:33:22+0100"/>
<meta name="copyright" content="None"/>
<meta name="keywords" content="imap, transfert, migration"/>
<meta name="description" content="imap migration tool"/>
@ -46,7 +46,9 @@
<p><b>imapsync</b> software is a command line tool allowing incremental and
recursive <b>IMAP</b> transfers from one mailbox to another, both anywhere on the internet
or in your local network. "Incremental" means you can stop the transfer at any time
and restart it later efficiently. "Recursive" means all folders hierarchy can be copied.
and restart it later efficiently. "Recursive" means all folders hierarchy can be copied.
"Command line" means it's not a graphical tool, imapsync on Windows has to be run in a DOS box
(cmd.exe) or from a <a href="#DOC_BASIC">batch file</a>.
</p>
<p><b>imapsync</b> is useful for imap account <b>migration</b> or imap account <b>backup</b>.
@ -95,7 +97,7 @@ total is 93 millions for 2011</li>
<p>New features or bugfixes since previous releases:</p>
<!-- <ul>
<li><b>1.508</b></li>
<li><b>1.515</b></li>
<li><b>Enhancement</b>: </li>
<li><b>Enhancement</b>: </li>
<li><b>Enhancement</b>: </li>
@ -111,12 +113,50 @@ total is 93 millions for 2011</li>
</ul>
-->
<ul>
<li><b>1.516</b></li>
<li><b>Usability</b>: Added <b>host2 minus host1 statistic</b>: number of messages and bytes.
One difference at the start and one at the end.
Useful to <b>detect quickly a difference between host2 and host1</b>.
Need both --foldersizes and --foldersizesatend options (which are on by default).</li>
<li><b>Usability</b>: Added <b>--foldersizesatend</b>. It gets the folders sizes at the end of the whole transfer.
Turned on by default (use --nofoldersizesatend to turn it off).</li>
<li><b>Enhancement</b>: Added option <b>--delete2duplicates</b>; it deletes messages in host2 that are duplicates.
--delete2duplicates is on when --delete2 is set unless --nodelete2duplicates is set too.
</li>
<li><b>Usability</b>: Added <b>current date at the beginning</b> of the run,
useful when imapsync doesn't end properly or hasn't finished yet.</li>
<li><b>Enhancement</b>: Added option <b>--pidfilelocking</b>; it aborts imapsync, when just launched,
in case another imapsync may be running.
Turned off by default</li>
<li><b>Usability</b>: Added option <b>--showpasswords</b>. it shows passwords on output instead of "MASKED".
Turned off by default.
Useful to restart a run by reading the log or to see what happen with special characters.
</li>
<li><b>Bug fix</b>: Added option <b>--fixslash2</b> to avoid the '<b>Invalid mailbox name</b>' error.
It acts when --sep2 is not character / and --sep1 is character / and host1 folder name contains --sep2 characters.
Turned on by default (--nofixslash2 to unable it).</li>
<li><b>Enhancement</b>: Added option <b>--noabletosearch</b> to allow the listing of messages without the imap "SEARCH ALL" command.
It's useful for playing with poor imap servers like <b>Softalk 7.6.4</b> (8.6 is fine with SEARCH ALL).</li>
</ul>
<ul>
<li><b>1.508</b></li>
<li><b>Usability</b>: imapsync guesses and <b>prints when it'll finish</b> the transfer; added <b>ETA</b> after each copy (Estimated Time of Arrival)</li>
<li><b>Enhancement</b>: Added <b>--noexpungeaftereach</b> to speedup --delete --expunge from Gmail.</li>
<li><b>Usability</b>: Added Host1 or Host2 before "Nb messages" "Total size" with --foldersiszes (to facilitate parsing)</li>
<li><b>Bug fix</b>: Previous fix about characters *|?:"<> in cache path was not complete.</li>
<li><b>Bug fix</b>: Previous fix about characters <kbd>*|?:"&lt;&gt;</kbd> to <kbd>_</kbd> in cache path was not complete.</li>
</ul>
@ -213,7 +253,7 @@ any Unix, Linux, Windows, or Mac OS operating system.
</p>
<p>
<b>+ One year</b> of imapsync <b>updates</b> without extra payment.<br/>
<b>+ Two years</b> of imapsync <b>updates</b> without extra payment.<br/>
<b>+ 30 days money-back guarantee!</b> (any reason qualifies)<br/>
</p>
@ -234,7 +274,7 @@ Price <b>42 EUR</b> is equal to around <b>50 USD</b>, no problem to pay in USD (
</select>
<br/>
<input type="hidden" name="on1" value="VAT if professional in Europe"/>
Enter your <b>VAT</b> <input type="text" name="os1" size="13" maxlength="13"/> <b> if you're a European professional</b> (for accounting). It's 2 letters followed by 11 digits, for example mine is FR74429303332.
Enter your <b>VAT</b> <input type="text" name="os1" size="17" maxlength="17"/> <b> if you're a European professional</b> (for accounting). It's 2 letters followed by 11 digits, for example mine is FR74429303332.
<br/>
<input type="hidden" name="currency_code" value="EUR"/>
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif"
@ -259,7 +299,7 @@ buying the latest win32 <b>standalone imapsync.exe</b> for <b>42 EUR</b>
</p>
<p>
<b>+ One year</b> of imapsync <b>updates</b> without extra payment.<br/>
<b>+ Two years</b> of imapsync <b>updates</b> without extra payment.<br/>
<b>+ 30 days money-back guarantee!</b> (any reason qualifies)<br/>
</p>
@ -279,7 +319,7 @@ Price <b>42 EUR</b> is equal to around <b>50 USD</b>, no problem to pay in USD (
</select>
<br/>
<input type="hidden" name="on1" value="VAT if professional in Europe"/>
Enter your <b>VAT</b> <input type="text" name="os1" size="13" maxlength="13"/> <b> if you're a European professional</b> (for accounting). It's 2 letters followed by 11 digits, for example mine is FR74429303332.
Enter your <b>VAT</b> <input type="text" name="os1" size="17" maxlength="17"/> <b> if you're a European professional</b> (for accounting). It's 2 letters followed by 11 digits, for example mine is FR74429303332.
<br/>
<input type="hidden" name="currency_code" value="EUR"/>
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif"
@ -324,7 +364,7 @@ Payment by Paypal account and credit card accepted. <br/>
</select>
<br/>
<input type="hidden" name="on1" value="VAT if professional in Europe"/>
Enter your <b>VAT</b> <input type="text" name="os1" size="13" maxlength="13"/> <b> if you're a European professional</b> (for accounting). It's 2 letters followed by 11 digits, for example mine is FR74429303332.
Enter your <b>VAT</b> <input type="text" name="os1" size="17" maxlength="17"/> <b> if you're a European professional</b> (for accounting). It's 2 letters followed by 11 digits, for example mine is FR74429303332.
<br/>
<input type="hidden" name="currency_code" value="EUR"/>
<input type="image"
@ -341,7 +381,7 @@ Please give a <b>delivery postal address where the invoice will be needed</b> (y
since reedit is not easy (and forbidden by law).
</p>
<h2>Documentation</h2>
<h2><a id="doc"></a>Documentation</h2>
<p>Read the <a href="INSTALL">INSTALL</a> file to know how to install imapsync on your system.
</p>
@ -497,7 +537,7 @@ Don't hesitate to have a try, I will help you and make efforts to switch them to
<li>Qualcomm Worldmail (NT) (<a href="http://www.eudora.com/worldmail/">http://www.eudora.com/worldmail/</a>) </li>
<li>Rockliffe Mailsite 5.3.11, 4.5.6 (<a href="http://www.mailsite.com/">http://www.mailsite.com/</a>) </li>
<li>Samsung Contact IMAP server 8.5.0 </li>
<li>Scalix v10.1, 10.0.1.3, 11.0.0.431 (<a href="http://www.scalix.com/">http://www.scalix.com/</a>) </li>
<li>Scalix v10.1, 10.0.1.3, 11.0.0.431, 11.4.6 (<a href="http://www.scalix.com/">http://www.scalix.com/</a>) </li>
<li>SmarterMail, Smarter Mail 5.0 Enterprise, Smarter Mail 5.5 [host1]. (<a href="http://www.smartertools.com/">http://www.smartertools.com/</a>) </li>
<li>SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System) (<a href="http://www.oracle.com/">http://www.oracle.com/</a>) </li>
<li>Sun Java(tm) System Messaging Server 6.2-2.05, 6.2-7.05, 6.3 (<a href="http://www.oracle.com/">http://www.oracle.com/</a>) </li>
@ -576,7 +616,7 @@ alt="Viewable With Any Browser" />
<!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: index.shtml,v 1.131 2012/09/11 22:07:18 gilles Exp gilles $)
($Id: index.shtml,v 1.136 2012/11/03 00:46:00 gilles Exp gilles $)
</p>
</body>

133
tests.sh
View file

@ -1,6 +1,6 @@
#!/bin/sh
# $Id: tests.sh,v 1.201 2012/09/10 21:12:35 gilles Exp gilles $
# $Id: tests.sh,v 1.205 2012/11/03 00:38:15 gilles Exp gilles $
# Example 1:
# CMD_PERL='perl -I./Mail-IMAPClient-3.32/lib' sh -x tests.sh
@ -49,7 +49,7 @@ run_test() {
if test x"$?" = x"0"; then
echo "$1 passed"
else
echo "$1 failed" >&2
echo "$1 failed"
fi
}
@ -145,6 +145,10 @@ passwords_masked() {
$CMD_PERL ./imapsync --host1 boumboum --password1 secret --justbanner | grep MASKED
}
passwords_not_masked() {
$CMD_PERL ./imapsync --host1 boumboum --password1 secret --justbanner --showpasswords| grep secret
}
first_sync_dry() {
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 toto \
@ -165,7 +169,7 @@ first_sync() {
locallocal() {
can_send && sendtestmessage
#can_send && sendtestmessage
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
@ -194,6 +198,34 @@ pidfile() {
! test -f /var/tmp/imapsync.pid
}
ll_pidfilelocking() {
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--folder INBOX --pidfile /var/tmp/imapsync_test_pidfilelocking.pid \
--pidfilelocking --justconnect
echo "Exited $?"
! test -f /var/tmp/imapsync_test_pidfilelocking.pid
touch /var/tmp/imapsync_test_pidfilelocking.pid
if $CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--folder INBOX --pidfile /var/tmp/imapsync_test_pidfilelocking.pid \
--pidfilelocking --justconnect; then
echo "Exited $?"; ! :
else
echo "Exited $?"
fi
test -f /var/tmp/imapsync_test_pidfilelocking.pid
rm /var/tmp/imapsync_test_pidfilelocking.pid
}
justbanner() {
$CMD_PERL ./imapsync \
--justbanner
@ -887,6 +919,17 @@ ll_maxage_nonew()
}
ll_nosearch_hack()
{
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--folder INBOX.few_emails --debugdev --debugimap1 --noabletosearch
}
ll_newmessage()
{
can_send && sendtestmessage
@ -1070,7 +1113,7 @@ ll_regextrans2()
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--justfolders \
--nofoldersize \
--nofoldersizes \
--regextrans2 's/yop/yoX/' \
--folder 'INBOX.yop.yap'
}
@ -1087,7 +1130,7 @@ ll_regextrans2_downcase()
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--justfolders \
--nofoldersize \
--nofoldersizes \
--regextrans2 's/(.*)\Q${h1_sep}\E(.+)$/$1${h2_sep}\L$2\E/' \
--folder 'INBOX.yop.YAP' --justfolders --debug --dry
}
@ -1104,7 +1147,7 @@ ll_regextrans2_ucfirst()
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--justfolders \
--nofoldersize \
--nofoldersizes \
--regextrans2 's/(.*)\Q${h1_sep}\E(.)(.+)$/$1${h2_sep}\u$2\L$3\E/' \
--folder 'INBOX.yop.YAP' --justfolders --debug --dry
}
@ -1118,7 +1161,7 @@ ll_regextrans2_slash()
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--justfolders \
--nofoldersize \
--nofoldersizes \
--folder 'INBOX.yop.yap' \
--sep1 '/' \
--regextrans2 's,/,_,'
@ -1133,7 +1176,7 @@ ll_regextrans2_subfolder()
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--justfolders \
--nofoldersize \
--nofoldersizes \
--folder 'INBOX.yop.yap' \
--prefix1 'INBOX.yop.' \
--regextrans2 's,^${h2_prefix}(.*),${h2_prefix}FOO${h2_sep}$1,' --dry
@ -1149,7 +1192,7 @@ ll_regextrans2_remove_space()
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--justfolders \
--nofoldersize \
--nofoldersizes \
--folder 'INBOX.yop.y p' \
--regextrans2 's, ,,' \
--dry
@ -1171,7 +1214,7 @@ ll_regextrans2_archive_per_month()
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--nofoldersize \
--nofoldersizes \
--search "SENTSINCE 1-$month-$year SENTBEFORE 30-$month-$year" \
--regextrans2 "s{.*}{INBOX.Archive.$year.$month_n}"
}
@ -1647,6 +1690,17 @@ ll_delete2_uidexpunge2_implicit() {
}
ll_delete2duplicates() {
can_send && sendtestmessage titi
can_send && sendtestmessage tata
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--folder INBOX \
--delete2duplicates --uidexpunge2
}
ll_delete2_dev() {
@ -1898,6 +1952,22 @@ xxxxx_gmail_7() {
}
xxxxx_gmail_8_xlist() {
! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \
--host1 $HOST2 \
--user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 imap.gmail.com \
--ssl2 \
--user2 gilles.lamiral@gmail.com \
--passfile2 ../../var/pass/secret.gilles_gmail \
--foldersizes \
--folder INBOX
}
gmail_xxxxx() {
! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \
@ -2180,24 +2250,26 @@ ll_nousecache() {
--folder INBOX
}
ll_useuid_usecache()
{
ll_usecache_INBOX() {
if can_send; then
sendtestmessage
else
:
fi
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--folder INBOX \
--delete2 --expunge2 \
--useuid
echo 'rm /home/vmail/titi/.yop.yap/cur/*'
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--usecache --foldersizes \
--folder INBOX
}
ll_usecache_noheader() {
if can_send; then
sendtestmessage
@ -2246,6 +2318,23 @@ ll_usecache_debugcache_useuid() {
--folder INBOX --useheader '' --debugcache --useuid
}
ll_useuid_usecache()
{
if can_send; then
sendtestmessage
else
:
fi
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 tata \
--passfile1 ../../var/pass/secret.tata \
--host2 $HOST2 --user2 titi \
--passfile2 ../../var/pass/secret.titi \
--folder INBOX \
--delete2 --expunge2 \
--useuid
echo 'rm /home/vmail/titi/.yop.yap/cur/*'
}
ll_useuid()
{
@ -2885,10 +2974,12 @@ option_tests
option_tests_debug
option_bad_delete2
passwords_masked
passwords_not_masked
first_sync_dry
first_sync
locallocal
pidfile
ll_pidfilelocking
justbanner
nomodules_version
xxxxx_gmail